diff --git a/AGENTS.md b/AGENTS.md index 162678f2..5365f6f3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,10 +18,10 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - `bun scripts/cli.ts server start`:以异步 job 启动 database、backend-core、frontend、provider-gateway 和主 server 用户服务,部署规则见 `docs/reference/deployment.md`。 - `bun scripts/cli.ts server status`:查询固定端口、容器状态、健康检查和访问 URL,判定标准见 `docs/reference/deployment.md`。 - `bun scripts/cli.ts server logs`:分页返回文件日志与 Docker 日志尾部,日志规则见 `docs/reference/observability.md`。 -- `bun scripts/cli.ts server rebuild `:以 build-first、Compose lock、no-deps force-recreate 和 post-up validation 的异步 job 重建单个服务,规则见 `docs/reference/deployment.md`。 +- `bun scripts/cli.ts server rebuild `:以 build-first、Compose lock、no-deps force-recreate 和 post-up validation 的异步 job 重建主 server Compose 内单个服务;Code Queue 部署在 D601,规则见 `docs/reference/deployment.md`。 - `bun scripts/cli.ts provider attach [--master-server URL] [--up] [--force]`:在新增计算节点上生成两项配置的 provider-gateway 挂载包;默认只需要主 server URL(默认 `http://74.48.78.17/`)和唯一 Provider ID,生成的 Compose 固定 Docker socket、`pid: "host"`、`restart: always`、只读 `/workspace` 与 SSH 维护私钥挂载,规则见 `docs/reference/provider-gateway.md`。 - `bun scripts/cli.ts ssh [ssh-like args...]`:通过 provider-gateway 的 Host SSH / WSL SSH 维护桥打开近似原生 ssh 的交互会话或远端命令,并在远端 PATH 注入 `apply_patch`、`glob` 与 `skill-discover`;`apply-patch`、`py`、`skills`、结构化 `find`、`glob` 和 `argv` 子命令用于避免远端补丁、Python stdin、skill 发现与常用只读命令的嵌套转义问题,使用规则见 `docs/reference/cli.md` 和 `docs/reference/provider-gateway.md`。 -- `bun scripts/cli.ts microservice list/status/health/proxy`:管理和验证挂载在主 server 或计算节点 Docker 中的用户服务,OA Event Flow/Code Queue/Todo Note/Baidu Netdisk on main-server 与 FindJob/Pipeline/MET Nonlinear on D601 的规则见 `docs/reference/microservices.md`。 +- `bun scripts/cli.ts microservice list/status/health/proxy`:管理和验证挂载在主 server 或计算节点 Docker 中的用户服务,OA Event Flow/Todo Note/Baidu Netdisk on main-server 与 Code Queue/FindJob/Pipeline/MET Nonlinear on D601 的规则见 `docs/reference/microservices.md`。 - `bun scripts/cli.ts codex task `:按 Code Queue 任务 ID 查询初始 prompt、最后 assistant message、工具调用摘要、attempt/judge/error 和耗时,便于新任务引用历史 session。 - `bun scripts/cli.ts codex judge --attempt [--dry-run]`:按指定 task/attempt 用与队列 worker 相同的上下文构建和 MiniMax judge 调用路径单步复现完成判定;`--dry-run` 只输出 prompt/payload 诊断。 - `bun scripts/cli.ts server stop`:以异步 job 停止固定 Compose 项目中的全部 UniDesk 服务,停止后用 `server status` 复核。 @@ -32,7 +32,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 ## Runtime - `bun`:TypeScript 运行时固定使用 Bun,组件入口和 CLI 都直接运行 `.ts` 文件,约束见 `docs/reference/config.md`。 -- `docker-compose.yml`:主 server 统一编排 core、frontend、database、本机 provider gateway、Todo Note 后端、Baidu Netdisk 后端、Code Queue 后端和 OA Event Flow 后端,且只公开 frontend/provider ingress,服务拓扑见 `docs/reference/deployment.md`。 +- `docker-compose.yml`:主 server 统一编排 core、frontend、database、本机 provider gateway、Todo Note 后端、Baidu Netdisk 后端和 OA Event Flow 后端;Code Queue 使用 D601 Compose 部署并通过 provider-gateway 私有代理接入,服务拓扑见 `docs/reference/deployment.md`。 - `src/components/frontend`:前端源码固定使用 TypeScript + React,`app.tsx` 只做 shell/router,左侧主模块与顶部子标签统一编译为模块前缀路由:`/ops//`、`/nodes//`、`/tasks//`、`/config//`,只有用户服务使用 `/app//` 深链接,运行总览包含通用性能面板,资源监控含曲线和进程资源排序表,Todo Note、FindJob、Pipeline、MET Nonlinear、Baidu Netdisk、Code Queue、OA Event Flow 等业务页必须拆到独立 TSX 模块,界面规则见 `docs/reference/frontend.md`。 - `backend-core / frontend performance`:backend-core 暴露 `/api/performance`,frontend 暴露同源 `/api/frontend-performance` 并在 `/ops/performance/` 汇总组件请求、失败请求、内部操作和慢操作,规则见 `docs/reference/observability.md`。 - `Unified OA event flow`:`oa-event-flow` 是独立主 server 用户服务,提供事件表、按 tag 订阅和 Trace/STEP 统计中心,Code Queue 与 Pipeline 都必须接入统一事件流;共享契约见 `docs/reference/oa-event-flow.md`,Pipeline 专有控制流规则见 `docs/reference/pipeline-oa-event-flow.md`。 diff --git a/TEST.md b/TEST.md index dde998f0..93821954 100644 --- a/TEST.md +++ b/TEST.md @@ -10,7 +10,7 @@ ## T3 主 server 自接入 Provider Gateway -阅读 `AGENTS.md`(本项目 `AGENTS.md` 同时承担 `SKILL.md` 对 `scripts/cli.ts` 的解释职责),然后用 cli 手动测试以下内容:运行 `bun scripts/cli.ts server status` 和 `bun scripts/cli.ts debug health`,确认公网只监听 frontend 与 provider ingress,backend-core 和 database 显示为 Docker 内部端口,`/api/nodes` 中存在 `main-server` provider,状态为 `online`,`/api/nodes/system-status` 中存在 CPU/内存/硬盘采样,`/api/nodes/docker-status` 中存在 `main-server` 的 Docker 快照,且 provider 标签中能看到 Docker socket 可用性。 +阅读 `AGENTS.md`(本项目 `AGENTS.md` 同时承担 `SKILL.md` 对 `scripts/cli.ts` 的解释职责),然后用 cli 手动测试以下内容:运行 `bun scripts/cli.ts server status` 和 `bun scripts/cli.ts debug health`,确认面向浏览器的公网入口只有 frontend 与 provider ingress,backend-core 显示为 Docker 内部端口,database/OA Event Flow 若因 D601 Code Queue 映射宿主端口也必须显示为受限宿主端口,且 `network.restrictedHostAccess.allowedSourceCidrs` 已生成来源限制,`/api/nodes` 中存在 `main-server` provider,状态为 `online`,`/api/nodes/system-status` 中存在 CPU/内存/硬盘采样,`/api/nodes/docker-status` 中存在 `main-server` 的 Docker 快照,且 provider 标签中能看到 Docker socket 可用性。 ## T4 前端控制台连通 @@ -26,7 +26,7 @@ ## T7 停止与端口释放 -阅读 `AGENTS.md`(本项目 `AGENTS.md` 同时承担 `SKILL.md` 对 `scripts/cli.ts` 的解释职责),然后用 cli 手动测试以下内容:运行 `bun scripts/cli.ts server stop`,确认立即返回 job id;等待 `bun scripts/cli.ts job status latest` 成功后运行 `bun scripts/cli.ts server status`,确认 frontend 与 provider ingress 公网端口不再监听,backend-core 与 database 没有宿主机端口映射,容器状态不再运行。 +阅读 `AGENTS.md`(本项目 `AGENTS.md` 同时承担 `SKILL.md` 对 `scripts/cli.ts` 的解释职责),然后用 cli 手动测试以下内容:运行 `bun scripts/cli.ts server stop`,确认立即返回 job id;等待 `bun scripts/cli.ts job status latest` 成功后运行 `bun scripts/cli.ts server status`,确认 frontend 与 provider ingress 公网端口不再监听,backend-core 没有宿主机端口映射,database 的受限映射不再可用,容器状态不再运行。 ## Issue 记录 @@ -97,9 +97,11 @@ 阅读 `AGENTS.md`(本项目 `AGENTS.md` 同时承担 `SKILL.md` 对 `scripts/cli.ts` 的解释职责),然后用 cli 手动测试以下内容:确认 D518 `/mnt/d/work/todo_note` 已复制到主 server `/root/todo_note`,运行 `bun scripts/cli.ts microservice list`,确认 `todo-note` 显示为 `providerId=main-server`、`public=false`、`frontendOnly=true`、仓库 URL `https://gitee.com/Lyon1998/todo_note`、`todo-note:4211` 后端映射和 `todo-note-backend` 容器摘要;运行 `bun scripts/cli.ts microservice health todo-note`,确认返回 `storage=postgres`;运行 `bun scripts/cli.ts microservice proxy todo-note /api/instances --max-body-bytes 8000`,确认能看到 `CONSTAR`、`大论文`、`找工作`、`小论文`、`事务` 五个迁移清单,总任务数不低于 100。随后通过 backend-core 或 `bun scripts/cli.ts e2e run` 执行临时清单 create/add/toggle/undo/delete 写入循环,确认 Todo Note 写入真实经过 backend-core、main-server provider-gateway、`todo-note-backend` 和主 PostgreSQL,且删除前必须按唯一临时清单名称重新选中临时清单,不能误删迁移清单。最后登录公网 frontend `http://74.48.78.17:18081/`,进入 `用户服务 / Todo Note`,确认清单、树形任务、筛选、提醒、移动、撤销/重做、字号控制都以 React 控件展示,默认没有裸 JSON,只有点击 `查看原始JSON` 才显示原始数据。 -## T23 Main Server Code Queue User Service +## T23 D601 Code Queue User Service -阅读 `AGENTS.md`(本项目 `AGENTS.md` 同时承担 `SKILL.md` 对 `scripts/cli.ts` 的解释职责),然后用 cli 手动测试以下内容:运行 `bun scripts/cli.ts microservice list`,确认 `code-queue` 显示为 `providerId=main-server`、`public=false`、`frontendOnly=true`、仓库 URL `https://github.com/pikasTech/unidesk`、`code-queue:4222` 后端映射和 `code-queue-backend` 容器摘要;运行 `bun scripts/cli.ts server rebuild code-queue` 并用 `bun scripts/cli.ts job status ` 等待该 job 成功且输出 post-up validation,再运行 `bun scripts/cli.ts microservice health code-queue`、`bun scripts/cli.ts microservice proxy code-queue /api/dev-ready --raw`、`bun scripts/cli.ts microservice proxy code-queue /api/tasks` 和 `bun scripts/cli.ts codex task <已有taskId>`,确认链路通过 backend-core、main-server provider-gateway 和 Code Queue 后端,且 task id 查询返回初始 prompt、最后 assistant message、工具调用摘要、attempt/judge/error 和耗时,且 `queue.devReady.ok=true`、`devReady.missingTools=[]`、`docker.versionOk=true`、`docker.composeOk=true`,必需工具包含 `docker`、`docker-compose`、`jq`、`ssh`、`rsync`、`pip3` 和 `unzip`;提交会产生较多命令输出的小任务后,`/health` 和 `/api/tasks` 仍必须在常规 CLI 超时内返回,容器内不得堆积无超时 healthcheck 进程。运行 `bun scripts/cli.ts microservice proxy code-queue /api/dev-containers/D601/start --method POST --raw`(或等价同源 POST),确认 Code Queue 拉起 D601 `unidesk-codex-dev-D601` 开发容器,返回 JSON 中 `masterProxy.mode=ssh-tun-nat`、`verification.pingGoogleOk=true`、`directPingEvidence` 表明建隧道前直连失败、`pingGoogleLog` 包含 `PING google.com` 和 `0% packet loss`,且 `masterProxyEvidenceAfter` 中 `UNIDESK-CODEX-DEV-D601` NAT 链或 `tun601` 计数比 ping 前增长,证明开发容器网络经 master server 全局代理而不是 D601 本地出网。再用 `bun scripts/cli.ts microservice proxy code-queue /api/tasks --raw` 确认返回的 `queue.executionProviders` 至少包含 `main-server` 和 `D601`,`main-server` 的 `defaultWorkdir=/root/unidesk`,`D601` 的 `defaultWorkdir=/home/ubuntu`,并且 `queue.executionModes` 包含 `windows-native`;通过 API 提交任务时 `providerId=main-server` 必须在本机容器执行,`providerId=D601` 必须自动复用/拉起 D601 开发容器并在任务 JSON、Trace summary 和日志中显示 `providerId=D601`、`cwd=/home/ubuntu`;通过 API 或前端提交 `providerId=D601`、`executionMode=windows-native`、`model=gpt-5.4-mini`、`cwd=/mnt/f/Work/ConStart` 的小任务,必须显示 `executionMode=windows-native`,且 Trace 中的 Codex initialize/userAgent 证明 Codex 运行在 Windows 原生环境。随后登录公网 frontend `http://74.48.78.17:18081/`,进入 `用户服务 / Code Queue`,确认页面显示默认模型 `gpt-5.5`、默认执行 Provider `main-server`、默认工作目录 `/root/unidesk`、Provider 下拉菜单包含 `D601 · /home/ubuntu`、模型下拉菜单包含 `gpt-5.4-mini`/`gpt-5.4`/`gpt-5.5`、入队份数、队列指标、任务 ID、复制任务 ID、引用按钮、任务耗时、引用任务 ID、清空输入、创建成功提示、任务提交表单、Codex CLI-like 输出、attempt 表、MiniMax/fallback judge 状态、追加 prompt、打断和重试控件;通过页面提交一个小任务,确认任务进入 queued/running/succeeded 或可解释的 failed 状态,并且输出区能看到运行中的 Codex 消息。批量验收时设置 `入队份数=5` 或用 `---` 分隔 5 段 prompt,一次性入队 5 条任务,确认 5 条任务按顺序运行并全部进入 succeeded 或可解释的非成功终态,不能只运行第一条后停止;其中任一任务被 judge 判定 `fail` 时只能把当前任务标为 failed,后续 queued 任务仍必须继续推进。测试异常中断时可以提交长任务后点击 `打断`,确认任务变为 canceled 或被 judge 标记为非成功终态;自动重试只应在服务端/传输异常、任务正常结束但 execution record 显示未完成、或 judge 判定 retry 时发生;retry 必须复用已有 Codex thread 并 append 继续执行 prompt,只有当前任务 complete 后才推进队列中的下一个任务。MiniMax judge 必须能处理 Markdown fence/夹杂文本等 JSON 去噪;若去噪后仍失败,必须把解析错误和上一轮去噪前原始回答反馈给 MiniMax 修复后重试,日志中应出现 `judge_json_parse_retry`,且 repair 成功时仍以 `source=minimax` 返回。Codex provider key 只能通过 `OPENAI_API_KEY`、`CRS_OAI_KEY` 这类运行时环境透传,MiniMax API key 只能通过 `UNIDESK_CODE_QUEUE_MINIMAX_API_KEY` 这类运行时环境传入,禁止写入 `config.json`、Dockerfile、源码或测试文档。 +阅读 `AGENTS.md`(本项目 `AGENTS.md` 同时承担 `SKILL.md` 对 `scripts/cli.ts` 的解释职责),然后用 cli 手动测试以下内容:运行 `bun scripts/cli.ts microservice list`,确认 `code-queue` 显示为 `providerId=D601`、`public=false`、`frontendOnly=true`、仓库 URL `https://github.com/pikasTech/unidesk`、D601 本机 `127.0.0.1:4222` 后端映射和 D601 `code-queue-backend` 容器摘要;在 D601 上使用 `src/components/microservices/code-queue/docker-compose.d601.yml` 重建/启动 Code Queue,并确认主 server 根目录 `docker-compose.yml` 中不再存在 `code-queue` service。运行 `bun scripts/cli.ts microservice health code-queue`、`bun scripts/cli.ts microservice proxy code-queue /api/dev-ready --raw`、`bun scripts/cli.ts microservice proxy code-queue /api/tasks` 和 `bun scripts/cli.ts codex task <已有taskId>`,确认链路通过 backend-core、D601 provider-gateway 和 D601 Code Queue 后端,且 task id 查询返回初始 prompt、最后 assistant message、工具调用摘要、attempt/judge/error 和耗时,`queue.storage.primary=postgres`、`queue.storage.postgresReady=true`、`queue.devReady.missingTools=[]`、`queue.devReady.docker.versionOk=true`、`queue.devReady.docker.composeOk=true`;`queue.devReady.ssh.ready` 只在需要跨 Provider SSH/Windows-native 任务时作为强制项。在 D601 `code-queue-backend` 容器内验证主 PostgreSQL 端口映射可执行 `select 1`,主 OA Event Flow 端口映射 `/health` 可访问,本机 ClaudeQQ `http://host.docker.internal:3290/health` 可访问;这些映射不得成为任意公网入口。 + +随后登录公网 frontend `http://74.48.78.17:18081/`,进入 `用户服务 / Code Queue`,确认页面显示默认模型 `gpt-5.5`、默认执行 Provider `D601`、默认工作目录 `/workspace`、模型下拉菜单包含 `gpt-5.4-mini`/`gpt-5.4`/`gpt-5.5`、入队份数、队列指标、任务 ID、复制任务 ID、引用按钮、任务耗时、引用任务 ID、清空输入、创建成功提示、任务提交表单、Trace 输出、attempt 表、MiniMax/fallback judge 状态、追加 prompt、打断和重试控件;通过页面提交一个小任务,确认任务进入 queued/running/succeeded 或可解释的 failed 状态,并且输出区能看到运行中的 Codex 消息。批量验收时设置 `入队份数=5` 或用 `---` 分隔 5 段 prompt,一次性入队 5 条任务,确认 5 条任务按顺序运行并全部进入 succeeded 或可解释的非成功终态,不能只运行第一条后停止;其中任一任务被 judge 判定 `fail` 时只能把当前任务标为 failed,后续 queued 任务仍必须继续推进。测试异常中断时可以提交长任务后点击 `打断`,确认任务变为 canceled 或被 judge 标记为非成功终态;自动重试只应在服务端/传输异常、任务正常结束但 execution record 显示未完成、或 judge 判定 retry 时发生;retry 必须复用已有 Codex thread 并 append 继续执行 prompt,只有当前任务 complete 后才推进队列中的下一个任务。MiniMax judge 必须能处理 Markdown fence/夹杂文本等 JSON 去噪;若去噪后仍失败,必须把解析错误和上一轮去噪前原始回答反馈给 MiniMax 修复后重试,日志中应出现 `judge_json_parse_retry`,且 repair 成功时仍以 `source=minimax` 返回。Codex provider key 只能通过 `OPENAI_API_KEY`、`CRS_OAI_KEY` 这类运行时环境透传,MiniMax API key 只能通过 D601 env-file 运行时环境传入,禁止写入 `config.json`、Dockerfile、源码或测试文档。 ## T24 MET Nonlinear D601 GPU User Service diff --git a/config.json b/config.json index a63749c4..8cd0dba6 100644 --- a/config.json +++ b/config.json @@ -25,6 +25,12 @@ "providerIngress": { "port": 18082, "containerPort": 8081 + }, + "restrictedHostAccess": { + "bindHost": "0.0.0.0", + "allowedSourceCidrs": [ + "36.49.30.105/32" + ] } }, "database": { @@ -499,19 +505,19 @@ { "id": "code-queue", "name": "Code Queue", - "providerId": "main-server", - "description": "Code Queue 是主 server 承载的平台无关代码代理队列用户服务,通过 port 层适配 Codex 与 OpenCode,用于串行任务队列、运行中输出、追加 prompt、打断会话、异常中断判定和自动重试。", + "providerId": "D601", + "description": "Code Queue 是部署在 D601 的平台无关代码代理队列用户服务,通过 D601 本机端口、主 PostgreSQL 端口映射和 OA/ClaudeQQ 私有链路提供串行任务队列、运行中输出、追加 prompt、打断会话、异常中断判定和自动重试。", "repository": { "url": "https://github.com/pikasTech/unidesk", - "commitId": "2aaf0447a62c336f3a488d77516edbf05ff1d742", + "commitId": "cbbed004a6c84a7dbc554bb90692bd80b4384e67", "dockerfile": "src/components/microservices/code-queue/Dockerfile", - "composeFile": "docker-compose.yml", + "composeFile": "src/components/microservices/code-queue/docker-compose.d601.yml", "composeService": "code-queue", "containerName": "code-queue-backend" }, "backend": { - "nodeBaseUrl": "http://code-queue:4222", - "nodeBindHost": "code-queue", + "nodeBaseUrl": "http://host.docker.internal:4222", + "nodeBindHost": "127.0.0.1", "nodePort": 4222, "proxyMode": "provider-gateway-http", "frontendOnly": true, @@ -532,9 +538,9 @@ "timeoutMs": 30000 }, "development": { - "providerId": "main-server", + "providerId": "D601", "sshPassthrough": true, - "worktreePath": "/root/unidesk" + "worktreePath": "/home/ubuntu/unidesk-code-queue-deploy" }, "frontend": { "route": "/apps/code-queue", diff --git a/docker-compose.yml b/docker-compose.yml index b53f61fa..eae3a63f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,8 @@ services: restart: unless-stopped expose: - "5432" + ports: + - "${UNIDESK_DATABASE_BIND_HOST}:${UNIDESK_DATABASE_PORT}:5432" environment: POSTGRES_USER: "${UNIDESK_DATABASE_USER}" POSTGRES_PASSWORD: "${UNIDESK_DATABASE_PASSWORD}" @@ -107,87 +109,6 @@ services: timeout: 3s retries: 20 - code-queue: - build: - context: . - dockerfile: src/components/microservices/code-queue/Dockerfile - container_name: code-queue-backend - restart: unless-stopped - mem_limit: "${UNIDESK_CODE_QUEUE_MEM_LIMIT:-1200m}" - memswap_limit: "${UNIDESK_CODE_QUEUE_MEMSWAP_LIMIT:-1800m}" - depends_on: - - database - - backend-core - - oa-event-flow - expose: - - "4222" - environment: - HOST: "0.0.0.0" - PORT: "4222" - DATABASE_URL: "postgres://${UNIDESK_DATABASE_USER}:${UNIDESK_DATABASE_PASSWORD}@database:5432/${UNIDESK_DATABASE_NAME}" - CODE_QUEUE_DATA_DIR: "/var/lib/unidesk/code-queue" - CODE_QUEUE_WORKDIR: "/root/unidesk" - CODE_QUEUE_CODEX_HOME: "/var/lib/unidesk/code-queue/codex-home" - CODE_QUEUE_OPENCODE_XDG_DIR: "/var/lib/unidesk/code-queue/opencode-xdg" - CODE_QUEUE_SOURCE_CODEX_CONFIG: "/root/.codex/config.toml" - CODE_QUEUE_DEFAULT_MODEL: "gpt-5.5" - CODE_QUEUE_MODELS: "gpt-5.5,gpt-5.4-mini,gpt-5.4,minimax-m2.7" - CODE_QUEUE_MODEL_REASONING_EFFORTS: "gpt-5.5=xhigh" - CODE_QUEUE_SANDBOX: "danger-full-access" - CODE_QUEUE_APPROVAL_POLICY: "never" - OA_EVENT_FLOW_BASE_URL: "http://oa-event-flow:4255" - CODE_QUEUE_MAX_ATTEMPTS: "99" - CODE_QUEUE_MAX_ACTIVE_QUEUES: "${UNIDESK_CODE_QUEUE_MAX_ACTIVE_QUEUES:-0}" - NODE_OPTIONS: "${UNIDESK_CODE_QUEUE_NODE_OPTIONS:---max-old-space-size=512}" - CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS: "${UNIDESK_CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS:-10}" - CODE_QUEUE_IN_MEMORY_EVENT_RECORDS: "${UNIDESK_CODE_QUEUE_IN_MEMORY_EVENT_RECORDS:-10}" - CODE_QUEUE_CODEX_SQLITE_LOG_EXPORT_BATCH_SIZE: "${UNIDESK_CODE_QUEUE_CODEX_SQLITE_LOG_EXPORT_BATCH_SIZE:-500}" - CODE_QUEUE_MAIN_PROVIDER_ID: "main-server" - CODE_QUEUE_REMOTE_WORKDIR: "${UNIDESK_CODE_QUEUE_REMOTE_WORKDIR:-/home/ubuntu}" - CODE_QUEUE_EXECUTION_PROVIDER_IDS: "${UNIDESK_CODE_QUEUE_EXECUTION_PROVIDER_IDS:-D601}" - CODE_QUEUE_DEV_CONTAINER_MASTER_HOST: "${UNIDESK_PUBLIC_HOST}" - CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID: "${UNIDESK_CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID:-D601}" - CODE_QUEUE_DEV_CONTAINER_IMAGE: "${UNIDESK_CODE_QUEUE_DEV_CONTAINER_IMAGE:-}" - CODE_QUEUE_DEV_CONTAINER_WORKDIR: "${UNIDESK_CODE_QUEUE_DEV_CONTAINER_WORKDIR:-/home/ubuntu}" - CODE_QUEUE_WINDOWS_NATIVE_CODEX_DEFAULT_WORKDIR: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_DEFAULT_WORKDIR:-/mnt/f/Work/ConStart}" - CODE_QUEUE_WINDOWS_NATIVE_CODEX_BRIDGE_DIR: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_BRIDGE_DIR:-/home/ubuntu/.unidesk/code-queue/windows-native-codex}" - CODE_QUEUE_WINDOWS_NATIVE_CODEX_COMMAND: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_COMMAND:-codex app-server --listen stdio://}" - CODE_QUEUE_WINDOWS_NATIVE_CODEX_CONNECT_HOST: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_CONNECT_HOST:-host.docker.internal}" - CODE_QUEUE_WINDOWS_NATIVE_CODEX_IDLE_TIMEOUT_MS: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_IDLE_TIMEOUT_MS:-600000}" - CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED:-true}" - CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL:-http://backend-core:8080/api/microservices/claudeqq/proxy}" - CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE:-private}" - CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID:-645275593}" - CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID:-}" - CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS:-12000}" - CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS:-15000}" - CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS:-3}" - OPENAI_API_KEY: "${OPENAI_API_KEY:-}" - CRS_OAI_KEY: "${CRS_OAI_KEY:-}" - MINIMAX_API_KEY: "${UNIDESK_CODE_QUEUE_MINIMAX_API_KEY:-}" - MINIMAX_API_BASE: "${UNIDESK_CODE_QUEUE_MINIMAX_API_BASE:-https://api.minimaxi.com/v1}" - MINIMAX_MODEL: "${UNIDESK_CODE_QUEUE_MINIMAX_MODEL:-MiniMax-M2.7}" - MINIMAX_JUDGE_TIMEOUT_MS: "${UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_TIMEOUT_MS:-90000}" - MINIMAX_JUDGE_REPAIR_ATTEMPTS: "${UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_REPAIR_ATTEMPTS:-2}" - LOG_FILE: "/var/log/unidesk/${UNIDESK_LOG_DAY}/${UNIDESK_LOG_PREFIX}_code-queue.jsonl" - UNIDESK_LOG_RETENTION_BYTES: "${UNIDESK_LOG_RETENTION_BYTES:-1GiB}" - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - .:/root/unidesk - - .:/workspace - - /root/.codex/config.toml:/root/.codex/config.toml:ro - - ${UNIDESK_HOST_ROOT_SSH_DIR:-/root/.ssh}:/root/.ssh:ro - - ${UNIDESK_LOG_DIR}:/var/log/unidesk - - ./.state/code-queue:/var/lib/unidesk/code-queue - extra_hosts: - - "host.docker.internal:host-gateway" - healthcheck: - test: ["CMD-SHELL", "curl -fsS --max-time 2 http://127.0.0.1:4222/health >/dev/null"] - interval: 5s - timeout: 3s - retries: 20 - - oa-event-flow: image: oa-event-flow build: @@ -200,6 +121,8 @@ services: - backend-core expose: - "4255" + ports: + - "${UNIDESK_OA_EVENT_FLOW_BIND_HOST}:${UNIDESK_OA_EVENT_FLOW_PORT}:4255" environment: HOST: "0.0.0.0" PORT: "4255" diff --git a/docs/reference/cli.md b/docs/reference/cli.md index cc3869d1..4dd17dfc 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -10,9 +10,9 @@ UniDesk 的统一 CLI 入口是根目录 `scripts/cli.ts`,运行方式固定 - `check` 执行配置校验、文件存在性检查、`scripts/` TypeScript 检查、`src/components/` TypeScript 检查和 Docker Compose 配置检查。 - `server start` 创建异步 job,在后台执行 Docker 构建和启动;命令本身只负责返回 job id、日志路径和启动命令。 - `server stop` 创建异步 job,在后台停止固定 Compose project 中的全部 UniDesk 服务。 -- `server status` 查询公开端口、内部端口、Compose 容器、core/frontend/provider/database 健康检查和访问 URL。 +- `server status` 查询公开端口、受限宿主端口、内部端口、Compose 容器、core/frontend/provider/database 健康检查和访问 URL;D601 Code Queue 使用的 PostgreSQL/OA Event Flow host mapping 必须出现在受限宿主端口而不是无条件公开入口中。 - `server logs` 返回 `logs/` 文件日志和 Docker 容器日志的尾部,默认限制输出大小,避免日志爆炸。 -- `server rebuild ` 创建异步 job,先构建目标服务镜像,随后在 `.state/locks/server-compose.lock` 串行保护下用 `--no-deps --force-recreate` 替换目标 service 并等待容器 `healthy/running`;该命令用于替代手工删除容器的兜底流程,其中 `todo-note`、`code-queue`、`project-manager` 和 `baidu-netdisk` 只重建主 server 承载的对应后端,不会重建或删除 database 命名卷。 +- `server rebuild ` 创建异步 job,先构建目标服务镜像,随后在 `.state/locks/server-compose.lock` 串行保护下用 `--no-deps --force-recreate` 替换目标 service 并等待容器 `healthy/running`;该命令用于替代手工删除容器的兜底流程,其中 `todo-note`、`project-manager`、`baidu-netdisk` 和 `oa-event-flow` 只重建主 server 承载的对应后端,不会重建或删除 database 命名卷。Code Queue 部署在 D601,不再由 `server rebuild` 管理。 - `provider attach [--master-server URL] [--up] [--force]` 在新计算节点生成两项配置的 provider-gateway 挂载包:`.state/provider-.env` 默认只包含 `UNIDESK_MASTER_SERVER` 与 `PROVIDER_ID`,`provider-.yml` 固定 Docker socket、`pid: "host"`、`restart: always`、只读 `/workspace` 和 SSH 维护私钥挂载;`--up` 会立即执行生成的 `docker compose up -d --build`。 - `ssh [ssh-like args...]` 通过 backend-core 内网 WebSocket broker 和 provider-gateway 的 Host SSH / WSL SSH 维护桥连接目标节点;无后续参数时进入远端登录 shell,有后续参数时按 ssh 远端命令体验执行并返回远端 exit code。 - `ssh apply-patch [tool args...] < patch.diff` 直接调用远端注入的 `apply_patch` 工具,并把本地 stdin 中的标准 `*** Begin Patch` / `*** End Patch` patch 流透传给目标节点。 @@ -32,7 +32,7 @@ UniDesk 的统一 CLI 入口是根目录 `scripts/cli.ts`,运行方式固定 长时操作采用 Fire-and-Forget 模式:CLI 创建 `.state/jobs/{jobId}.json`,后台进程执行真实命令,并将 stdout、stderr 分别写入 `.state/jobs/{jobId}.stdout.log` 与 `.state/jobs/{jobId}.stderr.log`。调用者通过 `bun scripts/cli.ts job status ` 查询进度和尾部输出。 -`server rebuild` 与 `server start`、`server stop` 一样必须通过返回的 job id 确认结果;不要把 `server rebuild code-queue && server rebuild frontend` 理解成“前一个重建已完成”,因为两个命令只是在快速创建异步 job。重建 frontend 的标准流程是运行 `bun scripts/cli.ts server rebuild frontend`,随后轮询 `bun scripts/cli.ts job status ` 到 `succeeded`,再用 `server status` 或 `e2e run` 验证公网 frontend;重建 Todo Note 后端使用 `bun scripts/cli.ts server rebuild todo-note`,随后用 `microservice health todo-note` 和 `microservice proxy todo-note /api/instances` 验证;重建 Code Queue 后端使用 `bun scripts/cli.ts server rebuild code-queue`,随后用 `microservice health code-queue` 和 `microservice proxy code-queue /api/tasks` 验证;重建 Project Manager 后端使用 `bun scripts/cli.ts server rebuild project-manager`,随后用 `microservice health project-manager` 和 `microservice proxy project-manager /api/projects` 验证;重建 Baidu Netdisk 后端使用 `bun scripts/cli.ts server rebuild baidu-netdisk`,随后用 `microservice health baidu-netdisk` 和 `microservice proxy baidu-netdisk /api/transfers` 验证;重建 main server File Browser 使用 `bun scripts/cli.ts server rebuild filebrowser`,随后用 `microservice health filebrowser` 和 `microservice proxy filebrowser / --max-body-bytes 2000` 验证。不得把 `docker rm` 手工兜底当成正式交付步骤。 +`server rebuild` 与 `server start`、`server stop` 一样必须通过返回的 job id 确认结果;不要把连续 `server rebuild` 命令理解成“前一个重建已完成”,因为两个命令只是在快速创建异步 job。重建 frontend 的标准流程是运行 `bun scripts/cli.ts server rebuild frontend`,随后轮询 `bun scripts/cli.ts job status ` 到 `succeeded`,再用 `server status` 或 `e2e run` 验证公网 frontend;重建 Todo Note 后端使用 `bun scripts/cli.ts server rebuild todo-note`,随后用 `microservice health todo-note` 和 `microservice proxy todo-note /api/instances` 验证;重建 Project Manager 后端使用 `bun scripts/cli.ts server rebuild project-manager`,随后用 `microservice health project-manager` 和 `microservice proxy project-manager /api/projects` 验证;重建 Baidu Netdisk 后端使用 `bun scripts/cli.ts server rebuild baidu-netdisk`,随后用 `microservice health baidu-netdisk` 和 `microservice proxy baidu-netdisk /api/transfers` 验证;重建 OA Event Flow 后端使用 `bun scripts/cli.ts server rebuild oa-event-flow`,随后用 `microservice health oa-event-flow` 和 `microservice proxy oa-event-flow /api/diagnostics` 验证。Code Queue 后端在 D601 用 `src/components/microservices/code-queue/docker-compose.d601.yml` 重建,再用 `microservice health code-queue` 和 `microservice proxy code-queue /api/tasks` 验证。不得把 `docker rm` 手工兜底当成正式交付步骤。 ## Output Contract diff --git a/docs/reference/config.md b/docs/reference/config.md index db4e692e..95ff1f5e 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -8,7 +8,7 @@ TypeScript 运行时固定为 Bun。根目录 CLI、backend-core、frontend 和 ## Network Ports -`config.json` 中保留 core、frontend、database 和 providerIngress 的端口字段,但只有 frontend 与 providerIngress 允许映射到宿主机公网端口。core 和 database 的 `port` 字段用于测试公网阻断和历史兼容,实际服务只使用 Docker 内网 `containerPort`。 +`config.json` 中保留 core、frontend、database 和 providerIngress 的端口字段。frontend 与 providerIngress 是面向浏览器/Provider 的公开入口;core 不允许映射公网。database 的 `port` 字段用于 D601 Code Queue 的受限 PostgreSQL 端口映射和公网阻断测试,必须配合 `network.restrictedHostAccess` 的来源白名单限制到 D601 出口地址,不能作为任意公网数据库入口。 ## Auth @@ -26,11 +26,11 @@ TypeScript 运行时固定为 Bun。根目录 CLI、backend-core、frontend 和 `microservices` 定义挂载在计算节点或主 server Docker 中的非核心用户服务。用户服务是挂在 UniDesk 核心服务上的用户业务能力,缺少这些服务时 UniDesk 核心仍必须能运行。该数组只保存业务仓库 URL、commit id、业务仓库自身 Dockerfile/docker-compose 引用、provider 映射、节点后端端口和 UniDesk frontend 集成入口;不得把业务全量代码复制进 UniDesk。`backend.public` 必须为 `false`,`backend.frontendOnly` 必须为 `true`,`backend.allowedPathPrefixes` 必须限制到业务 API 前缀,`backend.allowedMethods` 必须显式列出允许代理的 HTTP 方法;浏览器只能通过 frontend 同源代理访问这些后端。详细规则见 `docs/reference/microservices.md`。 -主 server 承载的 Todo Note 用户服务使用 `providerId=main-server`、`nodeBaseUrl=http://todo-note:4211` 和 `allowedMethods=["GET","HEAD","POST","DELETE"]`,数据库使用主 PostgreSQL;Code Queue 使用 `providerId=main-server`、`nodeBaseUrl=http://code-queue:4222` 和 `allowedPathPrefixes=["/health","/logs","/api/"]`,只通过 frontend/backend/provider-gateway 私有代理访问 Compose 内网服务名;D601 的 FindJob 只允许 `GET/HEAD` 展示型读取路径;D601 的 Pipeline 允许 `GET/HEAD/POST`,其中 `POST` 只用于 Pipeline 后端 `/api/node-control/...` 的 append prompt、guide 和 redo/restart 等受控 node 操作。 +主 server 承载的 Todo Note 用户服务使用 `providerId=main-server`、`nodeBaseUrl=http://todo-note:4211` 和 `allowedMethods=["GET","HEAD","POST","DELETE"]`,数据库使用主 PostgreSQL;Code Queue 使用 `providerId=D601`、`nodeBaseUrl=http://host.docker.internal:4222` 和 `allowedPathPrefixes=["/health","/logs","/api/"]`,只通过 frontend/backend/D601 provider-gateway 私有代理访问 D601 本机映射;D601 的 FindJob 只允许 `GET/HEAD` 展示型读取路径;D601 的 Pipeline 允许 `GET/HEAD/POST`,其中 `POST` 只用于 Pipeline 后端 `/api/node-control/...` 的 append prompt、guide 和 redo/restart 等受控 node 操作。 ## Compose Env Generation -Docker Compose 本身不读取 JSON,因此 CLI 会从 `config.json` 生成 `.state/docker-compose.env`。该文件是派生状态,不应手写;如需改端口、token、provider 标签、登录凭据或主机名,应修改 `config.json` 后重新运行 CLI。CLI 会在保留当前日志前缀的同时刷新新增配置键,避免旧 env 文件遗漏字段。 +Docker Compose 本身不读取 JSON,因此 CLI 会从 `config.json` 生成 `.state/docker-compose.env`。该文件是派生状态,不应手写;如需改常规端口、token、provider 标签、登录凭据或主机名,应修改 `config.json` 后重新运行 CLI。`network.restrictedHostAccess.bindHost` 派生出 `UNIDESK_DATABASE_BIND_HOST` 和 `UNIDESK_OA_EVENT_FLOW_BIND_HOST`,`allowedSourceCidrs` 由 `server start/rebuild` 写入 `DOCKER-USER` 来源白名单;将 bind host 设为 `0.0.0.0` 时 `allowedSourceCidrs` 不能为空。CLI 会在保留当前日志前缀的同时刷新新增配置键,避免旧 env 文件遗漏字段。 ## Secrets diff --git a/docs/reference/deployment.md b/docs/reference/deployment.md index f4fc8b8c..18f5af7a 100644 --- a/docs/reference/deployment.md +++ b/docs/reference/deployment.md @@ -1,6 +1,6 @@ # UniDesk Deployment Reference -主 server 使用根目录 `docker-compose.yml` 统一编排 database、backend-core、frontend 和 provider-gateway。当前环境本身就是主 server,因此 provider-gateway 也在同一台机器上启动,用与普通计算节点相同的 WebSocket 方式接入 core。 +主 server 使用根目录 `docker-compose.yml` 统一编排 database、backend-core、frontend、provider-gateway 以及必须留在主 server 的用户服务。当前环境本身就是主 server,因此 provider-gateway 也在同一台机器上启动,用与普通计算节点相同的 WebSocket 方式接入 core。Code Queue 不再属于主 server Compose,长期部署在 D601 并通过 provider-gateway `microservice.http` 接入。 ## Services @@ -9,15 +9,15 @@ - `frontend` 是唯一公开 Web 控制台,提供登录、从 TSX 转译出的 React 应用资产和到 backend-core 的同源代理。 - `provider-gateway` 是当前主 server 的本机计算节点代理,通过 WebSocket 主动连到 provider ingress,挂载 `/var/run/docker.sock` 作为自动任务执行主路径,使用 `pid: "host"` 读取节点级进程资源,并周期性上报系统资源指标、进程占用与 Docker daemon 状态;维护用 Host SSH / WSL SSH 私钥目录只读挂载到 `/run/host-ssh`,不得作为自动任务调度主路径。 - `todo-note` 是主 server 承载的 Todo Note 纯后端用户服务,容器名 `todo-note-backend`,只在 Compose 内网暴露 `4211/tcp`,使用主 PostgreSQL 存储迁移后的 Todo Note 数据。 -- `code-queue` 是主 server 承载的 Codex app-server 队列用户服务,容器名 `code-queue-backend`,仅在 Compose 内网暴露 `4222/tcp` 给本机 provider-gateway 私有代理访问,容器硬上限为 `300m` memory/swap;任务、queue、未读状态、控制状态和通知 outbox 一律写入主 PostgreSQL,不保留本地状态文件 fallback,浏览器只能通过 UniDesk frontend 同源代理查看运行输出、追加 prompt、打断和重试。 +- `code-queue` 是部署在 D601 的 Codex/OpenCode 队列用户服务,容器名 `code-queue-backend`,D601 只绑定 `127.0.0.1:4222`,由 D601 provider-gateway 通过 `http://host.docker.internal:4222` 私有访问;任务、queue、未读状态、控制状态和通知 outbox 一律写入主 PostgreSQL,不保留本地状态文件 fallback,浏览器只能通过 UniDesk frontend 同源代理查看运行输出、追加 prompt、打断和重试。 - `project-manager` 是主 server 承载的项目管理用户服务,容器名 `project-manager-backend`,仅在 Compose 内网暴露 `4233/tcp`,项目清单写入主 PostgreSQL,浏览器只能通过 UniDesk frontend 同源代理执行增删改查、Excel 导入和 Excel 导出。 - `baidu-netdisk` 是主 server 承载的百度网盘存储用户服务,容器名 `baidu-netdisk-backend`,仅在 Compose 内网暴露 `4244/tcp`,OAuth/token/transfer 状态写入主 PostgreSQL,浏览器只能通过 UniDesk frontend 同源代理执行设备码登录、文件浏览和 staging 传输任务控制。 ## Public Exposure Boundary -Docker Compose 只能向公网暴露两个接口:frontend host port 和 provider ingress host port。backend-core REST API 和 PostgreSQL database 必须只在 Docker 内部网络中可达,不允许映射到宿主机公网端口;浏览器访问 core API 必须通过 frontend 的同源代理完成。 +Docker Compose 对最终用户只公开 frontend host port 和 provider ingress host port。backend-core REST API 仍不得映射公网;PostgreSQL 和 OA Event Flow 只允许为了 D601 Code Queue 使用受限端口映射,并必须由 `network.restrictedHostAccess.allowedSourceCidrs` 生成的 `DOCKER-USER` 规则限制到 D601 出口地址,不能作为浏览器或任意公网客户端入口。浏览器访问 core API 必须通过 frontend 的同源代理完成。 -计算节点上的用户服务后端也遵守同一边界:业务容器端口只绑定节点本机地址,并由 provider-gateway 主动连出 WebSocket 后接受 backend-core 的 `microservice.http` 调度访问。主 server 不为用户服务新增公网反向代理端口;最终用户只通过 UniDesk frontend 的 React 页面访问结构化业务控件。 +计算节点上的用户服务后端也遵守同一边界:业务容器端口只绑定节点本机地址,并由 provider-gateway 主动连出 WebSocket 后接受 backend-core 的 `microservice.http` 调度访问。主 server 不为用户服务新增面向浏览器的公网反向代理端口;最终用户只通过 UniDesk frontend 的 React 页面访问结构化业务控件。 ## Docker Compose Runtime @@ -27,11 +27,11 @@ Compose v2 安装后仍然必须遵守 UniDesk 的服务控制入口:全栈生 ## Start And Stop -`bun scripts/cli.ts server start` 与 `bun scripts/cli.ts server stop` 都是异步 job。启动 job 只执行固定 Compose project 的 `up -d --build --remove-orphans`,不得先 `down`,避免在 provider-gateway 旧容器或网络冲突时把 `code-queue-backend` 等长任务容器先删掉又启动失败;停止 job 才允许执行 `down --remove-orphans`。启动和停止流程都禁止删除 Docker named volume。所有会改变主 server Compose 状态的 job 必须通过 `.state/locks/server-compose.lock` 串行化;`server rebuild code-queue && server rebuild frontend` 这类连续命令只代表连续创建异步 job,不能代表第一个 job 已结束,实际容器变更仍必须由 Compose lock 串行执行。 +`bun scripts/cli.ts server start` 与 `bun scripts/cli.ts server stop` 都是异步 job。启动 job 只执行固定 Compose project 的 `up -d --build --remove-orphans`,不得先 `down`,避免在 provider-gateway 旧容器或网络冲突时把长驻控制面容器先删掉又启动失败;停止 job 才允许执行 `down --remove-orphans`。启动和停止流程都禁止删除 Docker named volume。所有会改变主 server Compose 状态的 job 必须通过 `.state/locks/server-compose.lock` 串行化;连续 `server rebuild` 命令只代表连续创建异步 job,不能代表第一个 job 已结束,实际容器变更仍必须由 Compose lock 串行执行。 ## Single Service Rebuild -前端、backend-core、本机 provider-gateway 或主 server 承载的 Todo Note/Code Queue/Project Manager/Baidu Netdisk 用户服务需要重建时,统一使用 `bun scripts/cli.ts server rebuild `,其中 `` 只能是 `backend-core`、`frontend`、`provider-gateway`、`todo-note`、`code-queue`、`project-manager` 或 `baidu-netdisk`。File Browser 部署在 D518/D601 计算节点,不属于主 server Compose 可重建服务。该命令先执行目标服务镜像构建,构建成功后才通过 `up -d --no-deps --force-recreate ` 替换目标容器,避免构建失败导致运行中的服务被提前停掉。 +前端、backend-core、本机 provider-gateway 或主 server 承载的 Todo Note/Project Manager/Baidu Netdisk/OA Event Flow 用户服务需要重建时,统一使用 `bun scripts/cli.ts server rebuild `,其中 `` 只能是 `backend-core`、`frontend`、`provider-gateway`、`todo-note`、`project-manager`、`baidu-netdisk` 或 `oa-event-flow`。Code Queue、File Browser、FindJob、Pipeline、MET Nonlinear 和 ClaudeQQ 部署在计算节点,不属于主 server Compose 可重建服务。该命令先执行目标服务镜像构建,构建成功后才通过 `up -d --no-deps --force-recreate ` 替换目标容器,避免构建失败导致运行中的服务被提前停掉。 frontend 改动必须明确上线到公网:修改 `src/components/frontend/src/`、`src/components/frontend/public/style.css`、frontend 使用的共享 TSX/TS 模块或 WebUI 导航后,必须在同一变更集中执行 `bun scripts/cli.ts server rebuild frontend`,并等待 job 成功。公网 WebUI 的 `/app.js` 是 `unidesk-frontend` 容器启动时从镜像内源码转译生成的运行时 bundle;只改工作区文件、只跑 `bun run check`、只跑 `Bun.build` 或只刷新浏览器都不会替换已经运行的容器。 @@ -41,7 +41,7 @@ frontend 的 Docker 上线顺序为:先运行必要的本地校验,例如 `b 紧急灾备或数据迁移期间如需手工启动单个 Compose service,也必须保持与 CLI 相同的隔离语义:使用固定 `--env-file .state/docker-compose.env` 和 `up -d --no-deps `,只启动目标容器;如果需要刷新 backend-core 的服务目录或环境变量,应把 `backend-core` 作为显式目标单独重建/替换,不能依赖 `up` 的依赖解析顺手重建 database、backend-core 或其他服务。 -正式流程不得依赖人工 `docker rm` 兜底;手工删除旧容器后若 job、Docker client 或 daemon 在 `up` 前中断,会直接造成 `direct microservice proxy failed`。`server rebuild ` 必须是可观测 job:build-first、Compose lock、no-deps force-recreate、post-up validation、保留 named volume。Code Queue 等长任务服务即使被重建也必须依赖服务自身 restart-recovery 恢复任务,不能用“避免重建”掩盖恢复缺陷。 +正式流程不得依赖人工 `docker rm` 兜底;手工删除旧容器后若 job、Docker client 或 daemon 在 `up` 前中断,会直接造成用户服务代理失败。`server rebuild ` 必须是可观测 job:build-first、Compose lock、no-deps force-recreate、post-up validation、保留 named volume。Code Queue 等计算节点长任务服务即使被重建也必须依赖服务自身 restart-recovery 恢复任务,不能用“避免重建”掩盖恢复缺陷。 ## User Service Restart Recovery @@ -49,11 +49,11 @@ frontend 的 Docker 上线顺序为:先运行必要的本地校验,例如 `b ## Health Criteria -服务跑通的最低标准是:backend-core 内网 `/health` 返回 ok,frontend 公网 `/health` 返回 ok,provider ingress 公网 `/health` 返回 ok,database 在容器内 `pg_isready` 可用,Todo Note 后端 `/api/health` 返回 `storage=postgres`,Code Queue `/health` 返回队列摘要、默认模型和 `queue.storage`,Project Manager `/health` 返回 `storage.primary=postgres` 和项目数量,backend-core `/api/performance` 返回性能指标,`/api/nodes` 中出现 `main-server` provider 且状态为 `online`,`/api/nodes/system-status` 中出现 `main-server` 的 CPU/内存/硬盘采样,`/api/nodes/docker-status` 中出现 `main-server` 的 Docker 快照。交付前还必须运行 `bun scripts/cli.ts e2e run`,并以 `docs/reference/e2e.md` 的门禁作为最终判定。 +服务跑通的最低标准是:backend-core 内网 `/health` 返回 ok,frontend 公网 `/health` 返回 ok,provider ingress 公网 `/health` 返回 ok,database 在容器内 `pg_isready` 可用,Todo Note 后端 `/api/health` 返回 `storage=postgres`,D601 Code Queue `/health` 返回队列摘要、默认模型和 `queue.storage`,Project Manager `/health` 返回 `storage.primary=postgres` 和项目数量,backend-core `/api/performance` 返回性能指标,`/api/nodes` 中出现 `main-server` 和 `D601` provider 且状态为 `online`,`/api/nodes/system-status` 中出现对应 CPU/内存/硬盘采样,`/api/nodes/docker-status` 中能看到主 server 与 D601 Docker 快照。交付前还必须运行 `bun scripts/cli.ts e2e run`,并以 `docs/reference/e2e.md` 的门禁作为最终判定。 -## Main Server Memory Budget +## Code Queue D601 Resource Budget -主 server 内存预算按稀缺资源管理,不能把用户服务当作无限内存的 worker 节点使用。`code-queue-backend` 必须保持明确的 memory/swap 硬上限,默认 `CODE_QUEUE_MAX_ACTIVE_QUEUES=0` 以恢复 queue 间并行,仍保持 `CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS=10`、`CODE_QUEUE_IN_MEMORY_EVENT_RECORDS=10` 这类小热窗口;任务历史、队列统计、Trace/output 读取和 `/health` 摘要必须优先从 PostgreSQL 直读或聚合,不能为了性能便利在 Bun 进程内缓存全量历史。任何提高 Code Queue 热窗口、日志缓冲、Playwright/Codex 子进程常驻规模或容器上限的变更,或把 `CODE_QUEUE_MAX_ACTIVE_QUEUES` 显式改成正数,都必须在同一任务里说明内存预算来源,并通过 `docker inspect code-queue-backend`、`docker stats --no-stream code-queue-backend`、`microservice health code-queue` 和对应 E2E 证明未重新引入内存爆炸风险。 +Code Queue 已从主 server 迁移到 D601,但仍必须保持明确的 memory/swap 硬上限,默认 `CODE_QUEUE_MAX_ACTIVE_QUEUES=0` 以恢复 queue 间并行,仍保持 `CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS=10`、`CODE_QUEUE_IN_MEMORY_EVENT_RECORDS=10` 这类小热窗口;任务历史、队列统计、Trace/output 读取和 `/health` 摘要必须优先从 PostgreSQL 直读或聚合,不能为了性能便利在 Bun 进程内缓存全量历史。任何提高 Code Queue 热窗口、日志缓冲、Playwright/Codex 子进程常驻规模或容器上限的变更,或把 `CODE_QUEUE_MAX_ACTIVE_QUEUES` 显式改成正数,都必须在同一任务里说明 D601 资源预算来源,并通过 D601 `docker inspect code-queue-backend`、`docker stats --no-stream code-queue-backend`、`microservice health code-queue` 和对应 E2E 证明未重新引入内存爆炸风险。 ## Database Volume diff --git a/docs/reference/e2e.md b/docs/reference/e2e.md index be08eda0..a4a35bd2 100644 --- a/docs/reference/e2e.md +++ b/docs/reference/e2e.md @@ -31,17 +31,17 @@ Typical targeted commands: - `bun scripts/cli.ts e2e run --only frontend --skip frontend:todo-note-integrated-visible,frontend:findjob-integrated-visible` - `bun scripts/cli.ts e2e run --only network,provider-ingress` -- Public exposure: Docker port summary must show only frontend and provider ingress host mappings; public core、public database and known private user-service ports such as FindJob `3254`, MET Nonlinear `3288`, Todo Note `4211`, Code Queue host port `14222`, OA Event Flow `4255` and File Browser provider port `4251` probes must fail. +- Public exposure: Docker port summary must not show core REST or Code Queue public host mappings; frontend and provider ingress are the only browser/provider public entries. PostgreSQL `15432` and OA Event Flow `4255` may be host-mapped only for D601 Code Queue and must be protected by the `DOCKER-USER` source restrictions generated from `network.restrictedHostAccess`; E2E treats either an unreachable generic probe or a verified restricted rule as passing. Known private user-service ports such as FindJob `3254`, MET Nonlinear `3288`, Todo Note `4211`, Code Queue host port `14222` and File Browser provider port `4251` probes must fail. - Core API: `docker exec unidesk-backend-core` calls internal `GET /api/overview`, which must report `dbReady: true`, `pgdata.volumeName=unidesk_pgdata_10gb`, a positive PostgreSQL database byte count, and at least one online node; internal `GET /api/performance` must report component request statistics, internal operation statistics, PGDATA usage and Code Queue PostgreSQL storage metadata. - Provider self-connection: internal `GET /api/nodes` must contain `main-server` with `status: online`, `labels.providerGatewayVersion` equal to `src/components/provider-gateway/package.json`, `labels.providerGatewayUpgradePolicy: "always-enabled"`, `labels.providerGatewayRestartPolicyOk: true`, `labels.providerGatewayPidModeOk: true`, and `labels.providerGatewayRuntimeGuardOk: true`; internal `GET /api/nodes/system-status` must contain CPU/memory/disk samples plus a non-empty process resource list sorted by memory by default; internal `GET /api/nodes/docker-status` must contain a Docker snapshot for `main-server`; every running `provider-gateway` container visible in Docker snapshots must report `restartPolicy: "always"` and `pidMode: "host"`; public provider ingress `/health` must return ok. - Provider remote control: internal `/api/dispatch` must successfully complete a real `provider.upgrade` task in `mode: "plan"` so the upgrade path is validated without recreating the running gateway during E2E. -- User services: internal `/api/microservices` must include `todo-note`, `oa-event-flow` and `code-queue` on `main-server`, canonical `filebrowser` on `D518`, plus `findjob`, `pipeline`, `met-nonlinear`, `claudeqq` and `filebrowser-d601` on `D601` with `public=false`; `/api/microservices/todo-note/health` must report `storage=postgres`, `/api/microservices/todo-note/proxy/api/instances` must expose the migrated Todo Note lists, and a temporary Todo Note list create/add/toggle/undo/delete cycle must succeed through the real provider-gateway proxy; `/api/microservices/oa-event-flow/health`, `/api/microservices/oa-event-flow/proxy/api/diagnostics`, `/api/microservices/oa-event-flow/proxy/api/events`, `/api/microservices/oa-event-flow/proxy/api/events?tags=service:pipeline` and `/api/microservices/oa-event-flow/proxy/api/stats/trace` must prove the independent OA event table、Pipeline bridge 和 stats center are reachable through UniDesk proxy; `/api/microservices/code-queue/health` must return a Code Queue summary with default model `gpt-5.5`, and `/api/microservices/code-queue/proxy/api/tasks` must return queue state through the same proxy; `/api/microservices/filebrowser/health`, `/api/microservices/filebrowser-d601/health` and `/api/microservices/filebrowser/proxy/` must prove File Browser health and WebUI access through UniDesk proxy; `/api/microservices/findjob/health` and `/api/microservices/findjob/proxy/api/summary` must succeed through the real provider-gateway proxy; `/api/microservices/findjob/proxy/api/jobs?__unideskArrayLimit=jobs:5` must return a bounded preview with `_unidesk.arrayLimits` metadata; `/api/microservices/pipeline/health`, `/api/microservices/pipeline/proxy/api/snapshot?__unideskArrayLimit=registry.components:8,runs:3` and `/api/microservices/pipeline/proxy/api/oa-event-flow/diagnostics` must return Pipeline health, registry/run previews and OA event-flow evidence; `/api/microservices/met-nonlinear/health`, `/api/microservices/met-nonlinear/proxy/api/queue`, `/api/microservices/met-nonlinear/proxy/api/projects?root=projects&limit=500`, `/api/microservices/met-nonlinear/proxy/api/projects?root=ex_projects&limit=500`, `/api/microservices/met-nonlinear/proxy/api/projects/config?path=` and `/api/microservices/met-nonlinear/proxy/api/images` must return the D601 TS backend health, queue/GPU policy, full project tree inputs, structured project detail and ready `met-nonlinear-ml:tf26` image status. +- User services: internal `/api/microservices` must include `todo-note` and `oa-event-flow` on `main-server`, canonical `filebrowser` on `D518`, plus `code-queue`, `findjob`, `pipeline`, `met-nonlinear`, `claudeqq` and `filebrowser-d601` on `D601` with `public=false`; `/api/microservices/todo-note/health` must report `storage=postgres`, `/api/microservices/todo-note/proxy/api/instances` must expose the migrated Todo Note lists, and a temporary Todo Note list create/add/toggle/undo/delete cycle must succeed through the real provider-gateway proxy; `/api/microservices/oa-event-flow/health`, `/api/microservices/oa-event-flow/proxy/api/diagnostics`, `/api/microservices/oa-event-flow/proxy/api/events`, `/api/microservices/oa-event-flow/proxy/api/events?tags=service:pipeline` and `/api/microservices/oa-event-flow/proxy/api/stats/trace` must prove the independent OA event table、Pipeline bridge 和 stats center are reachable through UniDesk proxy; `/api/microservices/code-queue/health` must return a D601 Code Queue summary with default model `gpt-5.5`, and `/api/microservices/code-queue/proxy/api/tasks` must return queue state through the same D601 provider-gateway proxy; `/api/microservices/filebrowser/health`, `/api/microservices/filebrowser-d601/health` and `/api/microservices/filebrowser/proxy/` must prove File Browser health and WebUI access through UniDesk proxy; `/api/microservices/findjob/health` and `/api/microservices/findjob/proxy/api/summary` must succeed through the real provider-gateway proxy; `/api/microservices/findjob/proxy/api/jobs?__unideskArrayLimit=jobs:5` must return a bounded preview with `_unidesk.arrayLimits` metadata; `/api/microservices/pipeline/health`, `/api/microservices/pipeline/proxy/api/snapshot?__unideskArrayLimit=registry.components:8,runs:3` and `/api/microservices/pipeline/proxy/api/oa-event-flow/diagnostics` must return Pipeline health, registry/run previews and OA event-flow evidence; `/api/microservices/met-nonlinear/health`, `/api/microservices/met-nonlinear/proxy/api/queue`, `/api/microservices/met-nonlinear/proxy/api/projects?root=projects&limit=500`, `/api/microservices/met-nonlinear/proxy/api/projects?root=ex_projects&limit=500`, `/api/microservices/met-nonlinear/proxy/api/projects/config?path=` and `/api/microservices/met-nonlinear/proxy/api/images` must return the D601 TS backend health, queue/GPU policy, full project tree inputs, structured project detail and ready `met-nonlinear-ml:tf26` image status. - ClaudeQQ availability: `/api/microservices/claudeqq/health` must only pass when `ready=true`, NapCat HTTP and WebSocket are connected, and `napcat.loginState=logged_in`; `/api/microservices/claudeqq/proxy/api/napcat/login` must show the same logged-in account state and `/api/microservices/claudeqq/proxy/api/events/recent` must prove the backend can read the persistent event cache. A QR-code-only or not-logged-in NapCat state must be treated as unhealthy. - Database: the command writes an `unidesk_e2e_markers` row through `docker exec unidesk-database psql`, confirms provider state is stored in PostgreSQL, and checks Todo Note rows exist in `todo_note_instances` using the same named volume. - Pipeline OA event flow: `microservice:pipeline-oa-event-flow` must prove both no-audit and monitor-audit runs are driven by OA events end to end. The event stream must show `node-finished` as a neutral fact with `pipeline:{pipelineId}` and `epoch:{runId}` tags, OA policy as the source of downstream/audit decisions, monitor decisions as OA control events, and runner control-result evidence. E2E must fail if delivery still depends on a legacy detail audit policy flag as policy authority, independent legacy audit-request points, a legacy batch completion gate, direct monitor-to-runner calls, or frontend/CLI writes to Pipeline `.state`. - The same Pipeline OA diagnostics must fail on legacy file-transport residuals. Procedure containers, monitor sessions, UI/Gantt DTO builders and CLI fetches must consume prompt/control/stop/display evidence only from the OA event ledger and normalized HTTP read APIs; `control-prompts.jsonl`, `monitor-prompts.jsonl`, `monitor-control`, `control-events.jsonl`, monitor stop files, `.state/pipeline-runs/{runId}/control/commands/`, `PIPELINE_*_APPEND_FILE`, local JSONL append/read helpers, and monitor `/pipeline-state` mounts are forbidden in runtime source. - Pipeline live Gantt setup: when `frontend:pipeline-gantt-observation-live-running` is selected, E2E first looks for a current Pipeline run that already contains both a `node-long-running-observation` marker and a still-running execution interval. If no such candidate exists, the E2E setup starts the D601 `monitor-management-behavior-test` pipeline through `bun scripts/cli.ts ssh D601 ...` and polls the private backend proxy until the observation candidate exists; the acceptance assertion itself still opens the public frontend with Playwright and verifies the rendered arrows, absence of observation source pseudo-points, target arrow inset, and live flashing running bar through React DOM controls. -- Frontend: Playwright must open the public frontend URL derived from `network.publicHost`, not localhost or a Docker-internal URL; it logs in with the configured account, waits for `核心在线`, asserts that `main-server` and `Main Server Provider` are visible, verifies desktop sidebar collapse and `PGDATA` overview metric, opens `运行总览 / 性能面板` to verify `Bwebui`、组件汇总、最近失败请求、内部操作汇总和最近慢操作, clicks `查看原始JSON` to verify Provider data from the frontend, confirms no raw JSON is visible before that click, opens task history to verify duration and failure diagnostics, opens resource nodes `资源监控` to verify CPU/Memory/Disk curves, the structured process resource table, default memory-desc sorting, sortable CPU column and provider upgrade precheck dispatch, opens `Docker 状态`, switches to `main-server`, and verifies the Docker Desktop-style container view including the database named volume `unidesk_pgdata_10gb`, opens `网关版本` and verifies the provider-gateway version, SSH 透传可用性、远程更新可用性 plus structured remote update records for `provider.upgrade`, then opens `用户服务 / 服务目录`、`用户服务 / Todo Note`、`用户服务 / OA Event Flow`、`用户服务 / Code Queue`、`用户服务 / FindJob`、`用户服务 / Pipeline` and `用户服务 / MET Nonlinear` to verify 主 server Todo Note/OA Event Flow/Code Queue、D601、仓库引用、私有后端映射、Todo Note 迁移清单和树形任务、OA Event Flow 事件表和 Trace stats 表、Code Queue 队列/模型/输出/初始 `Submitted prompt`/终态任务自动加载完整 Trace/追加 prompt/打断控件、FindJob 指标和岗位预览、Pipeline 组件矩阵、MiniMax 限额卡片、结构化 OA 事件流诊断面板、React Flow 控制图、epoch 甘特图、甘特图渲染图导出、monitor 首列排序、长任务观察连线、无观察来源伪点、running node 实时闪动执行条和 OpenCode Trace、MET Nonlinear 项目库/Fork/待启动队列/当前队列/已完成/失败诊断/GPU/镜像都通过 React 控件展示。Playwright 还必须验证深链接直达路由,例如公网 `http://:/app/pipeline/` 能直接落到 Pipeline 页面,随后切到 `资源节点 / Docker 状态` 时地址栏更新为 `/nodes/docker/`,并且浏览器 history 返回链路仍能回到 `/app/pipeline/`;还必须直开 `/app/code-queue/` 验证页面存在 `app-shell`、左侧主模块边栏、顶部状态栏、顶部子标签和 `code-queue-page`,防止用户服务 deep link 退化成缺 shell 的 standalone 页面;同时 `态势总览` 这类非用户服务页面应落在自己的模块前缀下,例如 `/ops/status/`。Playwright 必须覆盖默认可见时间按北京时间显示,至少包括顶部 `北京时间` 时钟、任务历史/网关版本更新时间和用户服务刷新时间,不得随浏览器本地时区漂移。Task history and provider upgrade records must not display a real sub-second duration as `0s`; MET Nonlinear running rows must show an ETA derived from backend progress or from `startedAt` plus epoch progress, and queue/completed rows must show training speed as `epoch/h`. +- Frontend: Playwright must open the public frontend URL derived from `network.publicHost`, not localhost or a Docker-internal URL; it logs in with the configured account, waits for `核心在线`, asserts that `main-server` and `Main Server Provider` are visible, verifies desktop sidebar collapse and `PGDATA` overview metric, opens `运行总览 / 性能面板` to verify `Bwebui`、组件汇总、最近失败请求、内部操作汇总和最近慢操作, clicks `查看原始JSON` to verify Provider data from the frontend, confirms no raw JSON is visible before that click, opens task history to verify duration and failure diagnostics, opens resource nodes `资源监控` to verify CPU/Memory/Disk curves, the structured process resource table, default memory-desc sorting, sortable CPU column and provider upgrade precheck dispatch, opens `Docker 状态`, switches to `main-server`, and verifies the Docker Desktop-style container view including the database named volume `unidesk_pgdata_10gb`, opens `网关版本` and verifies the provider-gateway version, SSH 透传可用性、远程更新可用性 plus structured remote update records for `provider.upgrade`, then opens `用户服务 / 服务目录`、`用户服务 / Todo Note`、`用户服务 / OA Event Flow`、`用户服务 / Code Queue`、`用户服务 / FindJob`、`用户服务 / Pipeline` and `用户服务 / MET Nonlinear` to verify 主 server Todo Note/OA Event Flow、D601 Code Queue、D601 业务服务、仓库引用、私有后端映射、Todo Note 迁移清单和树形任务、OA Event Flow 事件表和 Trace stats 表、Code Queue 队列/模型/输出/初始 `Submitted prompt`/终态任务自动加载完整 Trace/追加 prompt/打断控件、FindJob 指标和岗位预览、Pipeline 组件矩阵、MiniMax 限额卡片、结构化 OA 事件流诊断面板、React Flow 控制图、epoch 甘特图、甘特图渲染图导出、monitor 首列排序、长任务观察连线、无观察来源伪点、running node 实时闪动执行条和 OpenCode Trace、MET Nonlinear 项目库/Fork/待启动队列/当前队列/已完成/失败诊断/GPU/镜像都通过 React 控件展示。Playwright 还必须验证深链接直达路由,例如公网 `http://:/app/pipeline/` 能直接落到 Pipeline 页面,随后切到 `资源节点 / Docker 状态` 时地址栏更新为 `/nodes/docker/`,并且浏览器 history 返回链路仍能回到 `/app/pipeline/`;还必须直开 `/app/code-queue/` 验证页面存在 `app-shell`、左侧主模块边栏、顶部状态栏、顶部子标签和 `code-queue-page`,防止用户服务 deep link 退化成缺 shell 的 standalone 页面;同时 `态势总览` 这类非用户服务页面应落在自己的模块前缀下,例如 `/ops/status/`。Playwright 必须覆盖默认可见时间按北京时间显示,至少包括顶部 `北京时间` 时钟、任务历史/网关版本更新时间和用户服务刷新时间,不得随浏览器本地时区漂移。Task history and provider upgrade records must not display a real sub-second duration as `0s`; MET Nonlinear running rows must show an ETA derived from backend progress or from `startedAt` plus epoch progress, and queue/completed rows must show training speed as `epoch/h`. - Frontend dense-layout regression gate: whenever a frontend change touches Pipeline 右侧边栏、Trace timeline、详情抽屉、甘特图坐标或其他高信息密度面板, Playwright acceptance must inspect both `总高度` and `横向滚动条`. For Pipeline specifically, the OpenCode Trace session head must carry shared agent/model/session facts and the Trace body must use the same Code Queue `TraceView` styling; Playwright must fail if old `.pipeline-opencode-step`, `.pipeline-opencode-flow`, `.pipeline-step-message-card` or `.pipeline-opencode-part` user-visible styles reappear, if the Trace container introduces an internal horizontal scrollbar, or if `frontend:pipeline-gantt-frontend-y-accuracy` fails to prove the frontend `frontend-y` layout maps ticks, markers and execution bars from timestamps to y coordinates within tolerance. - OpenCode Trace must use Code Queue Trace styling and must not render the deprecated Pipeline continuous step connector; Playwright should fail if `.pipeline-opencode-flow`, `.pipeline-opencode-step` or any equivalent continuous connector/card returns to the user-visible Trace. - User service frontend assertions must wait for real backend data, not only the page skeleton. For Todo Note this means the page must show the migrated lists `CONSTAR`、`大论文`、`找工作`、`小论文`、`事务`, support creating a temporary list and task through the frontend, and delete that temporary list afterwards. The temporary list must be selected again by its unique generated name before deletion so E2E never deletes a migrated source list by accident. For FindJob this means the page must show a numeric `岗位总量`, `HEALTH OK`, and a non-empty `PREVIEW` count such as `40/1463 PREVIEW`; for Pipeline this means the page must show `Pipeline v2 工作台`, `Health OK`, a numeric component count, a non-empty React Flow control graph, `控制图`, `Epoch 甘特图`, and after clicking a Gantt execution line it must show `OpenCode Trace` rendered by the shared Code Queue-style Trace component with messages and tool-call groups; for MET Nonlinear this means the page must show `MET Nonlinear 训练编排`, `Health OK`, `Fork Project`, `加入待启动队列`, `启动队列`, `当前队列`, 最大并发设置、task queue and GPU/image panels, and must not show the removed hard-coded `创建10个10轮任务` frontend entry. The MET Nonlinear project library must render `projects/` and `ex_projects/` as a true path tree with folder Project counts; clicking a project row must open a structured detail panel containing `config.json`, `data/ 训练状态`, `模型参数`, `指标` and a parameter count such as `Total Params`; clicking a completed/current/failed job row must open a structured job detail and both the row and detail must show `epoch/h`. Full MET Nonlinear acceptance is driven by public frontend controls: choose a visible source Project, set batch size, epochs and max concurrency in inputs, fork into `projects/unidesk_forks/`, stage the selected forks, start the queue, and verify completed rows plus automatic `metnl-train-*` container removal; loading placeholders like `--` or empty states are not sufficient for E2E success. @@ -59,7 +59,7 @@ User service pages are covered by the same rule. `Todo Note` must show lists, ta ## Public Boundary Rule -The public frontend URL and provider ingress URL are the only public network interfaces. backend-core REST API and PostgreSQL database are Docker-internal only; E2E must prove the historical public core/database ports are not reachable. +The public frontend URL and provider ingress URL are the only unrestricted public network interfaces. backend-core REST API remains Docker-internal only; PostgreSQL and OA Event Flow may expose restricted host mappings solely for D601 Code Queue, and E2E must prove those mappings are unreachable to generic clients or protected by explicit source rules. ## Database Persistence Rule diff --git a/docs/reference/frontend.md b/docs/reference/frontend.md index e0625974..18b392b3 100644 --- a/docs/reference/frontend.md +++ b/docs/reference/frontend.md @@ -95,7 +95,7 @@ frontend shell 必须把左侧主模块与顶部子标签编译为统一的 URL - `ClaudeQQ` 子标签必须把 D601 ClaudeQQ 后端渲染为 UniDesk React 控件,包括 NapCat 容器登录二维码、NapCat HTTP/WS 状态、事件缓存、QQ 事件订阅表、订阅创建表单、消息推送表单、主用户私聊账号 `645275593` 标记、最近 QQ 事件、已发送记录和显式原始 JSON 按钮。 - `Baidu Netdisk` 子标签必须把主 server `baidu-netdisk-backend` 后端渲染为 UniDesk React 控件,包括 OAuth 设备码二维码/用户码登录、账号容量、配置工作根文件浏览(当前默认百度网盘根目录 `/`)、staging 目录上传/下载任务、上传/下载自测按钮与 MD5 结果、脱敏安全说明、日志摘要和显式原始 JSON 按钮;不得把 access token、refresh token、dlink 或 staging 文件字节流裸露到浏览器。 - `OA Event Flow` 子标签必须把主 server `oa-event-flow-backend` 后端渲染为 UniDesk React 控件,包括服务健康、事件表、tag 过滤、SSE live 状态、Trace/STEP stats 表、Code Queue/Pipeline 标签入口和显式原始 JSON 按钮;默认页面不得裸铺完整事件 JSON,事件表只展示结构化摘要,完整 envelope/payload 只能通过 `查看原始JSON` 打开。 - - `Code Queue` 子标签必须把主 server `code-queue-backend` 后端渲染为 UniDesk React 控件,包括多 queue lane、queue 内串行、queue 间并行、queue 合并(点击“合并 queue”后必须用公共 `UniDeskDialog` 打开独立小窗口,用下拉菜单选择源 queue;不得把源 queue 选择控件塞进正常提交任务的 Queue 选择区;合并后自动删除源 queue,只保留合并后的目标 queue,目标 queue 按原 queueEnteredAt/createdAt 时间顺序串行)、任务 ID/复制任务 ID、引用按钮、任务耗时、任务提交/批量提交、引用任务 ID、创建成功提示、清空输入、模型下拉、执行 Provider 下拉、执行模式下拉(默认容器/本机或 `windows-native`)、显式入队份数、默认模型 `gpt-5.5`、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、运行中追加 prompt、打断、手动重试和显式原始 JSON 按钮;`windows-native` 模式必须在任务 JSON、卡片和 Trace 头部显示,并要求非主 server WSL Provider 与 `/mnt/` 工作目录;Codex CLI-like 输出流必须始终保留任务的初始 `Submitted prompt` 和运行中 `Steer prompt`;整个 agent loop 消息流统一命名为专有名词 `Trace`,`Trace` 包含 assistant message、user prompt、system event 和 tool call,但非错误 system event 默认只保留在原始输出/数据库中,不在 TraceView 展示;Code Queue 与 Pipeline/OpenCode messages 必须共用 `src/components/frontend/src/trace.tsx` 的 Trace 公共组件、统一 Trace item 接口和 codex/opencode port 适配层;连续 read/edit/run 工具调用只是在 Trace 内折叠为可展开工具调用组,汇总格式至少包含 `xx read, xx edit, xx run`,并展示读取文件、编辑文件、运行命令和耗时摘要;最近 3 个工具调用保持展开,工具调用内容不得自动换行且必须在工具调用块内部横向滚动,工具调用组展开后不得再增加额外左侧缩进;message 与 prompt 必须自动换行,普通 message 不显示左侧项目符号缩进且永不折叠;Trace 首屏可以是摘要预览,但终态任务被选中后必须自动在后台加载完整 Trace,手动“加载完整 Trace”也必须从 Code Queue output archive 分页补齐早期 trace,不得把 preview 的 `hasMore=false` 当成完整历史;即使热状态为控制体积裁剪了早期 raw output,也要从结构化 `basePrompt/displayPrompt/promptHistory` 和 archive 合成完整用户输入与 agent trace,并且初始 prompt 默认显示注入前 prompt 而不是引用注入全文;当初始 prompt 含引用注入时,引用内容必须默认折叠,并只在 Trace 的初始消息中提供可展开的“最终传入 Codex 的真实完整 prompt”,不得再渲染独立 Prompt 全量卡片;多轮引用注入必须按上游/最早上下文在前、直接引用在后的顺序排列,每一轮必须有明确 `Reference Round N/M` 分割线和时间范围,不能用固定 6 轮截断引用链;点击队列引用按钮必须自动把该任务 ID 写入提交表单的引用输入框,引用任务 ID 创建新任务时必须自动注入 `bun scripts/cli.ts codex task ` 的提示;连续执行同一 prompt 应通过入队份数一次性生成多条任务,避免快速连点造成操作员误判。 + - `Code Queue` 子标签必须把 D601 `code-queue-backend` 后端渲染为 UniDesk React 控件,包括多 queue lane、queue 内串行、queue 间并行、queue 合并(点击“合并 queue”后必须用公共 `UniDeskDialog` 打开独立小窗口,用下拉菜单选择源 queue;不得把源 queue 选择控件塞进正常提交任务的 Queue 选择区;合并后自动删除源 queue,只保留合并后的目标 queue,目标 queue 按原 queueEnteredAt/createdAt 时间顺序串行)、任务 ID/复制任务 ID、引用按钮、任务耗时、任务提交/批量提交、引用任务 ID、创建成功提示、清空输入、模型下拉、执行 Provider 下拉、执行模式下拉(默认容器/本机或 `windows-native`)、显式入队份数、默认模型 `gpt-5.5`、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、运行中追加 prompt、打断、手动重试和显式原始 JSON 按钮;`windows-native` 模式必须在任务 JSON、卡片和 Trace 头部显示,并要求非本机 WSL Provider 与 `/mnt/` 工作目录;Codex CLI-like 输出流必须始终保留任务的初始 `Submitted prompt` 和运行中 `Steer prompt`;整个 agent loop 消息流统一命名为专有名词 `Trace`,`Trace` 包含 assistant message、user prompt、system event 和 tool call,但非错误 system event 默认只保留在原始输出/数据库中,不在 TraceView 展示;Code Queue 与 Pipeline/OpenCode messages 必须共用 `src/components/frontend/src/trace.tsx` 的 Trace 公共组件、统一 Trace item 接口和 codex/opencode port 适配层;连续 read/edit/run 工具调用只是在 Trace 内折叠为可展开工具调用组,汇总格式至少包含 `xx read, xx edit, xx run`,并展示读取文件、编辑文件、运行命令和耗时摘要;最近 3 个工具调用保持展开,工具调用内容不得自动换行且必须在工具调用块内部横向滚动,工具调用组展开后不得再增加额外左侧缩进;message 与 prompt 必须自动换行,普通 message 不显示左侧项目符号缩进且永不折叠;Trace 首屏可以是摘要预览,但终态任务被选中后必须自动在后台加载完整 Trace,手动“加载完整 Trace”也必须从 Code Queue output archive 分页补齐早期 trace,不得把 preview 的 `hasMore=false` 当成完整历史;即使热状态为控制体积裁剪了早期 raw output,也要从结构化 `basePrompt/displayPrompt/promptHistory` 和 archive 合成完整用户输入与 agent trace,并且初始 prompt 默认显示注入前 prompt 而不是引用注入全文;当初始 prompt 含引用注入时,引用内容必须默认折叠,并只在 Trace 的初始消息中提供可展开的“最终传入 Codex 的真实完整 prompt”,不得再渲染独立 Prompt 全量卡片;多轮引用注入必须按上游/最早上下文在前、直接引用在后的顺序排列,每一轮必须有明确 `Reference Round N/M` 分割线和时间范围,不能用固定 6 轮截断引用链;点击队列引用按钮必须自动把该任务 ID 写入提交表单的引用输入框,引用任务 ID 创建新任务时必须自动注入 `bun scripts/cli.ts codex task ` 的提示;连续执行同一 prompt 应通过入队份数一次性生成多条任务,避免快速连点造成操作员误判。 - `Code Queue` 前端改进必须在同一任务内重建并上线公网 frontend,不能只修改源码或本地 bundle;重建 frontend 是无状态 WebUI 替换,不会导致 Code Queue 长期任务失败。已结束未读任务只能在 task card 边角显示类似未读消息的 `codex-unread-badge` 圆点和“标为已读”操作,不得把整张卡片改成红色/琥珀色失败态边框、背景或胶囊标签;状态栏的“结束未读”提示也不得使用失败态红色。 - `Code Queue` 前端必须把 PostgreSQL-backed backend API 作为 task、queue、readAt/未读状态和 attempt 状态的唯一数据来源;不得用 `localStorage`、`sessionStorage` 或 IndexedDB 持久化这些业务状态,也不得在后端标记已读失败时伪造本地成功。前端允许保留 React 内存态、请求 in-flight guard 和本轮页面缓存,但刷新页面或切换设备后的状态必须完全由后端 PostgreSQL 数据恢复。 - `Code Queue` 前后端通信必须采用渐进式披露:首屏只请求 queue/task 轻量摘要、必要的 selected preview 和小体积统计,不得默认拉取完整 transcript、raw output、原始 JSON 或全部历史任务;加载下一页或搜索分页时必须显式传递 `selected=0`、`includeActive=0`、`stats=0` 等价开关,避免每一页重复请求 selected/active/stats;点击/选中 task 后再按需加载 summary、prompt part、trace step、raw output 或完整 Trace。`read`/`mark all read` 应调用专用 mutation 并用后端返回的 patch 更新当前内存态,不能为了隐藏未读圆点而强制刷新完整 overview;请求仍需遵守 PostgreSQL 权威源,失败时不得本地伪造已读。Code Queue 性能问题应优先通过缩小 API 响应、分页/cursor、去重 in-flight 请求、短 TTL 且 mutation 失效的页面缓存和后端 SQL 聚合解决,避免以重写渲染层或把大 JSON 藏在 DOM/React state 中规避慢请求。 diff --git a/docs/reference/microservices.md b/docs/reference/microservices.md index 8ff01326..e725a010 100644 --- a/docs/reference/microservices.md +++ b/docs/reference/microservices.md @@ -9,7 +9,7 @@ UniDesk 用户服务是挂载到 UniDesk 核心服务上的、面向用户使用 - 用户服务后端端口默认只绑定计算节点本机地址,例如 `127.0.0.1:`,不得直接暴露公网。 - 浏览器只访问 UniDesk frontend;frontend 通过同源 `/api/microservices/*` 代理到 backend-core,backend-core 再通过目标 provider-gateway 的 `microservice.http` 能力访问计算节点本机后端。 - backend-core REST API、database 和计算节点用户服务后端都不得新增公网端口;公网入口仍只有 frontend 和 provider ingress。 -- `microservice.http` 只允许 provider-gateway 访问 `http://127.0.0.1`、`http://localhost`、`http://host.docker.internal` 这类节点本地地址;主 server 内置用户服务可使用同一 Compose 网络内的显式服务名,例如 `todo-note:4211` 或 `code-queue:4222`。backend-core 还必须用 `allowedPathPrefixes` 和 `allowedMethods` 同时限制可代理路径和 HTTP 方法。 +- `microservice.http` 只允许 provider-gateway 访问 `http://127.0.0.1`、`http://localhost`、`http://host.docker.internal` 这类节点本地地址;主 server 内置用户服务可使用同一 Compose 网络内的显式服务名,例如 `todo-note:4211`,D601 Code Queue 等计算节点服务必须使用节点本机映射。backend-core 还必须用 `allowedPathPrefixes` 和 `allowedMethods` 同时限制可代理路径和 HTTP 方法。 ## Config Contract @@ -122,26 +122,27 @@ Baidu Netdisk 在 UniDesk 语境中按纯后端服务管理:不得暴露百度 - provider-gateway 容器必须配置 `extra_hosts: ["host.docker.internal:host-gateway"]`,确保 D601/D518 Linux Docker 容器内能访问 WSL host 侧 `127.0.0.1:4251` 映射。 - UniDesk 前端:`用户服务 / File Browser` React 页面展示 D518 主目标和 D601 备用目标的健康状态、仓库引用、私有后端映射,并以 iframe 嵌入对应 File Browser WebUI;页面必须提供截图导出入口,并对上游 WebUI 注入紧凑布局样式,避免 material icon 字体异常时 `folder` 文本遮挡文件名;File Browser 自身端口不得直接暴露公网。 -### Code Queue On Main Server +### Code Queue On D601 -当前 Code Queue 作为 `id=code-queue` 的用户服务登记在 `config.json`,并接入统一 `oa-event-flow` 发布 Trace/STEP 事实事件与读取统计中心: +当前 Code Queue 作为 `id=code-queue` 的用户服务登记在 `config.json`,长期部署在 D601,并接入统一 `oa-event-flow` 发布 Trace/STEP 事实事件与读取统计中心: -- Provider:`main-server`,由本机 provider-gateway 通过 `microservice.http` 访问同一 Compose 网络内的 `http://code-queue:4222`。 +- Provider:`D601`,由 D601 provider-gateway 通过 `microservice.http` 访问 D601 本机映射 `http://host.docker.internal:4222`;容器对 D601 host 只绑定 `127.0.0.1:4222`,不得直接暴露公网。 - 代码引用:`https://github.com/pikasTech/unidesk` 与配置中的 `repository.commitId`;服务源码位于 `src/components/microservices/code-queue`,属于 UniDesk 自有控制面组件。 -- 部署引用:UniDesk 根仓库 `docker-compose.yml` 中的 `code-queue` service,Dockerfile 为 `src/components/microservices/code-queue/Dockerfile`,容器名为 `code-queue-backend`。 -- 上线纪律:Code Queue 相关的前端或后端改进必须在同一任务内正式上线并验证公网 frontend 或 live API,不能只停留在源码、构建产物或“后续再上线”。重建 `frontend` 只替换无状态 WebUI 容器,不会触碰 `code-queue-backend`、PostgreSQL 队列或运行中 Codex thread,不能以“可能影响长期任务”为由延迟前端上线;`code-queue-backend` 本身带有 restart-recovery,允许按 `server rebuild code-queue` 或 Compose 重启/替换,停止、重启或重建后必须从持久化状态恢复运行中和排队任务。修改 Code Queue 自身时不得等待当前 Code Queue task 结束、等待 queue idle 或等待 `0 running` 后才重启;这会等待自己退出形成自锁。应直接执行受 Compose lock、build-first、no-deps force-recreate 和 post-up validation 保护的重启/重建路径,并用恢复后的 live API 或公网 frontend 证明任务和队列仍可读可继续。 -- 更名与灾备恢复:旧版 Codex 队列服务名只允许作为兼容诊断和一次性迁移来源;`code-queue-backend` 容器自身 `/health` 正常但 `microservice health code-queue` 返回 `microservice not found`、或服务目录仍只出现旧服务 ID 时,优先判定为 backend-core 仍加载旧 `MICROSERVICES_JSON`,必须刷新 `.state/docker-compose.env` 并显式重建/重建替换 `backend-core`,随后用 `microservice list` 验证 `id=code-queue`、`nodeBaseUrl=http://code-queue:4222` 和容器摘要。若更名后 `unidesk_code_queue_*` 为空而历史 `unidesk_codex_queue_*` 表仍有队列数据,恢复前必须先停止 `code-queue-backend`,备份 `.state/code-queue` 与当前 `unidesk_code_queue_*` 表,再把历史本地状态目录合并到 `.state/code-queue/`,并用 `docker exec -i unidesk-database psql ...` 这类保持 stdin 的方式把 `unidesk_codex_queue_tasks`、`unidesk_codex_queue_queues` 和 `unidesk_codex_queue_notifications` 迁移到对应 `unidesk_code_queue_*` 表;不得在确认 `/api/tasks`、`/api/queues` 和 output archive 可读前删除历史本地状态目录或旧 PostgreSQL 表。迁移完成后只允许用 `docker compose --env-file .state/docker-compose.env up -d --no-deps code-queue` 或 `server rebuild code-queue` 启动目标服务,禁止在灾备窗口里无意执行会连带重建 database/backend-core 的裸 `up -d code-queue`。 -- Codex 认证:容器只从主 server 的 `/root/.codex/config.toml` 同步 Codex provider 配置到 `.state/code-queue/codex-home`,并通过运行时环境透传 `OPENAI_API_KEY`、`CRS_OAI_KEY` 等 provider 所需变量;这些 provider 环境变量必须由 `writeComposeEnv` 写入 `.state/docker-compose.env` 并由 Compose 注入,确保 `server rebuild code-queue` 的外部 Docker job runner、自重建和容器重启后不会丢失认证。新增 provider 的 `env_key` 时必须增加同类运行时透传和 Compose env 持久化,禁止把 Codex 或 MiniMax 密钥写入仓库文件。Code Queue 开发容器必须只读挂载 host 的 root SSH 目录到 `/root/.ssh`(默认 `${UNIDESK_HOST_ROOT_SSH_DIR:-/root/.ssh}`),让容器内 `git push`、`ssh -T git@github.com` 与 host 使用同一套 GitHub SSH key/known_hosts;不得把私钥复制进镜像或仓库。 +- 部署引用:UniDesk 仓库中的 `src/components/microservices/code-queue/docker-compose.d601.yml`,Dockerfile 为 `src/components/microservices/code-queue/Dockerfile`,容器名为 `code-queue-backend`;主 server 根目录 `docker-compose.yml` 不再包含 `code-queue` service。 +- 主服务依赖映射:D601 Code Queue 仍以主 PostgreSQL 为权威数据库,`DATABASE_URL` 必须指向主 server 受限端口映射;`OA_EVENT_FLOW_BASE_URL` 必须指向主 server OA Event Flow 受限端口映射;`CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL` 在 D601 上直接使用本机 ClaudeQQ 映射 `http://host.docker.internal:3290`。这些端口映射只服务 D601 运行时,必须用防火墙或等价策略限制来源,不得成为浏览器或任意公网客户端入口。 +- 上线纪律:Code Queue 相关的前端或后端改进必须在同一任务内正式上线并验证公网 frontend 或 live API,不能只停留在源码、构建产物或“后续再上线”。重建 `frontend` 只替换无状态 WebUI 容器,不会触碰 D601 `code-queue-backend`、PostgreSQL 队列或运行中 Codex thread,不能以“可能影响长期任务”为由延迟前端上线;`code-queue-backend` 本身带有 restart-recovery,允许按 D601 Compose 重启/替换,停止、重启或重建后必须从持久化状态恢复运行中和排队任务。修改 Code Queue 自身时不得等待当前 Code Queue task 结束、等待 queue idle 或等待 `0 running` 后才重启;这会等待自己退出形成自锁。应直接执行 D601 `docker compose -f src/components/microservices/code-queue/docker-compose.d601.yml up -d --build --force-recreate code-queue` 或等价 build-first 路径,并用恢复后的 live API 或公网 frontend 证明任务和队列仍可读可继续。 +- 更名与灾备恢复:旧版 Codex 队列服务名只允许作为兼容诊断和一次性迁移来源;`code-queue-backend` 容器自身 `/health` 正常但 `microservice health code-queue` 返回 `microservice not found`、或服务目录仍只出现旧服务 ID 时,优先判定为 backend-core 仍加载旧 `MICROSERVICES_JSON`,必须刷新 `.state/docker-compose.env` 并显式重建/重建替换 `backend-core`,随后用 `microservice list` 验证 `id=code-queue`、`nodeBaseUrl=http://host.docker.internal:4222` 和容器摘要。若更名后 `unidesk_code_queue_*` 为空而历史 `unidesk_codex_queue_*` 表仍有队列数据,恢复前必须先停止 `code-queue-backend`,备份 `.state/code-queue` 与当前 `unidesk_code_queue_*` 表,再把历史本地状态目录合并到 `.state/code-queue/`,并用 `docker exec -i unidesk-database psql ...` 这类保持 stdin 的方式把 `unidesk_codex_queue_tasks`、`unidesk_codex_queue_queues` 和 `unidesk_codex_queue_notifications` 迁移到对应 `unidesk_code_queue_*` 表;不得在确认 `/api/tasks`、`/api/queues` 和 output archive 可读前删除历史本地状态目录或旧 PostgreSQL 表。迁移完成后只允许在 D601 用 `docker compose -f src/components/microservices/code-queue/docker-compose.d601.yml up -d --build code-queue` 启动目标服务;禁止再通过主 server Compose 启动旧 `code-queue` service。 +- Codex 认证:容器只从 D601 的 `/home/ubuntu/.codex/config.toml` 同步 Codex provider 配置到 D601 `.state/code-queue/codex-home`,并通过 D601 `.state/code-queue-d601.env` 透传 `OPENAI_API_KEY`、`CRS_OAI_KEY` 等 provider 所需变量;这些 provider 环境变量不得写入仓库,必须由 D601 Compose env-file 注入,确保容器重建和重启后不会丢失认证。新增 provider 的 `env_key` 时必须增加同类运行时透传和 Compose env 持久化,禁止把 Codex 或 MiniMax 密钥写入仓库文件。Code Queue 容器必须只读挂载 D601 host 的 SSH 目录到 `/root/.ssh`(默认 `/home/ubuntu/.ssh`),让容器内 `git push`、`ssh -T git@github.com` 与 host 使用同一套 GitHub SSH key/known_hosts;不得把私钥复制进镜像或仓库。 - Develop-ready 镜像:Code Queue 镜像必须在启动前预装 UniDesk/Pipeline 调试所需工具,至少包含 `codex`、`bun`、`node`、`npm`/`npx`、`git`、`rg`、`curl`、`python3`/`pip3`、`docker`、`docker compose`、`docker-compose`、`jq`、`ssh`、`rsync`、`make`、`gcc`/`g++`、`tar`、`gzip` 和 `unzip`;不得依赖 Codex 任务运行时再 `apt-get install` 这些基础环境。 -- 远程开发容器与任务执行 Provider:Code Queue 必须能通过 live API 拉起 D601 等计算节点上的开发容器,入口为 `POST /api/dev-containers//start`,默认 Provider 为 `D601`。该流程由 Code Queue 调用 UniDesk `ssh ` 维护桥在目标节点创建 `unidesk-codex-dev-`,并在主 server 与开发容器之间建立 `ssh -w` TUN 点对点链路;主 server 负责对开发容器的 TUN 源地址做 NAT/MASQUERADE,开发容器默认路由和 DNS 改走该 TUN,从而让 `ping google.com`、DNS、HTTP(S) 等出网都经主 server 全局代理,而不是依赖 D601 本地网络。提交 Code Queue 任务时必须支持选择执行 Provider:`main-server` 在本机 Code Queue 容器中执行且默认工作目录保持 `/root/unidesk`;其他 Provider 在对应 `unidesk-codex-dev-` 容器中执行,默认工作目录为 `/home/ubuntu`,可按任务覆盖 `cwd`。远程任务启动前必须自动复用或拉起该 Provider 的开发容器、同步 Codex 配置和允许的运行时 provider 环境变量,并通过同一 master TUN/NAT 链路出网;目标 host 存在 `/mnt` 时,开发容器必须挂载 host `/mnt:/mnt`,确保 D601 这类 WSL 节点的 Windows 盘符路径如 `/mnt/f/Work/ConStart` 在任务容器内可见,避免 agent 因缺少真实工作区而搜索到无关项目。TUN 建立必须幂等处理 stale 状态:启动前清理旧 `tun`、默认路由和旧 tunnel SSH 进程,缺失旧设备不能导致失败,冷启动运行时准备要有有界但足够的 timeout。验收必须保留三类日志:容器直连 `google.com` 在建隧道前失败、容器建隧道后 `ping google.com` 成功、主 server 上对应 `UNIDESK-CODEX-DEV-` NAT 链或 `tun` 计数在 ping 前后增长;涉及 WSL 工作区任务时还必须在开发容器内验证目标 `/mnt/...` 路径可读。开发容器代理密钥只生成到 `.state/code-queue/dev-proxy/` 与目标节点用户目录,不得提交到仓库。 +- 远程开发容器与任务执行 Provider:Code Queue 必须能通过 live API 拉起 D601 等计算节点上的开发容器,入口为 `POST /api/dev-containers//start`,默认 Provider 为 `D601`。该流程由 Code Queue 调用 UniDesk `ssh ` 维护桥在目标节点创建 `unidesk-codex-dev-`,并在 Code Queue 所在节点与开发容器之间建立 `ssh -w` TUN 点对点链路;服务所在节点负责对开发容器的 TUN 源地址做 NAT/MASQUERADE,开发容器默认路由和 DNS 改走该 TUN,从而让 `ping google.com`、DNS、HTTP(S) 等出网都经主 server 全局代理,而不是依赖 D601 本地网络。提交 Code Queue 任务时必须支持选择执行 Provider:`D601` 在 D601 `code-queue-backend` 容器中本机执行,默认工作目录为 `/workspace`;其他 Provider 在对应 `unidesk-codex-dev-` 容器中执行,默认工作目录为 `/home/ubuntu`,可按任务覆盖 `cwd`。远程任务启动前必须自动复用或拉起该 Provider 的开发容器、同步 Codex 配置和允许的运行时 provider 环境变量,并通过同一 master TUN/NAT 链路出网;目标 host 存在 `/mnt` 时,开发容器必须挂载 host `/mnt:/mnt`,确保 D601 这类 WSL 节点的 Windows 盘符路径如 `/mnt/f/Work/ConStart` 在任务容器内可见,避免 agent 因缺少真实工作区而搜索到无关项目。TUN 建立必须幂等处理 stale 状态:启动前清理旧 `tun`、默认路由和旧 tunnel SSH 进程,缺失旧设备不能导致失败,冷启动运行时准备要有有界但足够的 timeout。验收必须保留三类日志:容器直连 `google.com` 在建隧道前失败、容器建隧道后 `ping google.com` 成功、服务所在节点上对应 `UNIDESK-CODEX-DEV-` NAT 链或 `tun` 计数在 ping 前后增长;涉及 WSL 工作区任务时还必须在开发容器内验证目标 `/mnt/...` 路径可读。开发容器代理密钥只生成到 `.state/code-queue/dev-proxy/` 与目标节点用户目录,不得提交到仓库。 - 远程 Provider 准备不得阻塞控制面:Code Queue 在请求处理、队列调度、远程开发容器准备、Host SSH/WSL SSH 透传、Codex/OpenCode 启动和日志导出路径中,禁止使用会长时间占用 Bun event loop 的同步子进程调用,例如针对远程 Provider 的 `spawnSync`、`execSync` 或 `execFileSync`。远程命令必须通过异步子进程执行,带显式 timeout、超时 kill、stdout/stderr 上限和任务 output 进度记录;远程准备失败只能让对应任务进入失败或 retry,不能让 `POST /api/tasks`、SSE `/api/events`、`/health`、overview 或前端 direct proxy 等控制面请求等待远程 SSH 结束。凡是改动 D601/远程 Provider 准备、`api/dev-containers/*`、任务入队启动或 `runCodeQueueSsh` 等路径,验收必须在一个远程 SSH/status/start 探针运行期间并发验证容器直连 `/health` 和 `/api/tasks/overview` 仍能在 1s 内返回,证明远程超时不会复发为全站刷新卡死。 - OpenCode 远程执行:`minimax-m2.7` 走 OpenCode JSON event port 时,本地和远程命令都必须显式执行 `opencode run ...`;远程 Docker exec 不得退化成 `exec run ...`,否则会在目标容器内变成 `bash: exec: run: not found`。OpenCode JSON stream 的终态判定以“当前进程退出码 + 当前 attempt 的最终 assistant response”为准:`exit=0` 且当前 attempt 产生非空最终回复时,即使上游没有发 `step_finish` 事件,也应视为正常 terminal;非零退出、无当前最终回复或传输关闭才进入 retry。每个 attempt 的 `finalResponse` 必须只来自当前 OpenCode/Codex turn,禁止在当前 turn 未产出最终回复时回退复用 task 上一次 `finalResponse`,否则会把旧任务内容误判为本轮完成。 - Codex 控制:服务内部启动 `codex app-server --listen stdio://`,用 JSON-RPC 调用 `thread/start`、`turn/start`、`turn/steer` 和 `turn/interrupt`,并监听 `turn/completed`、assistant delta、reasoning delta、command output delta、file diff delta 等通知生成前端可轮询的 transcript。 - 用户输入持久化:任务初始 prompt 以 `basePrompt/displayPrompt` 作为结构化来源,运行中追加的 `turn/steer` prompt 必须写入 `promptHistory`;transcript 构建时从这些结构化字段合成 `Submitted prompt` 和 `Steer prompt`,不能只依赖有 600 条上限的 raw output,否则长任务输出增长后会丢失关键人工指令。 - 队列语义:`POST /api/tasks` 或 `/api/tasks/batch` 入队,服务始终只运行一个 Codex turn;当前任务真正终止后才推进下一个任务。`GET /api/tasks` 与 `GET /api/tasks/{id}` 返回队列、attempt、judge 和输出;`GET /api/tasks/{id}/summary` 返回按任务 ID 查询的结构化摘要,包括初始 prompt、最后 assistant message、工具调用摘要、attempt、judge、错误和耗时;CLI 入口是 `bun scripts/cli.ts codex task `。`GET|POST /api/tasks/{id}/judge?attempt=N` 与 CLI `bun scripts/cli.ts codex judge --attempt N` 用于单步复现指定 attempt 的 judge,必须复用真实队列 worker 的上下文构建、prompt 压缩、MiniMax 调用、JSON 去噪/repair 和 fallback 路径;`dryRun=1`/`--dry-run` 只输出 prompt/payload 和重建诊断,不调用 MiniMax。`POST /api/tasks/{id}/steer` 向运行中 turn 推入 prompt;`POST /api/tasks/{id}/interrupt` 或 `DELETE /api/tasks/{id}` 打断/取消;`POST /api/tasks/{id}/retry` 手动重试。队列 worker 必须隔离单个 task 的异常,不能因为某个 app-server、judge 异常或 judge 判定 `fail` 让后续 queued 任务停止;`fail` 只把当前任务标为 failed,随后必须继续扫描并推进下一个 queued/retry_wait 任务。当存在 queued/retry_wait 且 worker 空闲时,watchdog 必须自动重新调度。 -- 稳定性与重启恢复:Code Queue 的第一目标是长期稳定可用;部署修复或运维排障时不得因为担心容器重启会打断任务而拒绝重启、重建或替换 `code-queue-backend`。容器重启、服务进程重启和镜像替换后,队列、`promptHistory`、running/judging/retry_wait 任务和 active session 元数据必须从 PostgreSQL 恢复,并在已有 `codexThreadId` 可用时用 `thread/resume` 和 continuation prompt 无缝继续当前任务;如果原 app-server turn 已丢失,也必须把当前任务恢复到可 retry/continue 的状态,不能错误推进下一个任务或永久卡住。主 server 侧重建必须走 `server rebuild code-queue`,该 job 受 `.state/locks/server-compose.lock` 串行化约束,并且必须在 build 后执行 no-deps force-recreate 与 post-up health validation;禁止在 job 中先手工 `docker rm` 再依赖后续命令补救,因为中断窗口会让容器消失并触发 frontend `direct microservice proxy failed`。重启后出现 active task 丢失、手动 steer/interrupt 记录丢失、running 任务卡死、误判完成、跳过当前任务、容器消失或阻塞队列,均属于 Code Queue 的 P0 核心缺陷,必须先修复并补充 restart-recovery 验收,不能把“避免重启”作为交付策略。 +- 稳定性与重启恢复:Code Queue 的第一目标是长期稳定可用;部署修复或运维排障时不得因为担心容器重启会打断任务而拒绝重启、重建或替换 `code-queue-backend`。容器重启、服务进程重启和镜像替换后,队列、`promptHistory`、running/judging/retry_wait 任务和 active session 元数据必须从 PostgreSQL 恢复,并在已有 `codexThreadId` 可用时用 `thread/resume` 和 continuation prompt 无缝继续当前任务;如果原 app-server turn 已丢失,也必须把当前任务恢复到可 retry/continue 的状态,不能错误推进下一个任务或永久卡住。D601 侧重建必须走 `src/components/microservices/code-queue/docker-compose.d601.yml`,并且必须在 build 后执行 force-recreate 与 post-up health validation;禁止先手工 `docker rm` 再依赖后续命令补救,因为中断窗口会让容器消失并触发 frontend `direct microservice proxy failed`。重启后出现 active task 丢失、手动 steer/interrupt 记录丢失、running 任务卡死、误判完成、跳过当前任务、容器消失或阻塞队列,均属于 Code Queue 的 P0 核心缺陷,必须先修复并补充 restart-recovery 验收,不能把“避免重启”作为交付策略。 - 调度与 active run slot:Code Queue 必须把“queue processor 正在等待/退避/轮询”和“实际占用 Codex/OpenCode 子进程运行槽”分开建模;`CODE_QUEUE_MAX_ACTIVE_QUEUES` 只限制真实 active run slot,不能把 retry backoff、等待内存下降或等待前序任务的 `processingQueues` 计入 active slot,否则设置全局 active slot 上限时,一个空等队列会把其他 runnable queue 永久饿死。多个 queue 同时等待 active slot 时必须显式维护 FIFO waiter 队列,避免某个长 retry/backoff 队列刚释放 slot 就立刻重抢,导致更早进入等待的 `retry_wait` 任务长期饥饿;`/health` 必须同时暴露真实 `activeQueueIds`、`activeRunSlotCount`、等待中的 `processingQueueIds` 和 active slot waiters,排障时以 active run slot 与 waiter 顺序判断是否真的有任务在跑、谁应下一个启动。restart-recovery 后的 `retry_wait` 任务若缺失 `codexThreadId`/OpenCode session id,不得无限拒绝 retry;必须用紧凑 recovery prompt 和原始任务摘要重新开一个 agent thread/session,让任务继续推进并在 Trace 中留下 recovery 证据。任何修改 scheduler、retry backoff、queue move、manual retry、shutdown recovery 或内存等待逻辑时,都必须保留“空等 processor 不占 active run slot”、“等待者 FIFO 不饥饿”和“缺失 thread/session 可恢复”的自测或 live 验证。 -- 内存优化过程与防回归:主 server 内存预算很小,Code Queue 的内存治理必须按“PostgreSQL 权威源优先、进程热状态最小化、容器硬上限兜底”的顺序设计。长期可复用的优化路径是:先确认任务、queue、readAt、promptHistory、active session 和通知 outbox 均可从 PostgreSQL 恢复;再把历史任务列表、详情、统计、Trace/output 和 `/health` 的只读查询改为 PostgreSQL 直读或聚合查询;随后只把 `queued`、`running`、`judging`、`retry_wait` 等调度必需任务载入 Bun 堆,并在 PostgreSQL 查询侧裁剪 hot `output`/`events`;最后用 dirty-only flush、append-only 输出归档、Codex SQLite 小批量导出、`bun --smol`、`mem_limit=600m`、`memswap_limit=1536m`、`NODE_OPTIONS=--max-old-space-size=768` 和 cgroup memory watchdog 作为运行时防线。PostgreSQL 到进程的单次读取足够快,不能为了减少 SQL 查询把全部历史 `task_json`、Trace、output 或统计摘要常驻内存;任何新增缓存都必须有默认较小的环境变量上限、明确淘汰策略、可从 PostgreSQL 或 append-only 归档重建,且不得影响重启恢复。新增或修改 `/api/tasks`、overview、stats、summary、transcript、output、trace、health、flush、scheduler 和通知路径时,禁止在常规请求中调用会物化全量历史任务 JSON 的代码,禁止启动后无条件重写全量历史 task JSON,禁止用未设上限的 `Map`/数组保存历史 output/event/Trace,`CODE_QUEUE_MAX_ACTIVE_QUEUES=0` 表示不按 queue 数量设置全局排队上限;如显式设置为正数,必须同时说明内存预算并补充内存压测验收。memory watchdog 必须以 cgroup working set 为主要判断,且在 swap 仍有余量时不得提前杀掉唯一 active run;否则 TypeScript/Playwright 这类短时高内存验证会被错误中断并让 retry 队列反复震荡。 +- 内存优化过程与防回归:Code Queue 已迁移到 D601,但内存治理仍必须按“PostgreSQL 权威源优先、进程热状态最小化、容器硬上限兜底”的顺序设计。长期可复用的优化路径是:先确认任务、queue、readAt、promptHistory、active session 和通知 outbox 均可从 PostgreSQL 恢复;再把历史任务列表、详情、统计、Trace/output 和 `/health` 的只读查询改为 PostgreSQL 直读或聚合查询;随后只把 `queued`、`running`、`judging`、`retry_wait` 等调度必需任务载入 Bun 堆,并在 PostgreSQL 查询侧裁剪 hot `output`/`events`;最后用 dirty-only flush、append-only 输出归档、Codex SQLite 小批量导出、`bun --smol`、`mem_limit=600m`、`memswap_limit=1536m`、`NODE_OPTIONS=--max-old-space-size=768` 和 cgroup memory watchdog 作为运行时防线。PostgreSQL 到进程的单次读取足够快,不能为了减少 SQL 查询把全部历史 `task_json`、Trace、output 或统计摘要常驻内存;任何新增缓存都必须有默认较小的环境变量上限、明确淘汰策略、可从 PostgreSQL 或 append-only 归档重建,且不得影响重启恢复。新增或修改 `/api/tasks`、overview、stats、summary、transcript、output、trace、health、flush、scheduler 和通知路径时,禁止在常规请求中调用会物化全量历史任务 JSON 的代码,禁止启动后无条件重写全量历史 task JSON,禁止用未设上限的 `Map`/数组保存历史 output/event/Trace,`CODE_QUEUE_MAX_ACTIVE_QUEUES=0` 表示不按 queue 数量设置全局排队上限;如显式设置为正数,必须同时说明内存预算并补充内存压测验收。memory watchdog 必须以 cgroup working set 为主要判断,且在 swap 仍有余量时不得提前杀掉唯一 active run;否则 TypeScript/Playwright 这类短时高内存验证会被错误中断并让 retry 队列反复震荡。 - 列表/详情延迟优化原则:Code Queue 控制面交互的长期目标是常规历史规模下首屏、`GET /api/tasks/overview`、`POST /api/tasks//read` 和分页加载均在 1s 内完成;性能面板出现十几秒级 `code_queue_direct_proxy` 或 `core_proxy` 慢操作时,必须优先按后端查询形态和前后端通信策略定位,不能把问题归因于 React 渲染后只改 UI。后端优化顺序是:先为 queue、status、updated/created 时间、readAt/terminal unread 和常用筛选条件补齐 PostgreSQL 索引;再用 SQL `COUNT`、`GROUP BY`、条件聚合和分页 ID 查询生成 queue/status/stats/unread 摘要;随后按 ID 轻量加载当前页、selected、active 和 unread priority task,禁止为了列表或已读操作解析完整 Trace、output archive、Codex transcript 或物化全量历史 `task_json`。`read`/`read-all` 这类 mutation 必须是 SQL-only 更新并返回最小 patch/queue 计数,不能触发 overview 全量重算或重载所有任务;启动 warm 只能预热小体积聚合和索引路径,不得把历史任务作为常驻缓存。允许 frontend/backend 代理使用秒级、严格有界、mutation 自动失效的 overview micro-cache 来吸收重复刷新,但 cache 只能作为抖动保护,不能替代数据库索引、聚合查询和分页披露,也不能让 stale readAt/queue/status 状态跨设备可见。 - Trace/实时输出热路径防回归:Code Queue 的 `appendOutput`、output archive append、`publishTaskEvent`、SSE `/api/events`、任务列表、overview、task meta 和 `/health` 都属于热路径,必须保持 O(1) 或明确小常数上界;这些路径不得同步调用完整 transcript 构建器、`taskFullOutput`、output archive 全量读取、Codex session/log 文件解析、完整 `task_json` 物化或任何会随历史输出长度增长的统计。输出追加时必须增量维护轻量持久化指标,至少包括 `stepCount`、`llmStepCount`、`outputMaxSeq` 或等价字段;列表、overview、meta、SSE 事件和 `/health` 只能读取这些指标或小体积 SQL 聚合。完整 Trace、`trace-summary`、`trace-steps`、`trace-step`、transcript/output 详情允许在显式详情请求中解析归档,但必须分页或有界、使用短 TTL 或容量受限缓存,并在 archive append 后失效。若 frontend 性能面板出现 Code Queue direct proxy 502、`/api/tasks/overview`/trace 接口成批超时,或容器内 `/health` 在 active output 持续追加时也卡住,优先按 Bun event-loop starvation/backpressure 排查,而不是先改 React 渲染;修复必须证明热路径不再随 output/archive 历史线性增长。 - 完成判定:app-server `turn/completed` 的 `turn.status=completed|interrupted|failed` 只代表 Codex turn 已结束;即使 `completed` 也必须把原始任务、当前 attempt 的 assistant 最终回复、command/file-change 事件、stderr tail 和 current attempt events 组成 execution record 交给 judge 判断是否真的完成。MiniMax judge 输入必须做有界压缩,保留终态、最终回复、关键错误/命令/部署证据和摘要计数,避免长 transcript 让 MiniMax 请求超时;默认 `UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_TIMEOUT_MS=90000`。MiniMax judge 之前和之后都必须保留少量协议级硬门禁:明确用户 interrupt 判为 fail;当前 attempt `terminalStatus=failed|null`、传输在终态前关闭、或当前 attempt 最终回复为空时判为 retry;这些门禁只保护“本轮 turn 是否可被验收”的事实,不得发明业务实现要求。协议门禁通过后,配置了 `UNIDESK_CODE_QUEUE_MINIMAX_API_KEY` 且 MiniMax 可用时,MiniMax `MiniMax-M2.7` 对业务是否 `complete|retry|fail` 的判定是权威结果;当且仅当 MiniMax LLM 调用失效(未配置、额度/限流/网络/超时不可用、JSON 去噪与 repair 全部耗尽、或返回超预算反馈且修复耗尽)时,才允许启用非 LLM/fallback 判断。MiniMax 返回必须先做 JSON 去噪,支持去除 Markdown fence、`json` 标签和从夹杂文本中提取平衡 JSON object;如果去噪后仍无法解析,服务必须把解析错误和上一轮去噪前原始回答反馈给 MiniMax 做 JSON repair 重试,重试次数由 `UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_REPAIR_ATTEMPTS` 控制,默认 `2`,耗尽后才进入 fallback,并在 fallback 原因、task JSON、attempt summary 和 TraceView 中保留 MiniMax 失败阶段、是否超时、耗时、prompt/payload 大小、HTTP 状态、错误名和响应预览。 @@ -149,9 +150,9 @@ Baidu Netdisk 在 UniDesk 语境中按纯后端服务管理:不得暴露百度 - Retry/推进语义:`retry` 不是新开一个独立任务或完全新 session;只要已有 `codexThreadId`,服务必须 `thread/resume` 原 thread 并 append 一个继续执行 prompt。continuation/judge feedback prompt 只应携带本轮缺口、恢复原因、验收要求和有界原始任务摘要,禁止重新注入完整引用上下文、历史 transcript 或长 JSON;服务重启恢复类 feedback 尤其必须保持短 prompt,依赖现有 thread 上文继续。超长 prompt 必须在 prompt 合成源头解决:每个 feedback/recovery/judge 生成器都要从结构化字段选择必要信息、去重合并缺口并提供按需查询入口,禁止先合成超长 prompt 再在末端用 substring/safePreview 一刀切硬截断;硬截断会静默丢失验收信息,风险高于长 prompt 本身。若 MiniMax `continuePrompt` 超出预算,必须要求 MiniMax 基于原始 judge 输入重新合成紧凑反馈,repair 耗尽后才可进入 fallback;不得把已生成的长 prompt 截尾后发送给 Codex。若 MiniMax 成功返回了预算内 `continuePrompt`,必须原样使用该反馈,不得再用 71-Freq、`period_sum/mpu_read_num`、`mpu_read_num`、历史限流中断等字符串识别把它覆盖成“简洁原始需求 continuation”。只有 judge 判定 `complete` 后,队列 worker 才把当前任务标为成功并推进下一个 queued/retry_wait 任务。非 LLM/fallback 判定产生的 `retry` 最多累计 `3` 次;达到上限后当前任务必须转为 `failed` 并记录原因,worker 继续推进后续 queued/retry_wait 任务,避免 fallback safety override 或硬编码判断造成无限循环。 - Judge 探针与复现:`GET|POST /api/judge/probe` 使用同一套 judge 逻辑跑内置 synthetic execution records,覆盖正常完成、正常结束但只给计划、未上线/未部署的服务或 WebUI 改动、传输中断和用户打断等样本,返回 `hits`、`total`、`hitRate`、每例 `expected` 与 `decision`;该接口不得回显 MiniMax API key。真实任务排障必须优先使用 `codex judge --attempt N` 或 `/api/tasks/{id}/judge?attempt=N`,响应要包含 attempt 窗口、promptChars/payloadBytes、stored judge 对比、MiniMax 失败阶段和是否因历史 per-attempt events 缺失而降级为 retained events 重建。 - 模型选择:默认 Codex 模型是 `gpt-5.5`,内置模型队列包含 `gpt-5.5`、`gpt-5.4-mini`、`gpt-5.4`;`gpt-5.5` 的默认 reasoning effort 必须是 `xhigh`,可通过 `CODE_QUEUE_MODEL_REASONING_EFFORTS` 追加或覆盖模型级默认值;每个入队任务可通过前端模型下拉菜单或 API 覆盖 `model`、`cwd`、`reasoningEffort` 和 `maxAttempts`,`maxAttempts` 上限为 `99`。Judge 判定 `retry` 或非用户取消类 `fail` 时必须继续已有 `codexThreadId`,不能新建 session;重试间隔使用指数退避,从 `1s` 开始,最大 `10min`。MiniMax 不可用而进入 fallback/non-LLM 判定时,当前 attempt 的 429、Too Many Requests、exceeded retry limit、overloaded、stream disconnected 等服务/限流错误应判定为 `retry`,不能当作完成;MiniMax 可用时,这些内容只能作为当前 attempt 的 factual evidence 提供给 MiniMax,不能通过硬编码覆盖 MiniMax 结果。 -- 状态与日志:`main-server` 默认工作目录为容器内 `/root/unidesk`,该路径映射主 server 的 `~/unidesk`;同时保留 `/workspace` 映射以兼容历史任务。非主 server Provider 的任务默认工作目录为 `/home/ubuntu`,任务 JSON、列表、Trace 摘要和 CLI 查询都必须显示 `providerId`、`executionMode` 与最终 `cwd`。`executionMode=default` 沿用主 server 本机 Codex 或远程执行容器 Codex;`executionMode=windows-native` 只允许非主 server WSL Provider、Codex 模型和 `/mnt/` 工作目录,Code Queue 仍会启动远程执行容器,但容器只运行 stdio relay,经 WSL bridge 调用 Windows 宿主原生 `codex app-server --listen stdio://`,避免公网/main-server 到 Provider 的临时断连直接杀死 Windows Codex 进程。Code Queue 的任务、queue、`readAt`/未读状态、attempt、judge、`promptHistory`、active session 元数据、控制状态和 ClaudeQQ 通知 outbox 一律以主 PostgreSQL 为权威,分别写入 `unidesk_code_queue_tasks`、`unidesk_code_queue_queues` 与 `unidesk_code_queue_notifications`;`DATABASE_URL` 是必需配置,服务不得在 PostgreSQL 缺失或不可用时进入文件存储模式。`.state/code-queue/state.json` 不再作为任务或 queue 状态存储,不得重新引入本地 JSON fallback;服务启动必须以 PostgreSQL 为唯一来源恢复队列,并把 running/judging 任务恢复为 retry_wait。主 server 内存很少,Code Queue 必须把“内存是稀缺资源”作为核心设计约束:历史任务列表、详情、统计和只读 Trace 查询优先从 PostgreSQL 直读,进程内只保留当前 running/judging、queued、retry_wait 等调度必需热任务,不得把全部历史 task JSON 长期缓存到 Bun 堆;需要短期热缓存时必须有严格上限、可裁剪、可从 PostgreSQL 和 append-only 输出归档重建。WebUI 不得用 browser `localStorage`、`sessionStorage` 或 IndexedDB 持久化 task/queue/readAt/unread 等业务状态;浏览器只能保留临时 UI 内存缓存,刷新后必须重新从后端读取 PostgreSQL 权威数据。Codex CLI-like output/Trace 的完整记录可以使用 append-only 文件作为日志型归档,但任务状态、未读状态和列表摘要不得依赖这些文件作为权威来源;`/api/tasks//transcript` 与 `/api/tasks//output` 必须能分页重建完整历史,不得因为热状态裁剪而丢失早期 trace。热 task JSON 只保留可配置窗口以保证 `/health`、`/api/tasks` 和 PostgreSQL flush 不被长任务拖死;主 server 为 Code Queue 放宽到 600M 容器预算后仍默认 `CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS=10`、`CODE_QUEUE_IN_MEMORY_EVENT_RECORDS=10`,启动时必须在 PostgreSQL 查询侧裁剪 hot output/events,并只 flush dirty task,禁止启动后无条件重写全量历史 task JSON;更高预算才允许调大热窗口。WebUI 必须支持多 queue 查看、显式创建 queue、提交时下拉选择 queue、提交时下拉选择执行 Provider 和执行模式,并支持把已创建且非 active 的任务移动到其他 queue;queue 内串行,queue 间默认并行且不互相排队;`CODE_QUEUE_MAX_ACTIVE_QUEUES` 仅作为显式配置的全局 active slot 上限,`0` 表示不按 queue 数量限流,内存不足时由 cgroup memory pressure 阻止新 run 并在任务响应中暴露 `QUEUED(MEM LIMIT)`。Code Queue 镜像必须内置 Playwright Chromium 浏览器与系统依赖,并使用 `bun --smol` 运行后端,保证队列任务能直接执行公网 frontend Playwright 回归且主进程内存可控,不得只在宿主机临时安装。日志写入 UniDesk `logs/{YYYYMMDD}/{startStamp}_{YYYYMMDD}_{HH}_code-queue.jsonl`,按小时切片并按日志族默认保留 `1GiB`;Codex app-server 上游产生的 `logs_*.sqlite` 只能作为短暂缓冲,必须由 Code Queue 周期性导出为 `logs/{YYYYMMDD}/{startStamp}_{YYYYMMDD}_{HH}_codex-app-server.jsonl`,导出后删除/压缩已导出的 SQLite 行,避免重新形成 `logs_2.sqlite` 大文件;`/logs` 端点返回最近结构化日志。`/health` 的 `queue.storage.primary` 必须恒为 `postgres`,并通过 `queue.storage.postgresReady`、`queue.devReady` 和 `/api/dev-ready` 暴露 PostgreSQL 可用性、develop-ready 自检、必需工具、Docker socket、`docker compose`、默认工作目录、Codex config 状态和 `/root/.ssh` 共享 SSH key 状态。Codex CLI-like 输出可能很大,服务必须节流状态持久化,禁止对每个 output delta 同步重写完整 state 导致 `/health` 和控制 API 卡死;容器 healthcheck 必须使用带超时的 HTTP 探针,不能留下堆积的无超时探针进程。 -- ClaudeQQ 通知:Code Queue 可通过 backend-core 的 `claudeqq` 用户服务代理调用 `POST /api/push/text`,在每个任务进入 `succeeded`、`failed` 或 `canceled` 终态后向配置目标发送最终 response,并附带 task id、queue、状态、模型、attempt、当前 running/queued/retry_wait 数和任务总耗时;当所有 queue 进入 `0 running / 0 queued` 空闲态时,必须单独发送一次空闲提醒。通知由 `CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED` 控制,目标由 `CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE=private|group`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID` 配置,默认私聊 `645275593`;代理基址、最终 response 最大字符数、单次超时和发送尝试次数分别由 `CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS` 和 `CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS` 配置。任务终态和队列空闲通知必须先写入 PostgreSQL outbox 表 `unidesk_code_queue_notifications` 再异步发送;不得使用 `.state/code-queue/claudeqq-notifications.json`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_OUTBOX_PATH` 或任何本地 JSON 作为通知权威存储。发送失败、NapCat 离线、代理 502 或容器重启时不能丢通知,必须按 `CODE_QUEUE_NOTIFY_CLAUDEQQ_RETRY_INTERVAL_MS` 指数退避重试并跨进程/容器重启保留。`/health` 的 `queue.notifications.claudeqq` 必须暴露非敏感配置、目标配置状态和 PostgreSQL outbox 统计;`GET /api/notifications/claudeqq` 返回 outbox 明细,`POST /api/notifications/claudeqq/drain` 手动触发发送,`POST /api/notifications/claudeqq/backfill` 可按 `since` 补入某次故障窗口内已终态任务,确保 QQ/NapCat 超时或离线不会让任务完成通知永久丢失。 -- OA 接入:Code Queue 后端通过 `OA_EVENT_FLOW_BASE_URL=http://oa-event-flow:4255` 发布每个 TraceView 可见执行行的 `trace-step-created`、幂等种子/乱序校正用 `trace-stats-snapshot`、`task-updated` 和 queue 事件;服务启动或手动 backfill 时必须用相同 `eventId` 幂等回放历史 TraceView 可见执行行,避免历史任务停留在旧 STEP 统计口径。前端通过 `oa-event-flow` 的 `service:code-queue` tag stream 更新 STEP 和 Trace Summary,Code Queue 私有 SSE 不再作为刷新权威。`STEP` 表示 TraceView 可见且非 system 的执行行数;system 行可保留在任务原始输出/数据库中,但默认不展示、不计入 STEP,工具调用数必须由 `readCount+editCount+runCount` 展示,不能复用 `stepCount`。 +- 状态与日志:`D601` 默认工作目录为容器内 `/workspace`,该路径映射 D601 上的 Code Queue 部署工作树;其他 Provider 的任务默认工作目录为 `/home/ubuntu`,任务 JSON、列表、Trace 摘要和 CLI 查询都必须显示 `providerId`、`executionMode` 与最终 `cwd`。`executionMode=default` 在 D601 本机 Code Queue 容器中运行 Codex/OpenCode;`executionMode=windows-native` 只允许非本机 WSL Provider、Codex 模型和 `/mnt/` 工作目录,Code Queue 仍会启动远程执行容器,但容器只运行 stdio relay,经 WSL bridge 调用 Windows 宿主原生 `codex app-server --listen stdio://`。Code Queue 的任务、queue、`readAt`/未读状态、attempt、judge、`promptHistory`、active session 元数据、控制状态和 ClaudeQQ 通知 outbox 一律以主 PostgreSQL 为权威,分别写入 `unidesk_code_queue_tasks`、`unidesk_code_queue_queues` 与 `unidesk_code_queue_notifications`;`DATABASE_URL` 是必需配置,服务不得在 PostgreSQL 缺失或不可用时进入文件存储模式。`.state/code-queue/state.json` 不再作为任务或 queue 状态存储,不得重新引入本地 JSON fallback;服务启动必须以 PostgreSQL 为唯一来源恢复队列,并把 running/judging 任务恢复为 retry_wait。D601 资源比主 server 宽裕,但 Code Queue 仍必须把“内存是稀缺资源”作为核心设计约束:历史任务列表、详情、统计和只读 Trace 查询优先从 PostgreSQL 直读,进程内只保留当前 running/judging、queued、retry_wait 等调度必需热任务;需要短期热缓存时必须有严格上限、可裁剪、可从 PostgreSQL 和 append-only 输出归档重建。WebUI 不得用 browser `localStorage`、`sessionStorage` 或 IndexedDB 持久化 task/queue/readAt/unread 等业务状态;浏览器只能保留临时 UI 内存缓存,刷新后必须重新从后端读取 PostgreSQL 权威数据。Codex CLI-like output/Trace 的完整记录可以使用 append-only 文件作为日志型归档,但任务状态、未读状态和列表摘要不得依赖这些文件作为权威来源;`/api/tasks//transcript` 与 `/api/tasks//output` 必须能分页重建完整历史,不得因为热状态裁剪而丢失早期 trace。WebUI 必须支持多 queue 查看、显式创建 queue、提交时下拉选择 queue、提交时下拉选择执行 Provider 和执行模式,并支持把已创建且非 active 的任务移动到其他 queue;queue 内串行,queue 间默认并行且不互相排队;`CODE_QUEUE_MAX_ACTIVE_QUEUES` 仅作为显式配置的全局 active slot 上限,`0` 表示不按 queue 数量限流,内存不足时由 cgroup memory pressure 阻止新 run 并在任务响应中暴露 `QUEUED(MEM LIMIT)`。Code Queue 镜像必须内置 Playwright Chromium 浏览器与系统依赖,并使用 `bun --smol` 运行后端,保证队列任务能直接执行公网 frontend Playwright 回归且主进程内存可控。日志写入 D601 `.state/code-queue/logs` 挂载的 UniDesk JSONL 日志;Codex app-server 上游产生的 `logs_*.sqlite` 只能作为短暂缓冲,必须由 Code Queue 周期性导出为 JSONL,避免重新形成大 SQLite 文件;`/logs` 端点返回最近结构化日志。`/health` 的 `queue.storage.primary` 必须恒为 `postgres`,并通过 `queue.storage.postgresReady`、`queue.devReady` 和 `/api/dev-ready` 暴露 PostgreSQL 可用性、develop-ready 自检、必需工具、Docker socket、`docker compose`、默认工作目录、Codex config 状态和 `/root/.ssh` 共享 SSH key 状态;D601 本机默认执行不要求容器内存在 SSH 私钥,只有跨 Provider SSH 或 `windows-native` 任务需要 `queue.devReady.ssh.ready=true`。Codex CLI-like 输出可能很大,服务必须节流状态持久化,禁止对每个 output delta 同步重写完整 state 导致 `/health` 和控制 API 卡死;容器 healthcheck 必须使用带超时的 HTTP 探针,不能留下堆积的无超时探针进程. +- ClaudeQQ 通知:Code Queue 在 D601 上通过 `CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL=http://host.docker.internal:3290` 直接调用本机 ClaudeQQ 后端 `POST /api/push/text`,在每个任务进入 `succeeded`、`failed` 或 `canceled` 终态后向配置目标发送最终 response,并附带 task id、queue、状态、模型、attempt、当前 running/queued/retry_wait 数和任务总耗时;当所有 queue 进入 `0 running / 0 queued` 空闲态时,必须单独发送一次空闲提醒。通知由 `CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED` 控制,目标由 `CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE=private|group`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID` 配置,默认私聊 `645275593`;代理基址、最终 response 最大字符数、单次超时和发送尝试次数分别由 `CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS` 和 `CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS` 配置。任务终态和队列空闲通知必须先写入 PostgreSQL outbox 表 `unidesk_code_queue_notifications` 再异步发送;不得使用 `.state/code-queue/claudeqq-notifications.json`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_OUTBOX_PATH` 或任何本地 JSON 作为通知权威存储。发送失败、NapCat 离线、代理 502 或容器重启时不能丢通知,必须按 `CODE_QUEUE_NOTIFY_CLAUDEQQ_RETRY_INTERVAL_MS` 指数退避重试并跨进程/容器重启保留。`/health` 的 `queue.notifications.claudeqq` 必须暴露非敏感配置、目标配置状态和 PostgreSQL outbox 统计;`GET /api/notifications/claudeqq` 返回 outbox 明细,`POST /api/notifications/claudeqq/drain` 手动触发发送,`POST /api/notifications/claudeqq/backfill` 可按 `since` 补入某次故障窗口内已终态任务,确保 QQ/NapCat 超时或离线不会让任务完成通知永久丢失。 +- OA 接入:Code Queue 后端通过 D601 env-file 中的 `OA_EVENT_FLOW_BASE_URL` 指向主 server OA Event Flow 受限端口映射,发布每个 TraceView 可见执行行的 `trace-step-created`、幂等种子/乱序校正用 `trace-stats-snapshot`、`task-updated` 和 queue 事件;服务启动或手动 backfill 时必须用相同 `eventId` 幂等回放历史 TraceView 可见执行行,避免历史任务停留在旧 STEP 统计口径。前端通过 `oa-event-flow` 的 `service:code-queue` tag stream 更新 STEP 和 Trace Summary,Code Queue 私有 SSE 不再作为刷新权威。`STEP` 表示 TraceView 可见且非 system 的执行行数;system 行可保留在任务原始输出/数据库中,但默认不展示、不计入 STEP,工具调用数必须由 `readCount+editCount+runCount` 展示,不能复用 `stepCount`。 - 代理路径:只允许 `/health`、`/logs` 和 `/api/` 前缀;允许方法为 `GET`、`HEAD`、`POST`、`DELETE`、`PATCH`。Code Queue 只在 Compose 内网暴露 `4222/tcp`,不得映射或开放到公网。 - UniDesk 前端:`用户服务 / Code Queue` React 页面负责展示队列卡片、任务 ID、复制任务 ID、引用按钮、任务耗时、默认模型、模型下拉、执行 Provider 下拉、执行模式下拉、Provider/模式对应默认工作目录、显式入队份数、引用任务 ID、清空输入、创建成功提示、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、追加 prompt、打断和手动重试控件;选择 `windows-native` 时应优先切到支持 Windows 原生 Codex 的非主 server Provider,并把工作目录提示切到 `/mnt/` 默认路径;整个 agent loop 消息流统一命名为专有名词 `Trace`,`Trace` 包含 assistant message、user prompt、system event 和 tool call;Code Queue 与 Pipeline/OpenCode messages 必须共用 `src/components/frontend/src/trace.tsx` 的 Trace 公共组件、统一 Trace item 接口和 codex/opencode port 适配层;连续 read/edit/run 工具调用只是在 Trace 内折叠为可展开工具调用组,汇总格式至少包含 `xx read, xx edit, xx run`,并展示读取文件、编辑文件、运行命令和耗时摘要;最近 3 个工具调用保持展开,工具调用内容不得自动换行且必须在工具调用块内部横向滚动,工具调用组展开后不得再增加额外左侧缩进;message 与 prompt 必须自动换行,普通 message 不显示左侧项目符号缩进且永不折叠;点击队列卡片引用按钮必须自动把该任务 ID 写入提交表单的引用任务 ID 输入框;引用任务 ID 创建新任务时必须自动注入 `bun scripts/cli.ts codex task ` 的提示,让 Codex 读取初始 prompt、最后消息和工具摘要后继续;连续执行同一 prompt 应使用 `入队份数` 一次性生成多条队列任务,而不是依赖快速连点按钮;左侧 queue/session 卡片的 `QUEUED` 状态必须显示原因,例如 `QUEUED(PREV TASK)`、`QUEUED(MEM LIMIT)`、`QUEUED(ACTIVE LIMIT)`;原始任务 JSON 只能通过显式 `查看原始JSON` 打开。 @@ -258,7 +259,7 @@ ClaudeQQ 在 UniDesk 语境中按消息网关后端服务管理:不得直接 - `bun scripts/cli.ts microservice health claudeqq`、`bun scripts/cli.ts microservice proxy claudeqq /api/napcat/login`、`bun scripts/cli.ts microservice proxy claudeqq /api/events/recent` 和 `bun scripts/cli.ts microservice proxy claudeqq /api/events/subscriptions`:验证 ClaudeQQ 后端、NapCat 容器登录、事件订阅和私有代理链路;消息推送使用 `POST /api/push/text`,不得开放 D601 `3290/3000/3001/6099` 公网端口。 - `bun scripts/cli.ts microservice health todo-note` 与 `bun scripts/cli.ts microservice proxy todo-note /api/instances`:验证主 server Todo Note 后端、PostgreSQL 存储和本机 provider-gateway 私有代理链路。 - `bun scripts/cli.ts microservice health oa-event-flow`、`bun scripts/cli.ts microservice proxy oa-event-flow /api/diagnostics --raw` 与 `bun scripts/cli.ts microservice proxy oa-event-flow '/api/events?tags=service:code-queue&limit=20' --raw`:验证统一 OA 事件流、事件表、tag 查询和统计中心。 -- `bun scripts/cli.ts microservice health code-queue` 与 `bun scripts/cli.ts microservice proxy code-queue /api/tasks`:验证主 server Code Queue 后端、PostgreSQL 强制持久化、统一 OA 事件发布和本机 provider-gateway 私有代理链路;写入、追加 prompt、打断和 readAt/未读状态都必须由 backend 写入 PostgreSQL,frontend 不得用本地存储伪造成功状态。 +- `bun scripts/cli.ts microservice health code-queue` 与 `bun scripts/cli.ts microservice proxy code-queue /api/tasks`:验证 D601 Code Queue 后端、主 PostgreSQL 强制持久化、统一 OA 事件发布和 D601 provider-gateway 私有代理链路;写入、追加 prompt、打断和 readAt/未读状态都必须由 backend 写入 PostgreSQL,frontend 不得用本地存储伪造成功状态。 - `bun scripts/cli.ts microservice health filebrowser`、`bun scripts/cli.ts microservice health filebrowser-d601` 与 `bun scripts/cli.ts microservice proxy filebrowser / --max-body-bytes 2000`:验证 D518 主 File Browser 和 D601 备用 File Browser 私有代理链路;浏览器 WebUI 必须通过 `/api/microservices/filebrowser/proxy/` 或 `/api/microservices/filebrowser-d601/proxy/` 访问,不得直接开放 `4251` 公网端口。 - `bun scripts/cli.ts --main-server-ip 74.48.78.17 microservice health findjob`:在计算节点或其他非主 server 主机上通过公网 frontend remote CLI 进行同一验证,不需要主 server SSH key。 @@ -278,16 +279,16 @@ ClaudeQQ 在 UniDesk 语境中按消息网关后端服务管理:不得直接 - 在主 server 运行 `bun scripts/cli.ts microservice list`,确认 `pipeline` 的 `providerId=D601`、`public=false`、`frontendOnly=true`、仓库 URL、commit id、`127.0.0.1:18082` 映射和 `pipeline-v2-control` 容器摘要可见。 - 在主 server 运行 `bun scripts/cli.ts microservice list`,确认 `met-nonlinear` 的 `providerId=D601`、`public=false`、`frontendOnly=true`、仓库 URL、commit id、`127.0.0.1:3288` 映射和 `met-nonlinear-ts` 容器摘要可见。 - 在主 server 运行 `bun scripts/cli.ts microservice list`,确认 `claudeqq` 的 `providerId=D601`、`public=false`、`frontendOnly=true`、仓库 URL、commit id、`127.0.0.1:3290` 映射和 `claudeqq-backend` 容器摘要可见。 -- 在主 server 运行 `bun scripts/cli.ts microservice list`,确认 `code-queue` 的 `providerId=main-server`、`public=false`、`frontendOnly=true`、UniDesk 仓库 URL、`code-queue:4222` 映射和 `code-queue-backend` 容器摘要可见。 +- 在主 server 运行 `bun scripts/cli.ts microservice list`,确认 `code-queue` 的 `providerId=D601`、`public=false`、`frontendOnly=true`、UniDesk 仓库 URL、`127.0.0.1:4222` 映射和 D601 `code-queue-backend` 容器摘要可见。 - 在主 server 运行 `bun scripts/cli.ts microservice list`,确认 `filebrowser` 和 `filebrowser-d601` 分别显示为 `providerId=D518` 和 `providerId=D601`,均为 `public=false`、`frontendOnly=true`,仓库 URL 为 `https://github.com/filebrowser/filebrowser`,后端映射为 `host.docker.internal:4251`,容器摘要分别为 `unidesk-filebrowser-d518` 和 `unidesk-filebrowser-d601`;列表中不得再出现主 server `filebrowser-main` 容器。 - 运行 `bun scripts/cli.ts microservice health findjob` 与 `bun scripts/cli.ts microservice proxy findjob /api/summary`,确认真实链路经过 backend-core、WebSocket、D601 provider-gateway 和 D601 本机 FindJob 后端。 - 运行 `bun scripts/cli.ts microservice health pipeline` 与 `bun scripts/cli.ts microservice proxy pipeline '/api/snapshot?__unideskArrayLimit=registry.components:8,runs:3'`,确认真实链路经过 backend-core、WebSocket、D601 provider-gateway 和 D601 本机 Pipeline 后端,且 run/procedure 摘要包含甘特图所需时间字段。 - 运行 `bun scripts/cli.ts microservice health met-nonlinear`、`bun scripts/cli.ts microservice proxy met-nonlinear /api/queue`、`bun scripts/cli.ts microservice proxy met-nonlinear '/api/projects?root=projects&limit=20'` 和 `bun scripts/cli.ts microservice proxy met-nonlinear /api/images`,确认真实链路经过 backend-core、WebSocket、D601 provider-gateway 和 D601 本机 MET Nonlinear TS 后端。 - 运行 `bun scripts/cli.ts microservice health claudeqq`、`bun scripts/cli.ts microservice proxy claudeqq /api/napcat/login`、`bun scripts/cli.ts microservice proxy claudeqq /api/events/recent` 和 `bun scripts/cli.ts microservice proxy claudeqq /api/events/subscriptions`,确认真实链路经过 backend-core、WebSocket、D601 provider-gateway 和 D601 本机 ClaudeQQ 后端;在 D601 上 `curl http://127.0.0.1:3290/health` 应显示 `service=claudeqq`、`pureBackend=true`、`napcat.containerized=true`、NapCat HTTP/WS 状态、二维码状态和订阅计数。 - 运行 `bun scripts/cli.ts microservice health todo-note` 与 `bun scripts/cli.ts microservice proxy todo-note /api/instances`,确认真实链路经过 backend-core、WebSocket、main-server provider-gateway 和主 server `todo-note-backend` 后端;输出中必须包含五个迁移清单和 PostgreSQL 存储健康状态。 -- 运行 `bun scripts/cli.ts microservice health code-queue` 与 `bun scripts/cli.ts microservice proxy code-queue /api/tasks`,确认真实链路经过 backend-core、WebSocket、main-server provider-gateway 和主 server `code-queue-backend` 后端,并且 `/health` 的 `queue.storage.primary=postgres`、`queue.storage.postgresReady=true`,不得出现 file fallback;`queue.notifications.claudeqq.outbox.storage=postgres` 且暴露 pending/failed/sent 统计。再通过公网 frontend 提交一个 `gpt-5.5` 小任务,确认队列串行推进、输出实时更新、结束后有 judge 判定,且运行中可追加 prompt 或打断。Code Queue 的重启恢复必须作为验收项:运行中任务存在时重启或重建 `code-queue-backend` 后,任务必须从 PostgreSQL 恢复到可继续执行状态,不能丢失 active task、`promptHistory`、后续 queued 任务、readAt/未读状态或已入 outbox 的 ClaudeQQ 通知;ClaudeQQ/NapCat 离线期间结束的任务必须能在 `/api/notifications/claudeqq` 中看到 pending/failed,并在登录恢复后通过 `POST /api/notifications/claudeqq/drain` 发送。Code Queue 服务名、表名前缀或持久化目录发生迁移后,还必须运行 `bun scripts/cli.ts e2e run --only microservice:catalog-code-queue,microservice:code-queue-status,microservice:code-queue-health,microservice:code-queue-tasks`,证明 backend-core catalog、私有代理、PostgreSQL 队列和任务列表都指向 `code-queue`。批量验收必须通过公网 frontend 设置 `入队份数=5` 或使用多段 prompt 分隔,一次性入队 5 条任务,并确认 5 条任务按顺序进入 running/judging/succeeded,而不是只运行第一条。 -- Code Queue 内存防回归验收:凡是改动 Code Queue 的持久化、scheduler、输出/Trace、health、列表/详情查询、日志导出或容器运行参数,交付前必须用 `docker compose --env-file .state/docker-compose.env config` 或 `docker inspect code-queue-backend` 确认 memory 硬上限为 `629145600` 字节、memory+swap 上限为 `1610612736` 字节,运行 `docker stats --no-stream code-queue-backend` 确认常驻内存低于 `600MiB` 且 `OOMKilled=false`、`RestartCount` 未异常增长,再运行 `bun scripts/cli.ts microservice health code-queue` 确认 `/health` 通过 PostgreSQL 汇总队列而不是物化全量历史任务,并能看到 active run slot 与 waiter 状态。验收还必须覆盖有历史任务存在时的 `/api/tasks`、单任务详情和 output/transcript 查询,证明热状态裁剪不会丢历史输出、也不会重新把全部历史 `task_json` 缓存在进程内;涉及 TypeScript/frontend 验证的任务应能在该 600M memory + 1536M memswap 预算中完成 `bun run --cwd src/components/frontend check` 这类短时高内存命令,而不是被 memory watchdog 反复 SIGTERM。 -- Code Queue 延迟防回归验收:凡是改动 Code Queue 列表、overview、readAt、Trace/summary 懒加载、实时 output/SSE 事件发布、frontend 请求策略、backend-core 用户服务代理或 frontend direct proxy,交付前必须在有历史任务数据且有 active output 流动的 live 环境验证 `GET /api/tasks/overview`、`POST /api/tasks//read`、选定 task 的 `trace-step` 和前端 `/app/code-queue/` 首屏均低于 1s 目标;可运行 `bun scripts/src/code-queue-perf.ts --json --target-ms 1000` 采集公网 frontend 下的首屏耗时、最慢 API 和 DOM 完成指标,并用 `bun scripts/cli.ts microservice proxy code-queue /api/tasks/overview --raw`、容器直连 `/health` 与 `/api/tasks/overview` curl、性能面板 `/api/performance` 与 `/api/frontend-performance` 失败/慢操作记录、`docker stats --no-stream code-queue-backend` 补充后端耗时、代理 502 和内存/CPU 证据。验收结论必须同时说明是否使用了短 TTL cache、cache 如何被 mutation 或 archive append 失效、数据库索引/聚合是否命中、输出热路径是否只读增量指标,以及分页加载是否跳过 selected/active/stats;不能只展示 cache 命中后的单次快照。 +- 运行 `bun scripts/cli.ts microservice health code-queue` 与 `bun scripts/cli.ts microservice proxy code-queue /api/tasks`,确认真实链路经过 backend-core、WebSocket、D601 provider-gateway 和 D601 `code-queue-backend` 后端,并且 `/health` 的 `queue.storage.primary=postgres`、`queue.storage.postgresReady=true`,不得出现 file fallback;`queue.notifications.claudeqq.outbox.storage=postgres` 且暴露 pending/failed/sent 统计。还必须在 D601 `code-queue-backend` 容器内验证主 PostgreSQL 端口映射、主 OA Event Flow 端口映射和本机 ClaudeQQ `http://host.docker.internal:3290` 均可访问。再通过公网 frontend 提交一个 `gpt-5.5` 小任务,确认队列串行推进、输出实时更新、结束后有 judge 判定,且运行中可追加 prompt 或打断。Code Queue 的重启恢复必须作为验收项:运行中任务存在时在 D601 重启或重建 `code-queue-backend` 后,任务必须从 PostgreSQL 恢复到可继续执行状态,不能丢失 active task、`promptHistory`、后续 queued 任务、readAt/未读状态或已入 outbox 的 ClaudeQQ 通知;ClaudeQQ/NapCat 离线期间结束的任务必须能在 `/api/notifications/claudeqq` 中看到 pending/failed,并在登录恢复后通过 `POST /api/notifications/claudeqq/drain` 发送。Code Queue 服务名、表名前缀或持久化目录发生迁移后,还必须运行 `bun scripts/cli.ts e2e run --only microservice:catalog-code-queue,microservice:code-queue-status,microservice:code-queue-health,microservice:code-queue-tasks`,证明 backend-core catalog、私有代理、PostgreSQL 队列和任务列表都指向 `code-queue`。批量验收必须通过公网 frontend 设置 `入队份数=5` 或使用多段 prompt 分隔,一次性入队 5 条任务,并确认 5 条任务按顺序进入 running/judging/succeeded,而不是只运行第一条。 +- Code Queue 内存防回归验收:凡是改动 Code Queue 的持久化、scheduler、输出/Trace、health、列表/详情查询、日志导出或容器运行参数,交付前必须在 D601 用 `docker compose -f src/components/microservices/code-queue/docker-compose.d601.yml config` 或 `docker inspect code-queue-backend` 确认 memory/swap 硬上限符合预算,运行 `docker stats --no-stream code-queue-backend` 确认常驻内存、`OOMKilled=false` 和 `RestartCount` 未异常增长,再运行 `bun scripts/cli.ts microservice health code-queue` 确认 `/health` 通过 PostgreSQL 汇总队列而不是物化全量历史任务,并能看到 active run slot 与 waiter 状态。验收还必须覆盖有历史任务存在时的 `/api/tasks`、单任务详情和 output/transcript 查询,证明热状态裁剪不会丢历史输出、也不会重新把全部历史 `task_json` 缓存在进程内;涉及 TypeScript/frontend 验证的任务应能在 D601 Code Queue memory/swap 预算中完成 `bun run --cwd src/components/frontend check` 这类短时高内存命令,而不是被 memory watchdog 反复 SIGTERM。 +- Code Queue 延迟防回归验收:凡是改动 Code Queue 列表、overview、readAt、Trace/summary 懒加载、实时 output/SSE 事件发布、frontend 请求策略、backend-core 用户服务代理或 frontend direct proxy,交付前必须在有历史任务数据且有 active output 流动的 live 环境验证 `GET /api/tasks/overview`、`POST /api/tasks//read`、选定 task 的 `trace-step` 和前端 `/app/code-queue/` 首屏均低于 1s 目标;可运行 `bun scripts/src/code-queue-perf.ts --json --target-ms 1000` 采集公网 frontend 下的首屏耗时、最慢 API 和 DOM 完成指标,并用 `bun scripts/cli.ts microservice proxy code-queue /api/tasks/overview --raw`、D601 容器直连 `/health` 与 `/api/tasks/overview` curl、性能面板 `/api/performance` 与 `/api/frontend-performance` 失败/慢操作记录、`docker stats --no-stream code-queue-backend` 补充后端耗时、代理 502 和内存/CPU 证据。验收结论必须同时说明是否使用了短 TTL cache、cache 如何被 mutation 或 archive append 失效、数据库索引/聚合是否命中、输出热路径是否只读增量指标,以及分页加载是否跳过 selected/active/stats;不能只展示 cache 命中后的单次快照。 - 运行 `bun scripts/cli.ts microservice health filebrowser`、`bun scripts/cli.ts microservice health filebrowser-d601` 和 `bun scripts/cli.ts microservice proxy filebrowser / --max-body-bytes 2000`,确认 File Browser health 返回 `status=OK`,WebUI HTML 包含 `File Browser`,D518/D601 通过 provider-gateway 访问节点本机 `4251`;随后在公网 frontend 的 `用户服务 / File Browser` 中确认 D518 为默认目标、可导出截图、iframe 紧凑布局不再有巨大 `folder` 标记遮挡文件名,并可浏览 `/mnt/c`。 - 在 D601 上用 `bun scripts/cli.ts ssh D601 ...` 调试业务仓库和容器,确认 `curl http://127.0.0.1:3254/api/health` 可用;不要把调试服务部署到主 server。 - 在 D601 上用 `bun scripts/cli.ts ssh D601 ...` 调试业务仓库和容器,确认 `curl http://127.0.0.1:18082/health` 和 `curl http://127.0.0.1:18082/api/snapshot` 可用;不要把 Pipeline 调试服务部署到主 server。 diff --git a/docs/reference/provider-gateway.md b/docs/reference/provider-gateway.md index 75a00c30..94bcc6fc 100644 --- a/docs/reference/provider-gateway.md +++ b/docs/reference/provider-gateway.md @@ -86,7 +86,7 @@ provider ingress 是唯一允许公网暴露的 provider 连接接口,当前 ## User Service HTTP Proxy -`microservice.http` 是 provider-gateway 给 UniDesk 用户服务使用的私有后端访问能力。backend-core 通过真实 WebSocket dispatch 下发目标 service id、节点本机 `targetBaseUrl`、path、query、method、request body、timeout 和可选 JSON 数组裁剪参数;provider-gateway 支持 `GET`、`HEAD`、`POST`、`PUT`、`PATCH`、`DELETE`,但最终允许方法必须由每个用户服务的 `backend.allowedMethods` 显式配置。provider-gateway 只允许访问 `http://127.0.0.1`、`http://localhost`、`http://host.docker.internal` 这些节点本地地址;主 server 内置 Todo Note 与 Code Queue 后端可分别使用 Compose 服务名 `http://todo-note:4211` 与 `http://code-queue:4222`。该能力不打开 provider-gateway 入站端口,也不替代业务仓库自身 Dockerfile/docker-compose。 +`microservice.http` 是 provider-gateway 给 UniDesk 用户服务使用的私有后端访问能力。backend-core 通过真实 WebSocket dispatch 下发目标 service id、节点本机 `targetBaseUrl`、path、query、method、request body、timeout 和可选 JSON 数组裁剪参数;provider-gateway 支持 `GET`、`HEAD`、`POST`、`PUT`、`PATCH`、`DELETE`,但最终允许方法必须由每个用户服务的 `backend.allowedMethods` 显式配置。provider-gateway 只允许访问 `http://127.0.0.1`、`http://localhost`、`http://host.docker.internal` 这些节点本地地址;主 server 内置 Todo Note 后端可使用 Compose 服务名 `http://todo-note:4211`,D601 Code Queue 必须使用 D601 本机映射 `http://host.docker.internal:4222`。该能力不打开 provider-gateway 入站端口,也不替代业务仓库自身 Dockerfile/docker-compose。 超大 JSON 响应可以使用 `jsonArrayLimits` 在 provider-gateway 返回前裁剪指定数组,并在响应体中写入 `_unidesk.arrayLimits` 元数据,便于 UniDesk frontend 预览列表而不展示裸 JSON。长期应优先推动业务后端提供分页 API;裁剪只是 UniDesk 集成层的展示保护。 diff --git a/docs/reference/windows-passthrough.md b/docs/reference/windows-passthrough.md index d95d48e5..444ee859 100644 --- a/docs/reference/windows-passthrough.md +++ b/docs/reference/windows-passthrough.md @@ -164,7 +164,7 @@ Keil/串口/board-comm 的通用顺序如下: ## Code Queue Windows Native Codex -Code Queue 支持在提交任务时选择 `executionMode=windows-native`。该模式用于 D601 这类 WSL Provider:主 server 仍先通过既有远程执行容器建立任务运行环境,但容器内不启动 `codex`;容器只运行 stdio relay,连接到 WSL 侧 bridge,再由 bridge 调用 Windows 宿主原生 `codex app-server --listen stdio://`。这样公网/main-server 到 Provider 的临时断连不会直接终止 Windows Codex 进程。 +Code Queue 支持在提交任务时选择 `executionMode=windows-native`。该模式用于 D601 这类 WSL Provider:D601 Code Queue 先通过本节点执行环境建立任务运行环境,但容器内不启动 `codex`;容器只运行 stdio relay,连接到 WSL 侧 bridge,再由 bridge 调用 Windows 宿主原生 `codex app-server --listen stdio://`。这样 UniDesk 控制面到 Provider 的临时断连不会直接终止 Windows Codex 进程。 约束: diff --git a/scripts/src/config.ts b/scripts/src/config.ts index e7ce8532..648c64d3 100644 --- a/scripts/src/config.ts +++ b/scripts/src/config.ts @@ -12,6 +12,7 @@ export interface UniDeskConfig { frontend: { port: number; containerPort: number }; database: { port: number; containerPort: number }; providerIngress: { port: number; containerPort: number }; + restrictedHostAccess?: { bindHost: string; allowedSourceCidrs: string[] }; }; auth: { username: string; password: string; sessionSecret: string; sessionTtlSeconds: number }; database: { user: string; password: string; name: string; volume: string; volumeSize: string }; @@ -127,6 +128,18 @@ function stringArrayField(obj: Record, key: string, path: strin return value as string[]; } +function optionalRestrictedHostAccess(network: Record): UniDeskConfig["network"]["restrictedHostAccess"] { + const value = network.restrictedHostAccess; + if (value === undefined) return undefined; + const record = asRecord(value, "network.restrictedHostAccess"); + const allowedSourceCidrs = stringArrayField(record, "allowedSourceCidrs", "network.restrictedHostAccess"); + if (allowedSourceCidrs.length === 0) throw new Error("network.restrictedHostAccess.allowedSourceCidrs must not be empty"); + return { + bindHost: stringField(record, "bindHost", "network.restrictedHostAccess"), + allowedSourceCidrs, + }; +} + function microserviceConfig(item: Record, index: number): UniDeskMicroserviceConfig { const path = `microservices[${index}]`; const repository = asRecord(item.repository, `${path}.repository`); @@ -200,6 +213,7 @@ export function readConfig(): UniDeskConfig { frontend: portPair(network, "frontend"), database: portPair(network, "database"), providerIngress: portPair(network, "providerIngress"), + restrictedHostAccess: optionalRestrictedHostAccess(network), }, database: { user: stringField(database, "user", "database"), diff --git a/scripts/src/debug.ts b/scripts/src/debug.ts index 82526ef6..c1627994 100644 --- a/scripts/src/debug.ts +++ b/scripts/src/debug.ts @@ -136,7 +136,8 @@ export async function debugHealth(config: UniDeskConfig): Promise { providerIngressPublic: await readJson(`http://127.0.0.1:${config.network.providerIngress.port}/health`), publicExposureBoundary: { coreHostPort: { port: config.network.core.port, expected: "not-exposed" }, - databaseHostPort: { port: config.network.database.port, expected: "not-exposed" }, + databaseHostPort: { port: config.network.database.port, expected: "restricted-to-code-queue-provider" }, + oaEventFlowHostPort: { port: 4255, expected: "restricted-to-code-queue-provider" }, }, }; } diff --git a/scripts/src/docker.ts b/scripts/src/docker.ts index 59217e82..ad831aea 100644 --- a/scripts/src/docker.ts +++ b/scripts/src/docker.ts @@ -19,7 +19,7 @@ export interface ContainerStatus { ports: string; } -const rebuildableServices = ["backend-core", "frontend", "provider-gateway", "todo-note", "code-queue", "project-manager", "baidu-netdisk", "oa-event-flow"] as const; +const rebuildableServices = ["backend-core", "frontend", "provider-gateway", "todo-note", "project-manager", "baidu-netdisk", "oa-event-flow"] as const; export type RebuildableService = typeof rebuildableServices[number]; export function isRebuildableService(value: string | undefined): value is RebuildableService { @@ -60,7 +60,7 @@ export function writeComposeEnv(config: UniDeskConfig, freshLogPrefix: boolean): const previousValue = (key: string): string => previousRaw.match(new RegExp(`^${key}=(.*)$`, "m"))?.[1]?.replace(/^"|"$/g, "") ?? ""; const runtimeSecret = (key: string): string => process.env[key] ?? previousValue(key); const runtimeSecretWithDefault = (key: string, defaultValue: string, legacyDefault = ""): string => { - if (process.env[key] !== undefined) return process.env[key] ?? defaultValue; + if (process.env[key] !== undefined) return process.env[key] || defaultValue; const previous = previousValue(key); if (previous.length > 0 && previous !== legacyDefault) return previous; return defaultValue; @@ -86,11 +86,13 @@ export function writeComposeEnv(config: UniDeskConfig, freshLogPrefix: boolean): chmodSync(join(logRoot, logDay), 0o777); const labels = JSON.stringify(config.providerGateway.labels); const microservices = JSON.stringify(config.microservices); + const restrictedHostBind = config.network.restrictedHostAccess?.bindHost || "127.0.0.1"; const lines = { UNIDESK_PUBLIC_HOST: config.network.publicHost, UNIDESK_CORE_PORT: String(config.network.core.port), UNIDESK_FRONTEND_PORT: String(config.network.frontend.port), UNIDESK_DATABASE_PORT: String(config.network.database.port), + UNIDESK_DATABASE_BIND_HOST: runtimeSecretWithDefault("UNIDESK_DATABASE_BIND_HOST", restrictedHostBind, "127.0.0.1"), UNIDESK_PROVIDER_INGRESS_PORT: String(config.network.providerIngress.port), UNIDESK_DATABASE_USER: config.database.user, UNIDESK_DATABASE_PASSWORD: config.database.password, @@ -147,6 +149,8 @@ export function writeComposeEnv(config: UniDeskConfig, freshLogPrefix: boolean): UNIDESK_CODE_QUEUE_DEV_CONTAINER_IMAGE: runtimeSecret("UNIDESK_CODE_QUEUE_DEV_CONTAINER_IMAGE"), UNIDESK_CODE_QUEUE_DEV_CONTAINER_WORKDIR: runtimeSecret("UNIDESK_CODE_QUEUE_DEV_CONTAINER_WORKDIR") || "/home/ubuntu", UNIDESK_OA_EVENT_FLOW_BASE_URL: runtimeSecret("UNIDESK_OA_EVENT_FLOW_BASE_URL") || "http://oa-event-flow:4255", + UNIDESK_OA_EVENT_FLOW_PORT: runtimeSecret("UNIDESK_OA_EVENT_FLOW_PORT") || "4255", + UNIDESK_OA_EVENT_FLOW_BIND_HOST: runtimeSecretWithDefault("UNIDESK_OA_EVENT_FLOW_BIND_HOST", restrictedHostBind, "127.0.0.1"), UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED: runtimeSecret("UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED") || "true", UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL: runtimeSecret("UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL") || "http://backend-core:8080/api/microservices/claudeqq/proxy", UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE: runtimeSecret("UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE") || "private", @@ -182,7 +186,12 @@ export function startStack(config: UniDeskConfig): unknown { throw new Error(`Fixed UniDesk port is occupied before start: ${occupiedPorts.map((p) => `${p.name}:${p.port}`).join(", ")}`); } const upCommand = [...compose, "up", "-d", "--build", "--remove-orphans"]; - const command = ["bash", "-lc", composeLockedScript(`set -euo pipefail; ${shellJoin(upCommand)}`)]; + const script = [ + "set -euo pipefail", + restrictedHostAccessScript(config), + shellJoin(upCommand), + ].filter((line) => line.length > 0).join("\n"); + const command = ["bash", "-lc", composeLockedScript(script)]; const job = startJob("server_start", command, "Build and start UniDesk services without tearing down running queue containers"); return { job, runtimeEnv, command, ports: fixedPorts(config) }; } @@ -246,14 +255,14 @@ export function rebuildService(config: UniDeskConfig, service: RebuildableServic const script = [ "set -euo pipefail", `echo ${shellJoin(["rebuild_service", service, "build_first_then_force_recreate_with_validation"])}`, + restrictedHostAccessScript(config), shellJoin(buildCommand), `nohup bash -lc ${shellQuote(watchdogScript)} >/dev/null 2>&1 &`, shellJoin(upCommand), validateScript, ].join("\n"); const command = ["bash", "-lc", composeLockedScript(script)]; - const jobRunner = service === "code-queue" ? { runner: "docker" as const, dockerImage: "unidesk-code-queue:latest" } : {}; - const job = startJob("server_rebuild", command, `Rebuild and validate UniDesk ${service} with serialized Docker Compose mutation`, jobRunner); + const job = startJob("server_rebuild", command, `Rebuild and validate UniDesk ${service} with serialized Docker Compose mutation`); return { job, runtimeEnv, @@ -268,7 +277,7 @@ export function rebuildService(config: UniDeskConfig, service: RebuildableServic noDeps: true, forceRecreate: true, composeMutationLock: rootPath(".state", "locks", "server-compose.lock"), - jobRunner: service === "code-queue" ? "docker" : "local", + jobRunner: "local", postUpValidation: true, namedVolumesPreserved: true, }, @@ -282,6 +291,36 @@ function fixedPorts(config: UniDeskConfig): Array<{ name: string; port: number; ]; } +function restrictedHostAccessScript(config: UniDeskConfig): string { + const access = config.network.restrictedHostAccess; + if (access === undefined || access.bindHost === "127.0.0.1") return ""; + const ports = [ + { name: "database", containerPort: config.network.database.containerPort }, + { name: "oa-event-flow", containerPort: 4255 }, + ]; + return [ + "iptables -N DOCKER-USER 2>/dev/null || true", + ...ports.flatMap((port) => [ + ...access.allowedSourceCidrs.map((source) => [ + `iptables -C DOCKER-USER -s ${shellQuote(source)} -p tcp --dport ${port.containerPort} -j ACCEPT 2>/dev/null`, + ` || iptables -I DOCKER-USER 1 -s ${shellQuote(source)} -p tcp --dport ${port.containerPort} -j ACCEPT`, + ].join(" \\\n")), + [ + `iptables -C DOCKER-USER -p tcp --dport ${port.containerPort} -j DROP 2>/dev/null`, + " || {", + " return_line=$(iptables -L DOCKER-USER --line-numbers | awk '$2==\"RETURN\" {print $1; exit}')", + " if [ -n \"$return_line\" ]; then", + ` iptables -I DOCKER-USER "$return_line" -p tcp --dport ${port.containerPort} -j DROP`, + " else", + ` iptables -A DOCKER-USER -p tcp --dport ${port.containerPort} -j DROP`, + " fi", + " }", + ].join("\n"), + `echo ${shellJoin(["restricted_host_access", port.name, String(port.containerPort), access.allowedSourceCidrs.join(",")])}`, + ]), + ].join("\n"); +} + function shellJoin(args: string[]): string { return args.map(shellQuote).join(" "); } @@ -366,6 +405,11 @@ function dockerExec(config: UniDeskConfig, container: string, command: string[]) export async function stackStatus(config: UniDeskConfig): Promise { const runtimeEnv = writeComposeEnv(config, false); + const runtimeRaw = existsSync(runtimeEnv.envFile) ? readFileSync(runtimeEnv.envFile, "utf8") : ""; + const runtimeValue = (key: string): string => runtimeRaw.match(new RegExp(`^${key}=(.*)$`, "m"))?.[1]?.replace(/^"|"$/g, "") ?? ""; + const databaseBindHost = runtimeValue("UNIDESK_DATABASE_BIND_HOST") || "127.0.0.1"; + const oaEventFlowBindHost = runtimeValue("UNIDESK_OA_EVENT_FLOW_BIND_HOST") || "127.0.0.1"; + const oaEventFlowPort = Number(runtimeValue("UNIDESK_OA_EVENT_FLOW_PORT") || "4255"); const coreHealth = dockerExecJson("unidesk-backend-core", "fetch('http://127.0.0.1:8080/health').then(r=>r.json()).then(j=>console.log(JSON.stringify({ok:true,status:200,body:j}))).catch(e=>{console.log(JSON.stringify({ok:false,error:String(e)}));process.exit(1)})"); const overview = dockerExecJson("unidesk-backend-core", "fetch('http://127.0.0.1:8080/api/overview').then(r=>r.json()).then(j=>console.log(JSON.stringify({ok:true,status:200,body:j}))).catch(e=>{console.log(JSON.stringify({ok:false,error:String(e)}));process.exit(1)})"); return { @@ -373,12 +417,28 @@ export async function stackStatus(config: UniDeskConfig): Promise { publicPorts: fixedPorts(config), blockedPublicPorts: [ { name: "backend-core-rest", port: config.network.core.port, listening: isPortListening(config.network.core.port), expected: "not-listening" }, - { name: "database", port: config.network.database.port, listening: isPortListening(config.network.database.port), expected: "not-listening" }, + ], + restrictedHostPorts: [ + { + name: "database", + bindHost: databaseBindHost, + hostPort: config.network.database.port, + containerPort: config.network.database.containerPort, + listening: isPortListening(config.network.database.port), + expected: databaseBindHost === "127.0.0.1" ? "local-only" : "restricted-to-code-queue-provider", + }, + { + name: "oa-event-flow", + bindHost: oaEventFlowBindHost, + hostPort: oaEventFlowPort, + containerPort: 4255, + listening: isPortListening(oaEventFlowPort), + expected: oaEventFlowBindHost === "127.0.0.1" ? "local-only" : "restricted-to-code-queue-provider", + }, ], internalPorts: [ { name: "backend-core", containerPort: config.network.core.containerPort, hostPort: null }, { name: "database", containerPort: config.network.database.containerPort, hostPort: null }, - { name: "code-queue", containerPort: 4222, hostPort: null }, { name: "project-manager", containerPort: 4233, hostPort: null }, { name: "baidu-netdisk", containerPort: 4244, hostPort: null }, { name: "oa-event-flow", containerPort: 4255, hostPort: null }, @@ -419,7 +479,7 @@ export function stackLogs(config: UniDeskConfig, tailBytes: number): unknown { const currentFiles = allFiles.filter((path) => basename(path).startsWith(runtimeEnv.logPrefix)); const selectedFiles = (currentFiles.length > 0 ? currentFiles : allFiles.slice(-12)).slice(-12); const files = selectedFiles.map((path) => ({ path, name: basename(path), tail: tailFile(path, tailBytes) })); - const containerNames = ["unidesk-database", "unidesk-backend-core", "unidesk-frontend", "unidesk-provider-gateway-main", "todo-note-backend", "code-queue-backend", "project-manager-backend", "baidu-netdisk-backend", "oa-event-flow-backend"]; + const containerNames = ["unidesk-database", "unidesk-backend-core", "unidesk-frontend", "unidesk-provider-gateway-main", "todo-note-backend", "project-manager-backend", "baidu-netdisk-backend", "oa-event-flow-backend"]; const docker = containerNames.map((name) => { const result = runCommand(["docker", "logs", "--tail", "40", name], repoRoot); return { name, exitCode: result.exitCode, stdoutTail: result.stdout.slice(-tailBytes), stderrTail: result.stderr.slice(-tailBytes) }; diff --git a/scripts/src/e2e.ts b/scripts/src/e2e.ts index 676aa9e9..58759afe 100644 --- a/scripts/src/e2e.ts +++ b/scripts/src/e2e.ts @@ -841,6 +841,36 @@ function dockerPortSummary(): unknown { }; } +function dockerUserPortRestriction(containerPort: number, allowedSourceCidrs: string[] = []): unknown { + const result = runCommand(["iptables", "-S", "DOCKER-USER"], repoRoot); + const lines = result.stdout.split("\n").map((line) => line.trim()).filter(Boolean); + const dportPattern = new RegExp(`--dport\\s+${containerPort}\\b`); + const portLines = lines.filter((line) => dportPattern.test(line)); + const acceptSources = portLines + .filter((line) => line.includes("-j ACCEPT")) + .map((line) => line.match(/(?:^|\s)-s\s+(\S+)/)?.[1] ?? "") + .filter((source) => source.length > 0); + const hasDrop = portLines.some((line) => line.includes("-j DROP")); + const requiredSourcesPresent = allowedSourceCidrs.length === 0 + ? acceptSources.length > 0 + : allowedSourceCidrs.every((source) => acceptSources.includes(source)); + return { + ok: result.exitCode === 0 && hasDrop && requiredSourcesPresent, + exitCode: result.exitCode, + containerPort, + acceptSources, + allowedSourceCidrs, + requiredSourcesPresent, + hasDrop, + lines: portLines, + stderr: result.stderr.slice(-1200), + }; +} + +function publicProbeBlockedOrRestricted(probe: unknown, restriction: unknown): boolean { + return (probe as { reachable?: boolean }).reachable === false || (restriction as { ok?: boolean }).ok === true; +} + function dockerStatusCheckDetail(dockerStatus: unknown, providerId: string): unknown { const response = dockerStatus as { ok?: boolean; status?: number; body?: { dockerStatuses?: Array<{ providerId?: string; name?: string; nodeStatus?: string; updatedAt?: string; dockerStatus?: { ok?: boolean; socketPresent?: boolean; collectedAt?: string; counts?: unknown; daemon?: unknown; containers?: Array<{ id?: string; name?: string; image?: string; state?: string; status?: string; ports?: string; restartPolicy?: string; pidMode?: string }> } }> } }; const item = response.body?.dockerStatuses?.find((entry) => entry.providerId === providerId); @@ -940,22 +970,25 @@ async function exposureChecks(config: UniDeskConfig, urls: PublicUrls, checks: E const portsText = (portSummary.rows ?? []).map((row) => `${row.name} ${row.ports}`).join("\n"); const corePublic = await fetchProbe(`${urls.blockedCoreUrl}/health`, 2500); const databasePublic = await tcpProbe(urls.blockedDatabaseHost, urls.blockedDatabasePort); + const allowedSourceCidrs = config.network.restrictedHostAccess?.allowedSourceCidrs ?? []; + const databaseRestriction = dockerUserPortRestriction(config.network.database.containerPort, allowedSourceCidrs); const findjobPublic = await fetchProbe(`http://${config.network.publicHost}:3254/api/health`, 2500); const metNonlinearPublic = await fetchProbe(`http://${config.network.publicHost}:3288/health`, 2500); const claudeqqPublic = await fetchProbe(`http://${config.network.publicHost}:3290/health`, 2500); const todoNotePublic = await fetchProbe(`http://${config.network.publicHost}:4211/api/health`, 2500); const codeQueuePublic = await fetchProbe(`http://${config.network.publicHost}:14222/health`, 2500); const oaEventFlowPublic = await fetchProbe(`http://${config.network.publicHost}:4255/health`, 2500); + const oaEventFlowRestriction = dockerUserPortRestriction(4255, allowedSourceCidrs); const filebrowserPublic = await fetchProbe(`http://${config.network.publicHost}:4251/health`, 2500); - addSelectedCheck(checks, options, "network:only-frontend-provider-ports", !portsText.includes(`:${config.network.core.port}->`) && !portsText.includes(`:${config.network.database.port}->`) && !portsText.includes(":14222->"), portSummary); + addSelectedCheck(checks, options, "network:only-frontend-provider-ports", !portsText.includes(`:${config.network.core.port}->`) && !portsText.includes(":14222->"), portSummary); addSelectedCheck(checks, options, "network:core-public-blocked", (corePublic as { reachable?: boolean }).reachable === false, corePublic); - addSelectedCheck(checks, options, "network:database-public-blocked", (databasePublic as { reachable?: boolean }).reachable === false, databasePublic); + addSelectedCheck(checks, options, "network:database-public-blocked", publicProbeBlockedOrRestricted(databasePublic, databaseRestriction), { publicProbe: databasePublic, restriction: databaseRestriction }); addSelectedCheck(checks, options, "network:findjob-public-blocked", (findjobPublic as { reachable?: boolean }).reachable === false, findjobPublic); addSelectedCheck(checks, options, "network:met-nonlinear-public-blocked", (metNonlinearPublic as { reachable?: boolean }).reachable === false, metNonlinearPublic); addSelectedCheck(checks, options, "network:claudeqq-public-blocked", (claudeqqPublic as { reachable?: boolean }).reachable === false, claudeqqPublic); addSelectedCheck(checks, options, "network:todo-note-public-blocked", (todoNotePublic as { reachable?: boolean }).reachable === false, todoNotePublic); addSelectedCheck(checks, options, "network:code-queue-public-blocked", (codeQueuePublic as { reachable?: boolean }).reachable === false, codeQueuePublic); - addSelectedCheck(checks, options, "network:oa-event-flow-public-blocked", (oaEventFlowPublic as { reachable?: boolean }).reachable === false, oaEventFlowPublic); + addSelectedCheck(checks, options, "network:oa-event-flow-public-blocked", publicProbeBlockedOrRestricted(oaEventFlowPublic, oaEventFlowRestriction), { publicProbe: oaEventFlowPublic, restriction: oaEventFlowRestriction }); addSelectedCheck(checks, options, "network:filebrowser-public-blocked", (filebrowserPublic as { reachable?: boolean }).reachable === false, filebrowserPublic); } @@ -1099,7 +1132,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2 addSelectedCheck(checks, options, "microservice:catalog-claudeqq", (microservices as { ok?: boolean }).ok === true && claudeqq?.providerId === "D601" && claudeqq.backend?.public === false && claudeqq.runtime?.container?.name === "claudeqq-backend", { microservices }); addSelectedCheck(checks, options, "microservice:catalog-todo-note", (microservices as { ok?: boolean }).ok === true && todoNote?.providerId === config.providerGateway.id && todoNote.backend?.public === false && todoNote.runtime?.container?.name === "todo-note-backend", { microservices }); addSelectedCheck(checks, options, "microservice:catalog-oa-event-flow", (microservices as { ok?: boolean }).ok === true && oaEventFlow?.providerId === config.providerGateway.id && oaEventFlow.backend?.public === false && oaEventFlow.runtime?.container?.name === "oa-event-flow-backend", { microservices }); - addSelectedCheck(checks, options, "microservice:catalog-code-queue", (microservices as { ok?: boolean }).ok === true && codeQueue?.providerId === config.providerGateway.id && codeQueue.backend?.public === false && codeQueue.runtime?.container?.name === "code-queue-backend", { microservices }); + addSelectedCheck(checks, options, "microservice:catalog-code-queue", (microservices as { ok?: boolean }).ok === true && codeQueue?.providerId === "D601" && codeQueue.backend?.public === false && codeQueue.runtime?.container?.name === "code-queue-backend", { microservices }); addSelectedCheck(checks, options, "microservice:catalog-filebrowser", (microservices as { ok?: boolean }).ok === true && filebrowser?.providerId === "D518" && filebrowser.backend?.public === false @@ -1167,7 +1200,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2 sampleEvents: oaEventFlowPipelineEventsBody?.events?.slice(0, 5), }); addSelectedCheck(checks, options, "microservice:oa-event-flow-stats", (oaEventFlowStats as { ok?: boolean }).ok === true && oaEventFlowStatsBody?.ok === true && Array.isArray(oaEventFlowStatsBody.stats), oaEventFlowStats); - addSelectedCheck(checks, options, "microservice:code-queue-status", (codeQueueStatus as { ok?: boolean }).ok === true && (codeQueueStatus as { body?: { microservice?: { id?: string; providerId?: string } } }).body?.microservice?.providerId === config.providerGateway.id, codeQueueStatus); + addSelectedCheck(checks, options, "microservice:code-queue-status", (codeQueueStatus as { ok?: boolean }).ok === true && (codeQueueStatus as { body?: { microservice?: { id?: string; providerId?: string } } }).body?.microservice?.providerId === "D601", codeQueueStatus); addSelectedCheck(checks, options, "microservice:code-queue-health", (codeQueueHealth as { ok?: boolean }).ok === true && codeQueueHealthBody?.ok === true && codeQueueHealthBody.queue?.defaultModel === "gpt-5.5" && codeQueueHealthBody.queue?.modelReasoningEfforts?.["gpt-5.5"] === "xhigh", codeQueueHealth); addSelectedCheck(checks, options, "microservice:code-queue-tasks", (codeQueueTasks as { ok?: boolean }).ok === true && codeQueueTasksBody?.ok === true && Array.isArray(codeQueueTasksBody.tasks) && codeQueueTasksBody.queue?.defaultModel === "gpt-5.5" && codeQueueTasksBody.queue?.modelReasoningEfforts?.["gpt-5.5"] === "xhigh", codeQueueTasks); const upgradeDispatch = dockerCoreJson("/api/dispatch", { @@ -2688,7 +2721,7 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2 && Number(oaEventFlowMetrics.rawButtonCount || 0) >= 2 && !oaEventFlowText.includes("{\n"), { oaEventFlowMetrics, oaEventFlowTextPreview: oaEventFlowText.slice(0, 1400) }); - addSelectedCheck(checks, options, "frontend:code-queue-integrated-visible", codeQueueTextLower.includes("code queue") && codeQueueText.includes("gpt-5.4-mini") && codeQueueText.includes("gpt-5.4") && codeQueueText.includes("gpt-5.5") && codeQueueText.includes("提交任务") && codeQueueText.includes("执行 Provider") && codeQueueText.includes("入队份数") && codeQueueText.includes("追加 prompt") && codeQueueText.includes("打断") && codeQueueTextLower.includes("查看 queue") && codeQueueText.includes("创建 queue") && codeQueueText.includes("合并 queue") && codeQueueOptions.some((text) => text.includes("All queues")) && codeQueueTracePlacement.firstChildIsTrace === true && codeQueueTracePlacement.noPageTopStatus === true && codeQueueTracePlacement.filterInsideTracePanel === true && codeQueueTracePlacement.taskSearchVisible === true && codeQueueTracePlacement.traceStatusVisible === true && codeQueueTracePlacement.markAllReadVisible === true && codeQueueGlobalStatus.activeMicroserviceVisible === true && codeQueueSidebarUpdateMetrics.hasRecentUpdateLabel === true && codeQueueHtmlGuard.rootAttrMissing === true && codeQueueHtmlGuard.sourceAttrMissing === true && codeQueueHtmlGuard.sourceNoBasePrompt === true && codeQueueSubmitQueueControl.tagName === "select" && codeQueueSubmitQueueControl.createButtonVisible === true && codeQueueSubmitQueueControl.mergeButtonVisible === true && codeQueueSubmitQueueControl.mergeSourceInlineMissing === true && codeQueueSubmitQueueControl.mergeDialogMissingBeforeClick === true && (codeQueueSubmitQueueControl.mergeButtonDisabled === true || (codeQueueSubmitQueueControl.mergeDialogVisible === true && codeQueueSubmitQueueControl.mergeDialogSelectVisible === true && Number(codeQueueSubmitQueueControl.mergeDialogSourceOptionCount || 0) > 1 && codeQueueSubmitQueueControl.mergeDialogSelectInsideSubmitForm !== true && codeQueueSubmitQueueControl.mergeDialogUsesCommonComponent === true && codeQueueSubmitQueueControl.mergeDialogDeleteNoteVisible === true)) && codeQueueSubmitQueueControl.oldInputMissing === true && codeQueueSubmitQueueControl.providerValue === "main-server" && codeQueueSubmitQueueControl.cwdValue === "/root/unidesk" && Array.isArray(codeQueueSubmitQueueControl.providerOptions) && codeQueueSubmitQueueControl.providerOptions.some((item: any) => item.value === "D601" && String(item.text || "").includes("/home/ubuntu")) && codeQueueSubmitQueueControl.maxAttemptsMax === "99" && codeQueueSubmitQueueControl.maxAttemptsValue === "99" && codeQueueSubmitQueueControl.moveQueueVisible === true && codeQueuePromptDefaultEmpty === true && codeQueueSubmitGuard.batchRowVisible === true && codeQueueSubmitGuard.checkboxVisible === true && codeQueueSubmitGuard.disabledBeforeConfirm === true && codeQueueSubmitGuard.enabledAfterConfirm === true && codeQueueSubmitGuard.waitElementMissingBeforeSubmit === true && codeQueueScrollbarMetrics.transcriptThin === true && codeQueueScrollbarMetrics.toolHorizontalHidden === true && (codeQueueSwitchMetrics.optionCount <= 1 || codeQueueSwitchMetrics.switched === true) && codeQueueTextLower.includes("attempts") && codeQueueText.includes("仅 UniDesk frontend 代理访问") && (codeQueueTaskCount === 0 || codeQueueOutputText.includes("Submitted prompt")), { codeQueueTaskCount, codeQueueOptions, codeQueueSwitchMetrics, codeQueueSubmitQueueControl, codeQueueSubmitGuard, codeQueueScrollbarMetrics, codeQueuePromptDefaultEmpty, codeQueueTracePlacement, codeQueueGlobalStatus, codeQueueSidebarUpdateMetrics, codeQueueHtmlGuard, codeQueueOutputPreview: codeQueueOutputText.slice(0, 900), codeQueueTextPreview: codeQueueText.slice(0, 1400) }); + addSelectedCheck(checks, options, "frontend:code-queue-integrated-visible", codeQueueTextLower.includes("code queue") && codeQueueText.includes("gpt-5.4-mini") && codeQueueText.includes("gpt-5.4") && codeQueueText.includes("gpt-5.5") && codeQueueText.includes("提交任务") && codeQueueText.includes("执行 Provider") && codeQueueText.includes("入队份数") && codeQueueText.includes("追加 prompt") && codeQueueText.includes("打断") && codeQueueTextLower.includes("查看 queue") && codeQueueText.includes("创建 queue") && codeQueueText.includes("合并 queue") && codeQueueOptions.some((text) => text.includes("All queues")) && codeQueueTracePlacement.firstChildIsTrace === true && codeQueueTracePlacement.noPageTopStatus === true && codeQueueTracePlacement.filterInsideTracePanel === true && codeQueueTracePlacement.taskSearchVisible === true && codeQueueTracePlacement.traceStatusVisible === true && codeQueueTracePlacement.markAllReadVisible === true && codeQueueGlobalStatus.activeMicroserviceVisible === true && codeQueueSidebarUpdateMetrics.hasRecentUpdateLabel === true && codeQueueHtmlGuard.rootAttrMissing === true && codeQueueHtmlGuard.sourceAttrMissing === true && codeQueueHtmlGuard.sourceNoBasePrompt === true && codeQueueSubmitQueueControl.tagName === "select" && codeQueueSubmitQueueControl.createButtonVisible === true && codeQueueSubmitQueueControl.mergeButtonVisible === true && codeQueueSubmitQueueControl.mergeSourceInlineMissing === true && codeQueueSubmitQueueControl.mergeDialogMissingBeforeClick === true && (codeQueueSubmitQueueControl.mergeButtonDisabled === true || (codeQueueSubmitQueueControl.mergeDialogVisible === true && codeQueueSubmitQueueControl.mergeDialogSelectVisible === true && Number(codeQueueSubmitQueueControl.mergeDialogSourceOptionCount || 0) > 1 && codeQueueSubmitQueueControl.mergeDialogSelectInsideSubmitForm !== true && codeQueueSubmitQueueControl.mergeDialogUsesCommonComponent === true && codeQueueSubmitQueueControl.mergeDialogDeleteNoteVisible === true)) && codeQueueSubmitQueueControl.oldInputMissing === true && codeQueueSubmitQueueControl.providerValue === "D601" && codeQueueSubmitQueueControl.cwdValue === "/workspace" && Array.isArray(codeQueueSubmitQueueControl.providerOptions) && codeQueueSubmitQueueControl.providerOptions.some((item: any) => item.value === "D601" && String(item.text || "").includes("/workspace")) && codeQueueSubmitQueueControl.maxAttemptsMax === "99" && codeQueueSubmitQueueControl.maxAttemptsValue === "99" && codeQueueSubmitQueueControl.moveQueueVisible === true && codeQueuePromptDefaultEmpty === true && codeQueueSubmitGuard.batchRowVisible === true && codeQueueSubmitGuard.checkboxVisible === true && codeQueueSubmitGuard.disabledBeforeConfirm === true && codeQueueSubmitGuard.enabledAfterConfirm === true && codeQueueSubmitGuard.waitElementMissingBeforeSubmit === true && codeQueueScrollbarMetrics.transcriptThin === true && codeQueueScrollbarMetrics.toolHorizontalHidden === true && (codeQueueSwitchMetrics.optionCount <= 1 || codeQueueSwitchMetrics.switched === true) && codeQueueTextLower.includes("attempts") && codeQueueText.includes("仅 UniDesk frontend 代理访问") && (codeQueueTaskCount === 0 || codeQueueOutputText.includes("Submitted prompt")), { codeQueueTaskCount, codeQueueOptions, codeQueueSwitchMetrics, codeQueueSubmitQueueControl, codeQueueSubmitGuard, codeQueueScrollbarMetrics, codeQueuePromptDefaultEmpty, codeQueueTracePlacement, codeQueueGlobalStatus, codeQueueSidebarUpdateMetrics, codeQueueHtmlGuard, codeQueueOutputPreview: codeQueueOutputText.slice(0, 900), codeQueueTextPreview: codeQueueText.slice(0, 1400) }); addSelectedCheck(checks, options, "frontend:code-queue-enqueue-await-smoke", codeQueueEnqueueAwaitSmoke.checked === true && codeQueueEnqueueAwaitSmoke.delayedPostCount === 1 diff --git a/scripts/src/remote.ts b/scripts/src/remote.ts index 1a3b8a51..bd26deb7 100644 --- a/scripts/src/remote.ts +++ b/scripts/src/remote.ts @@ -416,7 +416,8 @@ async function remoteHealth(session: FrontendSession, config: UniDeskConfig): Pr dockerStatusInternal: summarizeDockerStatus(await frontendJson(session, "/api/nodes/docker-status")), publicExposureBoundary: { coreHostPort: { port: config.network.core.port, expected: "not-exposed" }, - databaseHostPort: { port: config.network.database.port, expected: "not-exposed" }, + databaseHostPort: { port: config.network.database.port, expected: "restricted-to-code-queue-provider" }, + oaEventFlowHostPort: { port: 4255, expected: "restricted-to-code-queue-provider" }, }, }; } diff --git a/src/components/frontend/public/app.js b/src/components/frontend/public/app.js index c4223d9c..074b53f9 100644 --- a/src/components/frontend/public/app.js +++ b/src/components/frontend/public/app.js @@ -1,41 +1,41 @@ -(()=>{var FK=Object.create;var{getPrototypeOf:JK,defineProperty:N7,getOwnPropertyNames:UK}=Object;var QK=Object.prototype.hasOwnProperty;function qK(u){return this[u]}var NK,WK,Pu=(u,f,l)=>{var r=u!=null&&typeof u==="object";if(r){var n=f?NK??=new WeakMap:WK??=new WeakMap,i=n.get(u);if(i)return i}l=u!=null?FK(JK(u)):{};let y=f||!u||!u.__esModule?N7(l,"default",{value:u,enumerable:!0}):l;for(let _ of UK(u))if(!QK.call(y,_))N7(y,_,{get:qK.bind(u,_),enumerable:!0});if(r)n.set(u,y);return y};var nr=(u,f)=>()=>(f||u((f={exports:{}}).exports,f),f.exports);var du=((u)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(u,{get:(f,l)=>(typeof require<"u"?require:f)[l]}):u)(function(u){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+u+'" is not supported')});var B7=nr((su)=>{var Oy=Symbol.for("react.element"),LK=Symbol.for("react.portal"),wK=Symbol.for("react.fragment"),KK=Symbol.for("react.strict_mode"),GK=Symbol.for("react.profiler"),zK=Symbol.for("react.provider"),TK=Symbol.for("react.context"),EK=Symbol.for("react.forward_ref"),ZK=Symbol.for("react.suspense"),OK=Symbol.for("react.memo"),HK=Symbol.for("react.lazy"),W7=Symbol.iterator;function BK(u){if(u===null||typeof u!=="object")return null;return u=W7&&u[W7]||u["@@iterator"],typeof u==="function"?u:null}var K7={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},G7=Object.assign,z7={};function e1(u,f,l){this.props=u,this.context=f,this.refs=z7,this.updater=l||K7}e1.prototype.isReactComponent={};e1.prototype.setState=function(u,f){if(typeof u!=="object"&&typeof u!=="function"&&u!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,u,f,"setState")};e1.prototype.forceUpdate=function(u){this.updater.enqueueForceUpdate(this,u,"forceUpdate")};function T7(){}T7.prototype=e1.prototype;function v8(u,f,l){this.props=u,this.context=f,this.refs=z7,this.updater=l||K7}var k8=v8.prototype=new T7;k8.constructor=v8;G7(k8,e1.prototype);k8.isPureReactComponent=!0;var L7=Array.isArray,E7=Object.prototype.hasOwnProperty,I8={current:null},Z7={key:!0,ref:!0,__self:!0,__source:!0};function O7(u,f,l){var r,n={},i=null,y=null;if(f!=null)for(r in f.ref!==void 0&&(y=f.ref),f.key!==void 0&&(i=""+f.key),f)E7.call(f,r)&&!Z7.hasOwnProperty(r)&&(n[r]=f[r]);var _=arguments.length-2;if(_===1)n.children=l;else if(1<_){for(var $=Array(_),A=0;A<_;A++)$[A]=arguments[A+2];n.children=$}if(u&&u.defaultProps)for(r in _=u.defaultProps,_)n[r]===void 0&&(n[r]=_[r]);return{$$typeof:Oy,type:u,key:i,ref:y,props:n,_owner:I8.current}}function VK(u,f){return{$$typeof:Oy,type:u.type,key:f,ref:u.ref,props:u.props,_owner:u._owner}}function g8(u){return typeof u==="object"&&u!==null&&u.$$typeof===Oy}function DK(u){var f={"=":"=0",":":"=2"};return"$"+u.replace(/[=:]/g,function(l){return f[l]})}var w7=/\/+/g;function b8(u,f){return typeof u==="object"&&u!==null&&u.key!=null?DK(""+u.key):f.toString(36)}function n3(u,f,l,r,n){var i=typeof u;if(i==="undefined"||i==="boolean")u=null;var y=!1;if(u===null)y=!0;else switch(i){case"string":case"number":y=!0;break;case"object":switch(u.$$typeof){case Oy:case LK:y=!0}}if(y)return y=u,n=n(y),u=r===""?"."+b8(y,0):r,L7(n)?(l="",u!=null&&(l=u.replace(w7,"$&/")+"/"),n3(n,f,l,"",function(A){return A})):n!=null&&(g8(n)&&(n=VK(n,l+(!n.key||y&&y.key===n.key?"":(""+n.key).replace(w7,"$&/")+"/")+u)),f.push(n)),1;if(y=0,r=r===""?".":r+":",L7(u))for(var _=0;_{V7.exports=B7()});var R7=nr((Nf)=>{function d8(u,f){var l=u.length;u.push(f);u:for(;0>>1,n=u[r];if(0<_3(n,f))u[r]=f,u[l]=n,l=r;else break u}}function Xr(u){return u.length===0?null:u[0]}function c3(u){if(u.length===0)return null;var f=u[0],l=u.pop();if(l!==f){u[0]=l;u:for(var r=0,n=u.length,i=n>>>1;r_3(_,l))$_3(A,_)?(u[r]=A,u[$]=l,r=$):(u[r]=_,u[y]=l,r=y);else if($_3(A,l))u[r]=A,u[$]=l,r=$;else break u}}return f}function _3(u,f){var l=u.sortIndex-f.sortIndex;return l!==0?l:u.id-f.id}if(typeof performance==="object"&&typeof performance.now==="function")e8=performance,Nf.unstable_now=function(){return e8.now()};else $3=Date,u4=$3.now(),Nf.unstable_now=function(){return $3.now()-u4};var e8,$3,u4,or=[],g0=[],PK=1,Wr=null,Ql=3,j3=!1,on=!1,By=!1,p7=typeof setTimeout==="function"?setTimeout:null,m7=typeof clearTimeout==="function"?clearTimeout:null,S7=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function f4(u){for(var f=Xr(g0);f!==null;){if(f.callback===null)c3(g0);else if(f.startTime<=u)c3(g0),f.sortIndex=f.expirationTime,d8(or,f);else break;f=Xr(g0)}}function r4(u){if(By=!1,f4(u),!on)if(Xr(or)!==null)on=!0,i4(n4);else{var f=Xr(g0);f!==null&&y4(r4,f.startTime-u)}}function n4(u,f){on=!1,By&&(By=!1,m7(Vy),Vy=-1),j3=!0;var l=Ql;try{f4(f);for(Wr=Xr(or);Wr!==null&&(!(Wr.expirationTime>f)||u&&!C7());){var r=Wr.callback;if(typeof r==="function"){Wr.callback=null,Ql=Wr.priorityLevel;var n=r(Wr.expirationTime<=f);f=Nf.unstable_now(),typeof n==="function"?Wr.callback=n:Wr===Xr(or)&&c3(or),f4(f)}else c3(or);Wr=Xr(or)}if(Wr!==null)var i=!0;else{var y=Xr(g0);y!==null&&y4(r4,y.startTime-f),i=!1}return i}finally{Wr=null,Ql=l,j3=!1}}var F3=!1,t3=null,Vy=-1,P7=5,M7=-1;function C7(){return Nf.unstable_now()-M7u||125r?(u.sortIndex=l,d8(g0,u),Xr(or)===null&&u===Xr(g0)&&(By?(m7(Vy),Vy=-1):By=!0,y4(r4,l-r))):(u.sortIndex=n,d8(or,u),on||j3||(on=!0,i4(n4))),u};Nf.unstable_shouldYield=C7;Nf.unstable_wrapCallback=function(u){var f=Ql;return function(){var l=Ql;Ql=f;try{return u.apply(this,arguments)}finally{Ql=l}}}});var h7=nr((Ip,x7)=>{x7.exports=R7()});var vJ=nr((Ar)=>{var MK=qf(),$r=h7();function Uu(u){for(var f="https://reactjs.org/docs/error-decoder.html?invariant="+u,l=1;l"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),O4=Object.prototype.hasOwnProperty,CK=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,b7={},v7={};function RK(u){if(O4.call(v7,u))return!0;if(O4.call(b7,u))return!1;if(CK.test(u))return v7[u]=!0;return b7[u]=!0,!1}function xK(u,f,l,r){if(l!==null&&l.type===0)return!1;switch(typeof f){case"function":case"symbol":return!0;case"boolean":if(r)return!1;if(l!==null)return!l.acceptsBooleans;return u=u.toLowerCase().slice(0,5),u!=="data-"&&u!=="aria-";default:return!1}}function hK(u,f,l,r){if(f===null||typeof f>"u"||xK(u,f,l,r))return!0;if(r)return!1;if(l!==null)switch(l.type){case 3:return!f;case 4:return f===!1;case 5:return isNaN(f);case 6:return isNaN(f)||1>f}return!1}function Bl(u,f,l,r,n,i,y){this.acceptsBooleans=f===2||f===3||f===4,this.attributeName=r,this.attributeNamespace=n,this.mustUseProperty=l,this.propertyName=u,this.type=f,this.sanitizeURL=i,this.removeEmptyString=y}var Al={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(u){Al[u]=new Bl(u,0,!1,u,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(u){var f=u[0];Al[f]=new Bl(f,1,!1,u[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(u){Al[u]=new Bl(u,2,!1,u.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(u){Al[u]=new Bl(u,2,!1,u,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(u){Al[u]=new Bl(u,3,!1,u.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(u){Al[u]=new Bl(u,3,!0,u,null,!1,!1)});["capture","download"].forEach(function(u){Al[u]=new Bl(u,4,!1,u,null,!1,!1)});["cols","rows","size","span"].forEach(function(u){Al[u]=new Bl(u,6,!1,u,null,!1,!1)});["rowSpan","start"].forEach(function(u){Al[u]=new Bl(u,5,!1,u.toLowerCase(),null,!1,!1)});var K2=/[\-:]([a-z])/g;function G2(u){return u[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(u){var f=u.replace(K2,G2);Al[f]=new Bl(f,1,!1,u,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(u){var f=u.replace(K2,G2);Al[f]=new Bl(f,1,!1,u,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(u){var f=u.replace(K2,G2);Al[f]=new Bl(f,1,!1,u,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(u){Al[u]=new Bl(u,1,!1,u.toLowerCase(),null,!1,!1)});Al.xlinkHref=new Bl("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(u){Al[u]=new Bl(u,1,!1,u.toLowerCase(),null,!0,!0)});function z2(u,f,l,r){var n=Al.hasOwnProperty(f)?Al[f]:null;if(n!==null?n.type!==0:r||!(2{var UK=Object.create;var{getPrototypeOf:QK,defineProperty:L7,getOwnPropertyNames:qK}=Object;var NK=Object.prototype.hasOwnProperty;function WK(u){return this[u]}var LK,wK,Pu=(u,f,l)=>{var r=u!=null&&typeof u==="object";if(r){var n=f?LK??=new WeakMap:wK??=new WeakMap,i=n.get(u);if(i)return i}l=u!=null?UK(QK(u)):{};let y=f||!u||!u.__esModule?L7(l,"default",{value:u,enumerable:!0}):l;for(let _ of qK(u))if(!NK.call(y,_))L7(y,_,{get:WK.bind(u,_),enumerable:!0});if(r)n.set(u,y);return y};var nr=(u,f)=>()=>(f||u((f={exports:{}}).exports,f),f.exports);var uf=((u)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(u,{get:(f,l)=>(typeof require<"u"?require:f)[l]}):u)(function(u){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+u+'" is not supported')});var D7=nr((au)=>{var Vy=Symbol.for("react.element"),KK=Symbol.for("react.portal"),GK=Symbol.for("react.fragment"),zK=Symbol.for("react.strict_mode"),TK=Symbol.for("react.profiler"),EK=Symbol.for("react.provider"),ZK=Symbol.for("react.context"),OK=Symbol.for("react.forward_ref"),HK=Symbol.for("react.suspense"),BK=Symbol.for("react.memo"),VK=Symbol.for("react.lazy"),w7=Symbol.iterator;function DK(u){if(u===null||typeof u!=="object")return null;return u=w7&&u[w7]||u["@@iterator"],typeof u==="function"?u:null}var z7={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},T7=Object.assign,E7={};function ui(u,f,l){this.props=u,this.context=f,this.refs=E7,this.updater=l||z7}ui.prototype.isReactComponent={};ui.prototype.setState=function(u,f){if(typeof u!=="object"&&typeof u!=="function"&&u!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,u,f,"setState")};ui.prototype.forceUpdate=function(u){this.updater.enqueueForceUpdate(this,u,"forceUpdate")};function Z7(){}Z7.prototype=ui.prototype;function g8(u,f,l){this.props=u,this.context=f,this.refs=E7,this.updater=l||z7}var s8=g8.prototype=new Z7;s8.constructor=g8;T7(s8,ui.prototype);s8.isPureReactComponent=!0;var K7=Array.isArray,O7=Object.prototype.hasOwnProperty,a8={current:null},H7={key:!0,ref:!0,__self:!0,__source:!0};function B7(u,f,l){var r,n={},i=null,y=null;if(f!=null)for(r in f.ref!==void 0&&(y=f.ref),f.key!==void 0&&(i=""+f.key),f)O7.call(f,r)&&!H7.hasOwnProperty(r)&&(n[r]=f[r]);var _=arguments.length-2;if(_===1)n.children=l;else if(1<_){for(var $=Array(_),A=0;A<_;A++)$[A]=arguments[A+2];n.children=$}if(u&&u.defaultProps)for(r in _=u.defaultProps,_)n[r]===void 0&&(n[r]=_[r]);return{$$typeof:Vy,type:u,key:i,ref:y,props:n,_owner:a8.current}}function XK(u,f){return{$$typeof:Vy,type:u.type,key:f,ref:u.ref,props:u.props,_owner:u._owner}}function o8(u){return typeof u==="object"&&u!==null&&u.$$typeof===Vy}function YK(u){var f={"=":"=0",":":"=2"};return"$"+u.replace(/[=:]/g,function(l){return f[l]})}var G7=/\/+/g;function I8(u,f){return typeof u==="object"&&u!==null&&u.key!=null?YK(""+u.key):f.toString(36)}function i3(u,f,l,r,n){var i=typeof u;if(i==="undefined"||i==="boolean")u=null;var y=!1;if(u===null)y=!0;else switch(i){case"string":case"number":y=!0;break;case"object":switch(u.$$typeof){case Vy:case KK:y=!0}}if(y)return y=u,n=n(y),u=r===""?"."+I8(y,0):r,K7(n)?(l="",u!=null&&(l=u.replace(G7,"$&/")+"/"),i3(n,f,l,"",function(A){return A})):n!=null&&(o8(n)&&(n=XK(n,l+(!n.key||y&&y.key===n.key?"":(""+n.key).replace(G7,"$&/")+"/")+u)),f.push(n)),1;if(y=0,r=r===""?".":r+":",K7(u))for(var _=0;_{X7.exports=D7()});var h7=nr((qf)=>{function f4(u,f){var l=u.length;u.push(f);u:for(;0>>1,n=u[r];if(0<$3(n,f))u[r]=f,u[l]=n,l=r;else break u}}function Xr(u){return u.length===0?null:u[0]}function j3(u){if(u.length===0)return null;var f=u[0],l=u.pop();if(l!==f){u[0]=l;u:for(var r=0,n=u.length,i=n>>>1;r$3(_,l))$$3(A,_)?(u[r]=A,u[$]=l,r=$):(u[r]=_,u[y]=l,r=y);else if($$3(A,l))u[r]=A,u[$]=l,r=$;else break u}}return f}function $3(u,f){var l=u.sortIndex-f.sortIndex;return l!==0?l:u.id-f.id}if(typeof performance==="object"&&typeof performance.now==="function")l4=performance,qf.unstable_now=function(){return l4.now()};else t3=Date,r4=t3.now(),qf.unstable_now=function(){return t3.now()-r4};var l4,t3,r4,dr=[],o0=[],CK=1,Wr=null,Ql=3,F3=!1,u1=!1,Xy=!1,P7=typeof setTimeout==="function"?setTimeout:null,M7=typeof clearTimeout==="function"?clearTimeout:null,m7=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function n4(u){for(var f=Xr(o0);f!==null;){if(f.callback===null)j3(o0);else if(f.startTime<=u)j3(o0),f.sortIndex=f.expirationTime,f4(dr,f);else break;f=Xr(o0)}}function y4(u){if(Xy=!1,n4(u),!u1)if(Xr(dr)!==null)u1=!0,$4(_4);else{var f=Xr(o0);f!==null&&t4(y4,f.startTime-u)}}function _4(u,f){u1=!1,Xy&&(Xy=!1,M7(Yy),Yy=-1),F3=!0;var l=Ql;try{n4(f);for(Wr=Xr(dr);Wr!==null&&(!(Wr.expirationTime>f)||u&&!x7());){var r=Wr.callback;if(typeof r==="function"){Wr.callback=null,Ql=Wr.priorityLevel;var n=r(Wr.expirationTime<=f);f=qf.unstable_now(),typeof n==="function"?Wr.callback=n:Wr===Xr(dr)&&j3(dr),n4(f)}else j3(dr);Wr=Xr(dr)}if(Wr!==null)var i=!0;else{var y=Xr(o0);y!==null&&t4(y4,y.startTime-f),i=!1}return i}finally{Wr=null,Ql=l,F3=!1}}var J3=!1,A3=null,Yy=-1,C7=5,R7=-1;function x7(){return qf.unstable_now()-R7u||125r?(u.sortIndex=l,f4(o0,u),Xr(dr)===null&&u===Xr(o0)&&(Xy?(M7(Yy),Yy=-1):Xy=!0,t4(y4,l-r))):(u.sortIndex=n,f4(dr,u),u1||F3||(u1=!0,$4(_4))),u};qf.unstable_shouldYield=x7;qf.unstable_wrapCallback=function(u){var f=Ql;return function(){var l=Ql;Ql=f;try{return u.apply(this,arguments)}finally{Ql=l}}}});var v7=nr((sp,b7)=>{b7.exports=h7()});var IJ=nr((Ar)=>{var RK=Qf(),$r=v7();function Uu(u){for(var f="https://reactjs.org/docs/error-decoder.html?invariant="+u,l=1;l"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),V4=Object.prototype.hasOwnProperty,xK=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,k7={},I7={};function hK(u){if(V4.call(I7,u))return!0;if(V4.call(k7,u))return!1;if(xK.test(u))return I7[u]=!0;return k7[u]=!0,!1}function bK(u,f,l,r){if(l!==null&&l.type===0)return!1;switch(typeof f){case"function":case"symbol":return!0;case"boolean":if(r)return!1;if(l!==null)return!l.acceptsBooleans;return u=u.toLowerCase().slice(0,5),u!=="data-"&&u!=="aria-";default:return!1}}function vK(u,f,l,r){if(f===null||typeof f>"u"||bK(u,f,l,r))return!0;if(r)return!1;if(l!==null)switch(l.type){case 3:return!f;case 4:return f===!1;case 5:return isNaN(f);case 6:return isNaN(f)||1>f}return!1}function Vl(u,f,l,r,n,i,y){this.acceptsBooleans=f===2||f===3||f===4,this.attributeName=r,this.attributeNamespace=n,this.mustUseProperty=l,this.propertyName=u,this.type=f,this.sanitizeURL=i,this.removeEmptyString=y}var tl={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(u){tl[u]=new Vl(u,0,!1,u,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(u){var f=u[0];tl[f]=new Vl(f,1,!1,u[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(u){tl[u]=new Vl(u,2,!1,u.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(u){tl[u]=new Vl(u,2,!1,u,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(u){tl[u]=new Vl(u,3,!1,u.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(u){tl[u]=new Vl(u,3,!0,u,null,!1,!1)});["capture","download"].forEach(function(u){tl[u]=new Vl(u,4,!1,u,null,!1,!1)});["cols","rows","size","span"].forEach(function(u){tl[u]=new Vl(u,6,!1,u,null,!1,!1)});["rowSpan","start"].forEach(function(u){tl[u]=new Vl(u,5,!1,u.toLowerCase(),null,!1,!1)});var T2=/[\-:]([a-z])/g;function E2(u){return u[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(u){var f=u.replace(T2,E2);tl[f]=new Vl(f,1,!1,u,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(u){var f=u.replace(T2,E2);tl[f]=new Vl(f,1,!1,u,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(u){var f=u.replace(T2,E2);tl[f]=new Vl(f,1,!1,u,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(u){tl[u]=new Vl(u,1,!1,u.toLowerCase(),null,!1,!1)});tl.xlinkHref=new Vl("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(u){tl[u]=new Vl(u,1,!1,u.toLowerCase(),null,!0,!0)});function Z2(u,f,l,r){var n=tl.hasOwnProperty(f)?tl[f]:null;if(n!==null?n.type!==0:r||!(2_||n[y]!==i[_]){var $=` -`+n[y].replace(" at new "," at ");return u.displayName&&$.includes("")&&($=$.replace("",u.displayName)),$}while(1<=y&&0<=_);break}}}finally{$4=!1,Error.prepareStackTrace=l}return(u=u?u.displayName||u.name:"")?My(u):""}function bK(u){switch(u.tag){case 5:return My(u.type);case 16:return My("Lazy");case 13:return My("Suspense");case 19:return My("SuspenseList");case 0:case 2:case 15:return u=t4(u.type,!1),u;case 11:return u=t4(u.type.render,!1),u;case 1:return u=t4(u.type,!0),u;default:return""}}function D4(u){if(u==null)return null;if(typeof u==="function")return u.displayName||u.name||null;if(typeof u==="string")return u;switch(u){case ri:return"Fragment";case li:return"Portal";case H4:return"Profiler";case T2:return"StrictMode";case B4:return"Suspense";case V4:return"SuspenseList"}if(typeof u==="object")switch(u.$$typeof){case aj:return(u.displayName||"Context")+".Consumer";case sj:return(u._context.displayName||"Context")+".Provider";case E2:var f=u.render;return u=u.displayName,u||(u=f.displayName||f.name||"",u=u!==""?"ForwardRef("+u+")":"ForwardRef"),u;case Z2:return f=u.displayName||null,f!==null?f:D4(u.type)||"Memo";case a0:f=u._payload,u=u._init;try{return D4(u(f))}catch(l){}}return null}function vK(u){var f=u.type;switch(u.tag){case 24:return"Cache";case 9:return(f.displayName||"Context")+".Consumer";case 10:return(f._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return u=f.render,u=u.displayName||u.name||"",f.displayName||(u!==""?"ForwardRef("+u+")":"ForwardRef");case 7:return"Fragment";case 5:return f;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return D4(f);case 8:return f===T2?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof f==="function")return f.displayName||f.name||null;if(typeof f==="string")return f}return null}function cn(u){switch(typeof u){case"boolean":case"number":case"string":case"undefined":return u;case"object":return u;default:return""}}function dj(u){var f=u.type;return(u=u.nodeName)&&u.toLowerCase()==="input"&&(f==="checkbox"||f==="radio")}function kK(u){var f=dj(u)?"checked":"value",l=Object.getOwnPropertyDescriptor(u.constructor.prototype,f),r=""+u[f];if(!u.hasOwnProperty(f)&&typeof l<"u"&&typeof l.get==="function"&&typeof l.set==="function"){var{get:n,set:i}=l;return Object.defineProperty(u,f,{configurable:!0,get:function(){return n.call(this)},set:function(y){r=""+y,i.call(this,y)}}),Object.defineProperty(u,f,{enumerable:l.enumerable}),{getValue:function(){return r},setValue:function(y){r=""+y},stopTracking:function(){u._valueTracker=null,delete u[f]}}}}function U3(u){u._valueTracker||(u._valueTracker=kK(u))}function ej(u){if(!u)return!1;var f=u._valueTracker;if(!f)return!0;var l=f.getValue(),r="";return u&&(r=dj(u)?u.checked?"true":"false":u.value),u=r,u!==l?(f.setValue(u),!0):!1}function C3(u){if(u=u||(typeof document<"u"?document:void 0),typeof u>"u")return null;try{return u.activeElement||u.body}catch(f){return u.body}}function X4(u,f){var l=f.checked;return Bf({},f,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:l!=null?l:u._wrapperState.initialChecked})}function I7(u,f){var l=f.defaultValue==null?"":f.defaultValue,r=f.checked!=null?f.checked:f.defaultChecked;l=cn(f.value!=null?f.value:l),u._wrapperState={initialChecked:r,initialValue:l,controlled:f.type==="checkbox"||f.type==="radio"?f.checked!=null:f.value!=null}}function uF(u,f){f=f.checked,f!=null&&z2(u,"checked",f,!1)}function Y4(u,f){uF(u,f);var l=cn(f.value),r=f.type;if(l!=null)if(r==="number"){if(l===0&&u.value===""||u.value!=l)u.value=""+l}else u.value!==""+l&&(u.value=""+l);else if(r==="submit"||r==="reset"){u.removeAttribute("value");return}f.hasOwnProperty("value")?S4(u,f.type,l):f.hasOwnProperty("defaultValue")&&S4(u,f.type,cn(f.defaultValue)),f.checked==null&&f.defaultChecked!=null&&(u.defaultChecked=!!f.defaultChecked)}function g7(u,f,l){if(f.hasOwnProperty("value")||f.hasOwnProperty("defaultValue")){var r=f.type;if(!(r!=="submit"&&r!=="reset"||f.value!==void 0&&f.value!==null))return;f=""+u._wrapperState.initialValue,l||f===u.value||(u.value=f),u.defaultValue=f}l=u.name,l!==""&&(u.name=""),u.defaultChecked=!!u._wrapperState.initialChecked,l!==""&&(u.name=l)}function S4(u,f,l){if(f!=="number"||C3(u.ownerDocument)!==u)l==null?u.defaultValue=""+u._wrapperState.initialValue:u.defaultValue!==""+l&&(u.defaultValue=""+l)}var Cy=Array.isArray;function Ji(u,f,l,r){if(u=u.options,f){f={};for(var n=0;n"+f.valueOf().toString()+"";for(f=Q3.firstChild;u.firstChild;)u.removeChild(u.firstChild);for(;f.firstChild;)u.appendChild(f.firstChild)}});function r_(u,f){if(f){var l=u.firstChild;if(l&&l===u.lastChild&&l.nodeType===3){l.nodeValue=f;return}}u.textContent=f}var Iy={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},IK=["Webkit","ms","Moz","O"];Object.keys(Iy).forEach(function(u){IK.forEach(function(f){f=f+u.charAt(0).toUpperCase()+u.substring(1),Iy[f]=Iy[u]})});function nF(u,f,l){return f==null||typeof f==="boolean"||f===""?"":l||typeof f!=="number"||f===0||Iy.hasOwnProperty(u)&&Iy[u]?(""+f).trim():f+"px"}function iF(u,f){u=u.style;for(var l in f)if(f.hasOwnProperty(l)){var r=l.indexOf("--")===0,n=nF(l,f[l],r);l==="float"&&(l="cssFloat"),r?u.setProperty(l,n):u[l]=n}}var gK=Bf({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function P4(u,f){if(f){if(gK[u]&&(f.children!=null||f.dangerouslySetInnerHTML!=null))throw Error(Uu(137,u));if(f.dangerouslySetInnerHTML!=null){if(f.children!=null)throw Error(Uu(60));if(typeof f.dangerouslySetInnerHTML!=="object"||!("__html"in f.dangerouslySetInnerHTML))throw Error(Uu(61))}if(f.style!=null&&typeof f.style!=="object")throw Error(Uu(62))}}function M4(u,f){if(u.indexOf("-")===-1)return typeof f.is==="string";switch(u){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var C4=null;function O2(u){return u=u.target||u.srcElement||window,u.correspondingUseElement&&(u=u.correspondingUseElement),u.nodeType===3?u.parentNode:u}var R4=null,Ui=null,Qi=null;function o7(u){if(u=w_(u)){if(typeof R4!=="function")throw Error(Uu(280));var f=u.stateNode;f&&(f=Jt(f),R4(u.stateNode,u.type,f))}}function yF(u){Ui?Qi?Qi.push(u):Qi=[u]:Ui=u}function _F(){if(Ui){var u=Ui,f=Qi;if(Qi=Ui=null,o7(u),f)for(u=0;u>>=0,u===0?32:31-(iG(u)/yG|0)|0}var q3=64,N3=4194304;function Ry(u){switch(u&-u){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return u&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return u&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return u}}function b3(u,f){var l=u.pendingLanes;if(l===0)return 0;var r=0,n=u.suspendedLanes,i=u.pingedLanes,y=l&268435455;if(y!==0){var _=y&~n;_!==0?r=Ry(_):(i&=y,i!==0&&(r=Ry(i)))}else y=l&~n,y!==0?r=Ry(y):i!==0&&(r=Ry(i));if(r===0)return 0;if(f!==0&&f!==r&&(f&n)===0&&(n=r&-r,i=f&-f,n>=i||n===16&&(i&4194240)!==0))return f;if((r&4)!==0&&(r|=l&16),f=u.entangledLanes,f!==0)for(u=u.entanglements,f&=r;0l;l++)f.push(u);return f}function W_(u,f,l){u.pendingLanes|=f,f!==536870912&&(u.suspendedLanes=0,u.pingedLanes=0),u=u.eventTimes,f=31-Pr(f),u[f]=l}function AG(u,f){var l=u.pendingLanes&~f;u.pendingLanes=f,u.suspendedLanes=0,u.pingedLanes=0,u.expiredLanes&=f,u.mutableReadLanes&=f,u.entangledLanes&=f,f=u.entanglements;var r=u.eventTimes;for(u=u.expirationTimes;0=sy),yj=String.fromCharCode(32),_j=!1;function ZF(u,f){switch(u){case"keyup":return PG.indexOf(f.keyCode)!==-1;case"keydown":return f.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function OF(u){return u=u.detail,typeof u==="object"&&"data"in u?u.data:null}var ni=!1;function CG(u,f){switch(u){case"compositionend":return OF(f);case"keypress":if(f.which!==32)return null;return _j=!0,yj;case"textInput":return u=f.data,u===yj&&_j?null:u;default:return null}}function RG(u,f){if(ni)return u==="compositionend"||!p2&&ZF(u,f)?(u=TF(),B3=X2=un=null,ni=!1,u):null;switch(u){case"paste":return null;case"keypress":if(!(f.ctrlKey||f.altKey||f.metaKey)||f.ctrlKey&&f.altKey){if(f.char&&1=f)return{node:l,offset:f-u};u=r}u:{for(;l;){if(l.nextSibling){l=l.nextSibling;break u}l=l.parentNode}l=void 0}l=Aj(l)}}function DF(u,f){return u&&f?u===f?!0:u&&u.nodeType===3?!1:f&&f.nodeType===3?DF(u,f.parentNode):("contains"in u)?u.contains(f):u.compareDocumentPosition?!!(u.compareDocumentPosition(f)&16):!1:!1}function XF(){for(var u=window,f=C3();f instanceof u.HTMLIFrameElement;){try{var l=typeof f.contentWindow.location.href==="string"}catch(r){l=!1}if(l)u=f.contentWindow;else break;f=C3(u.document)}return f}function m2(u){var f=u&&u.nodeName&&u.nodeName.toLowerCase();return f&&(f==="input"&&(u.type==="text"||u.type==="search"||u.type==="tel"||u.type==="url"||u.type==="password")||f==="textarea"||u.contentEditable==="true")}function aG(u){var f=XF(),l=u.focusedElem,r=u.selectionRange;if(f!==l&&l&&l.ownerDocument&&DF(l.ownerDocument.documentElement,l)){if(r!==null&&m2(l)){if(f=r.start,u=r.end,u===void 0&&(u=f),"selectionStart"in l)l.selectionStart=f,l.selectionEnd=Math.min(u,l.value.length);else if(u=(f=l.ownerDocument||document)&&f.defaultView||window,u.getSelection){u=u.getSelection();var n=l.textContent.length,i=Math.min(r.start,n);r=r.end===void 0?i:Math.min(r.end,n),!u.extend&&i>r&&(n=r,r=i,i=n),n=cj(l,i);var y=cj(l,r);n&&y&&(u.rangeCount!==1||u.anchorNode!==n.node||u.anchorOffset!==n.offset||u.focusNode!==y.node||u.focusOffset!==y.offset)&&(f=f.createRange(),f.setStart(n.node,n.offset),u.removeAllRanges(),i>r?(u.addRange(f),u.extend(y.node,y.offset)):(f.setEnd(y.node,y.offset),u.addRange(f)))}}f=[];for(u=l;u=u.parentNode;)u.nodeType===1&&f.push({element:u,left:u.scrollLeft,top:u.scrollTop});typeof l.focus==="function"&&l.focus();for(l=0;l=document.documentMode,ii=null,I4=null,oy=null,g4=!1;function jj(u,f,l){var r=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;g4||ii==null||ii!==C3(r)||(r=ii,("selectionStart"in r)&&m2(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),oy&&t_(oy,r)||(oy=r,r=I3(I4,"onSelect"),0$i||(u.current=l2[$i],l2[$i]=null,$i--)}function Wf(u,f){$i++,l2[$i]=u.current,u.current=f}var jn={},Ll=Jn(jn),Rl=Jn(!1),y1=jn;function wi(u,f){var l=u.type.contextTypes;if(!l)return jn;var r=u.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===f)return r.__reactInternalMemoizedMaskedChildContext;var n={},i;for(i in l)n[i]=f[i];return r&&(u=u.stateNode,u.__reactInternalMemoizedUnmaskedChildContext=f,u.__reactInternalMemoizedMaskedChildContext=n),n}function xl(u){return u=u.childContextTypes,u!==null&&u!==void 0}function s3(){Gf(Rl),Gf(Ll)}function Wj(u,f,l){if(Ll.current!==jn)throw Error(Uu(168));Wf(Ll,f),Wf(Rl,l)}function xF(u,f,l){var r=u.stateNode;if(f=f.childContextTypes,typeof r.getChildContext!=="function")return l;r=r.getChildContext();for(var n in r)if(!(n in f))throw Error(Uu(108,vK(u)||"Unknown",n));return Bf({},l,r)}function a3(u){return u=(u=u.stateNode)&&u.__reactInternalMemoizedMergedChildContext||jn,y1=Ll.current,Wf(Ll,u),Wf(Rl,Rl.current),!0}function Lj(u,f,l){var r=u.stateNode;if(!r)throw Error(Uu(169));l?(u=xF(u,f,y1),r.__reactInternalMemoizedMergedChildContext=u,Gf(Rl),Gf(Ll),Wf(Ll,u)):Gf(Rl),Wf(Rl,l)}var L0=null,Ut=!1,W4=!1;function hF(u){L0===null?L0=[u]:L0.push(u)}function yz(u){Ut=!0,hF(u)}function Un(){if(!W4&&L0!==null){W4=!0;var u=0,f=Af;try{var l=L0;for(Af=1;u>=y,n-=y,w0=1<<32-Pr(f)+n|l<E?(D=H,H=null):D=H.sibling;var h=F(J,H,q[E],W);if(h===null){H===null&&(H=D);break}u&&H&&h.alternate===null&&f(J,H),N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h,H=D}if(E===q.length)return l(J,H),Ef&&en(J,E),z;if(H===null){for(;EE?(D=H,H=null):D=H.sibling;var V=F(J,H,h.value,W);if(V===null){H===null&&(H=D);break}u&&H&&V.alternate===null&&f(J,H),N=i(V,N,E),Z===null?z=V:Z.sibling=V,Z=V,H=D}if(h.done)return l(J,H),Ef&&en(J,E),z;if(H===null){for(;!h.done;E++,h=q.next())h=j(J,h.value,W),h!==null&&(N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h);return Ef&&en(J,E),z}for(H=r(J,H);!h.done;E++,h=q.next())h=U(H,J,E,h.value,W),h!==null&&(u&&h.alternate!==null&&H.delete(h.key===null?E:h.key),N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h);return u&&H.forEach(function(Y){return f(J,Y)}),Ef&&en(J,E),z}function w(J,N,q,W){if(typeof q==="object"&&q!==null&&q.type===ri&&q.key===null&&(q=q.props.children),typeof q==="object"&&q!==null){switch(q.$$typeof){case J3:u:{for(var z=q.key,Z=N;Z!==null;){if(Z.key===z){if(z=q.type,z===ri){if(Z.tag===7){l(J,Z.sibling),N=n(Z,q.props.children),N.return=J,J=N;break u}}else if(Z.elementType===z||typeof z==="object"&&z!==null&&z.$$typeof===a0&&Gj(z)===Z.type){l(J,Z.sibling),N=n(Z,q.props),N.ref=py(J,Z,q),N.return=J,J=N;break u}l(J,Z);break}else f(J,Z);Z=Z.sibling}q.type===ri?(N=i1(q.props.children,J.mode,W,q.key),N.return=J,J=N):(W=M3(q.type,q.key,q.props,null,J.mode,W),W.ref=py(J,N,q),W.return=J,J=W)}return y(J);case li:u:{for(Z=q.key;N!==null;){if(N.key===Z)if(N.tag===4&&N.stateNode.containerInfo===q.containerInfo&&N.stateNode.implementation===q.implementation){l(J,N.sibling),N=n(N,q.children||[]),N.return=J,J=N;break u}else{l(J,N);break}else f(J,N);N=N.sibling}N=Z4(q,J.mode,W),N.return=J,J=N}return y(J);case a0:return Z=q._init,w(J,N,Z(q._payload),W)}if(Cy(q))return Q(J,N,q,W);if(Dy(q))return L(J,N,q,W);T3(J,q)}return typeof q==="string"&&q!==""||typeof q==="number"?(q=""+q,N!==null&&N.tag===6?(l(J,N.sibling),N=n(N,q),N.return=J,J=N):(l(J,N),N=E4(q,J.mode,W),N.return=J,J=N),y(J)):l(J,N)}return w}var Gi=IF(!0),gF=IF(!1),e3=Jn(null),ut=null,ci=null,R2=null;function x2(){R2=ci=ut=null}function h2(u){var f=e3.current;Gf(e3),u._currentValue=f}function i2(u,f,l){for(;u!==null;){var r=u.alternate;if((u.childLanes&f)!==f?(u.childLanes|=f,r!==null&&(r.childLanes|=f)):r!==null&&(r.childLanes&f)!==f&&(r.childLanes|=f),u===l)break;u=u.return}}function Ni(u,f){ut=u,R2=ci=null,u=u.dependencies,u!==null&&u.firstContext!==null&&((u.lanes&f)!==0&&(Cl=!0),u.firstContext=null)}function zr(u){var f=u._currentValue;if(R2!==u)if(u={context:u,memoizedValue:f,next:null},ci===null){if(ut===null)throw Error(Uu(308));ci=u,ut.dependencies={lanes:0,firstContext:u}}else ci=ci.next=u;return f}var l1=null;function b2(u){l1===null?l1=[u]:l1.push(u)}function sF(u,f,l,r){var n=f.interleaved;return n===null?(l.next=l,b2(f)):(l.next=n.next,n.next=l),f.interleaved=l,E0(u,r)}function E0(u,f){u.lanes|=f;var l=u.alternate;l!==null&&(l.lanes|=f),l=u;for(u=u.return;u!==null;)u.childLanes|=f,l=u.alternate,l!==null&&(l.childLanes|=f),l=u,u=u.return;return l.tag===3?l.stateNode:null}var o0=!1;function v2(u){u.updateQueue={baseState:u.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function aF(u,f){u=u.updateQueue,f.updateQueue===u&&(f.updateQueue={baseState:u.baseState,firstBaseUpdate:u.firstBaseUpdate,lastBaseUpdate:u.lastBaseUpdate,shared:u.shared,effects:u.effects})}function G0(u,f){return{eventTime:u,lane:f,tag:0,payload:null,callback:null,next:null}}function _n(u,f,l){var r=u.updateQueue;if(r===null)return null;if(r=r.shared,(lf&2)!==0){var n=r.pending;return n===null?f.next=f:(f.next=n.next,n.next=f),r.pending=f,E0(u,l)}return n=r.interleaved,n===null?(f.next=f,b2(r)):(f.next=n.next,n.next=f),r.interleaved=f,E0(u,l)}function X3(u,f,l){if(f=f.updateQueue,f!==null&&(f=f.shared,(l&4194240)!==0)){var r=f.lanes;r&=u.pendingLanes,l|=r,f.lanes=l,B2(u,l)}}function zj(u,f){var{updateQueue:l,alternate:r}=u;if(r!==null&&(r=r.updateQueue,l===r)){var n=null,i=null;if(l=l.firstBaseUpdate,l!==null){do{var y={eventTime:l.eventTime,lane:l.lane,tag:l.tag,payload:l.payload,callback:l.callback,next:null};i===null?n=i=y:i=i.next=y,l=l.next}while(l!==null);i===null?n=i=f:i=i.next=f}else n=i=f;l={baseState:r.baseState,firstBaseUpdate:n,lastBaseUpdate:i,shared:r.shared,effects:r.effects},u.updateQueue=l;return}u=l.lastBaseUpdate,u===null?l.firstBaseUpdate=f:u.next=f,l.lastBaseUpdate=f}function ft(u,f,l,r){var n=u.updateQueue;o0=!1;var{firstBaseUpdate:i,lastBaseUpdate:y}=n,_=n.shared.pending;if(_!==null){n.shared.pending=null;var $=_,A=$.next;$.next=null,y===null?i=A:y.next=A,y=$;var c=u.alternate;c!==null&&(c=c.updateQueue,_=c.lastBaseUpdate,_!==y&&(_===null?c.firstBaseUpdate=A:_.next=A,c.lastBaseUpdate=$))}if(i!==null){var j=n.baseState;y=0,c=A=$=null,_=i;do{var{lane:F,eventTime:U}=_;if((r&F)===F){c!==null&&(c=c.next={eventTime:U,lane:0,tag:_.tag,payload:_.payload,callback:_.callback,next:null});u:{var Q=u,L=_;switch(F=f,U=l,L.tag){case 1:if(Q=L.payload,typeof Q==="function"){j=Q.call(U,j,F);break u}j=Q;break u;case 3:Q.flags=Q.flags&-65537|128;case 0:if(Q=L.payload,F=typeof Q==="function"?Q.call(U,j,F):Q,F===null||F===void 0)break u;j=Bf({},j,F);break u;case 2:o0=!0}}_.callback!==null&&_.lane!==0&&(u.flags|=64,F=n.effects,F===null?n.effects=[_]:F.push(_))}else U={eventTime:U,lane:F,tag:_.tag,payload:_.payload,callback:_.callback,next:null},c===null?(A=c=U,$=j):c=c.next=U,y|=F;if(_=_.next,_===null)if(_=n.shared.pending,_===null)break;else F=_,_=F.next,F.next=null,n.lastBaseUpdate=F,n.shared.pending=null}while(1);if(c===null&&($=j),n.baseState=$,n.firstBaseUpdate=A,n.lastBaseUpdate=c,f=n.shared.interleaved,f!==null){n=f;do y|=n.lane,n=n.next;while(n!==f)}else i===null&&(n.shared.lanes=0);t1|=y,u.lanes=y,u.memoizedState=j}}function Tj(u,f,l){if(u=f.effects,f.effects=null,u!==null)for(f=0;fl?l:4,u(!0);var r=w4.transition;w4.transition={};try{u(!1),f()}finally{Af=l,w4.transition=r}}function FJ(){return Tr().memoizedState}function Az(u,f,l){var r=tn(u);if(l={lane:r,action:l,hasEagerState:!1,eagerState:null,next:null},JJ(u))UJ(f,l);else if(l=sF(u,f,l,r),l!==null){var n=Hl();Mr(l,u,r,n),QJ(l,f,r)}}function cz(u,f,l){var r=tn(u),n={lane:r,action:l,hasEagerState:!1,eagerState:null,next:null};if(JJ(u))UJ(f,n);else{var i=u.alternate;if(u.lanes===0&&(i===null||i.lanes===0)&&(i=f.lastRenderedReducer,i!==null))try{var y=f.lastRenderedState,_=i(y,l);if(n.hasEagerState=!0,n.eagerState=_,Cr(_,y)){var $=f.interleaved;$===null?(n.next=n,b2(f)):(n.next=$.next,$.next=n),f.interleaved=n;return}}catch(A){}finally{}l=sF(u,f,n,r),l!==null&&(n=Hl(),Mr(l,u,r,n),QJ(l,f,r))}}function JJ(u){var f=u.alternate;return u===Hf||f!==null&&f===Hf}function UJ(u,f){dy=rt=!0;var l=u.pending;l===null?f.next=f:(f.next=l.next,l.next=f),u.pending=f}function QJ(u,f,l){if((l&4194240)!==0){var r=f.lanes;r&=u.pendingLanes,l|=r,f.lanes=l,B2(u,l)}}var nt={readContext:zr,useCallback:ql,useContext:ql,useEffect:ql,useImperativeHandle:ql,useInsertionEffect:ql,useLayoutEffect:ql,useMemo:ql,useReducer:ql,useRef:ql,useState:ql,useDebugValue:ql,useDeferredValue:ql,useTransition:ql,useMutableSource:ql,useSyncExternalStore:ql,useId:ql,unstable_isNewReconciler:!1},jz={readContext:zr,useCallback:function(u,f){return er().memoizedState=[u,f===void 0?null:f],u},useContext:zr,useEffect:Zj,useImperativeHandle:function(u,f,l){return l=l!==null&&l!==void 0?l.concat([u]):null,S3(4194308,4,$J.bind(null,f,u),l)},useLayoutEffect:function(u,f){return S3(4194308,4,u,f)},useInsertionEffect:function(u,f){return S3(4,2,u,f)},useMemo:function(u,f){var l=er();return f=f===void 0?null:f,u=u(),l.memoizedState=[u,f],u},useReducer:function(u,f,l){var r=er();return f=l!==void 0?l(f):f,r.memoizedState=r.baseState=f,u={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:u,lastRenderedState:f},r.queue=u,u=u.dispatch=Az.bind(null,Hf,u),[r.memoizedState,u]},useRef:function(u){var f=er();return u={current:u},f.memoizedState=u},useState:Ej,useDebugValue:e2,useDeferredValue:function(u){return er().memoizedState=u},useTransition:function(){var u=Ej(!1),f=u[0];return u=tz.bind(null,u[1]),er().memoizedState=u,[f,u]},useMutableSource:function(){},useSyncExternalStore:function(u,f,l){var r=Hf,n=er();if(Ef){if(l===void 0)throw Error(Uu(407));l=l()}else{if(l=f(),fl===null)throw Error(Uu(349));($1&30)!==0||uJ(r,f,l)}n.memoizedState=l;var i={value:l,getSnapshot:f};return n.queue=i,Zj(lJ.bind(null,r,i,u),[u]),r.flags|=2048,q_(9,fJ.bind(null,r,i,l,f),void 0,null),l},useId:function(){var u=er(),f=fl.identifierPrefix;if(Ef){var l=K0,r=w0;l=(r&~(1<<32-Pr(r)-1)).toString(32)+l,f=":"+f+"R"+l,l=U_++,0")&&($=$.replace("",u.displayName)),$}while(1<=y&&0<=_);break}}}finally{c4=!1,Error.prepareStackTrace=l}return(u=u?u.displayName||u.name:"")?xy(u):""}function kK(u){switch(u.tag){case 5:return xy(u.type);case 16:return xy("Lazy");case 13:return xy("Suspense");case 19:return xy("SuspenseList");case 0:case 2:case 15:return u=j4(u.type,!1),u;case 11:return u=j4(u.type.render,!1),u;case 1:return u=j4(u.type,!0),u;default:return""}}function S4(u){if(u==null)return null;if(typeof u==="function")return u.displayName||u.name||null;if(typeof u==="string")return u;switch(u){case ni:return"Fragment";case ri:return"Portal";case D4:return"Profiler";case O2:return"StrictMode";case X4:return"Suspense";case Y4:return"SuspenseList"}if(typeof u==="object")switch(u.$$typeof){case dj:return(u.displayName||"Context")+".Consumer";case oj:return(u._context.displayName||"Context")+".Provider";case H2:var f=u.render;return u=u.displayName,u||(u=f.displayName||f.name||"",u=u!==""?"ForwardRef("+u+")":"ForwardRef"),u;case B2:return f=u.displayName||null,f!==null?f:S4(u.type)||"Memo";case e0:f=u._payload,u=u._init;try{return S4(u(f))}catch(l){}}return null}function IK(u){var f=u.type;switch(u.tag){case 24:return"Cache";case 9:return(f.displayName||"Context")+".Consumer";case 10:return(f._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return u=f.render,u=u.displayName||u.name||"",f.displayName||(u!==""?"ForwardRef("+u+")":"ForwardRef");case 7:return"Fragment";case 5:return f;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return S4(f);case 8:return f===O2?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof f==="function")return f.displayName||f.name||null;if(typeof f==="string")return f}return null}function Jn(u){switch(typeof u){case"boolean":case"number":case"string":case"undefined":return u;case"object":return u;default:return""}}function uF(u){var f=u.type;return(u=u.nodeName)&&u.toLowerCase()==="input"&&(f==="checkbox"||f==="radio")}function gK(u){var f=uF(u)?"checked":"value",l=Object.getOwnPropertyDescriptor(u.constructor.prototype,f),r=""+u[f];if(!u.hasOwnProperty(f)&&typeof l<"u"&&typeof l.get==="function"&&typeof l.set==="function"){var{get:n,set:i}=l;return Object.defineProperty(u,f,{configurable:!0,get:function(){return n.call(this)},set:function(y){r=""+y,i.call(this,y)}}),Object.defineProperty(u,f,{enumerable:l.enumerable}),{getValue:function(){return r},setValue:function(y){r=""+y},stopTracking:function(){u._valueTracker=null,delete u[f]}}}}function Q3(u){u._valueTracker||(u._valueTracker=gK(u))}function fF(u){if(!u)return!1;var f=u._valueTracker;if(!f)return!0;var l=f.getValue(),r="";return u&&(r=uF(u)?u.checked?"true":"false":u.value),u=r,u!==l?(f.setValue(u),!0):!1}function R3(u){if(u=u||(typeof document<"u"?document:void 0),typeof u>"u")return null;try{return u.activeElement||u.body}catch(f){return u.body}}function p4(u,f){var l=f.checked;return Bf({},f,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:l!=null?l:u._wrapperState.initialChecked})}function s7(u,f){var l=f.defaultValue==null?"":f.defaultValue,r=f.checked!=null?f.checked:f.defaultChecked;l=Jn(f.value!=null?f.value:l),u._wrapperState={initialChecked:r,initialValue:l,controlled:f.type==="checkbox"||f.type==="radio"?f.checked!=null:f.value!=null}}function lF(u,f){f=f.checked,f!=null&&Z2(u,"checked",f,!1)}function m4(u,f){lF(u,f);var l=Jn(f.value),r=f.type;if(l!=null)if(r==="number"){if(l===0&&u.value===""||u.value!=l)u.value=""+l}else u.value!==""+l&&(u.value=""+l);else if(r==="submit"||r==="reset"){u.removeAttribute("value");return}f.hasOwnProperty("value")?P4(u,f.type,l):f.hasOwnProperty("defaultValue")&&P4(u,f.type,Jn(f.defaultValue)),f.checked==null&&f.defaultChecked!=null&&(u.defaultChecked=!!f.defaultChecked)}function a7(u,f,l){if(f.hasOwnProperty("value")||f.hasOwnProperty("defaultValue")){var r=f.type;if(!(r!=="submit"&&r!=="reset"||f.value!==void 0&&f.value!==null))return;f=""+u._wrapperState.initialValue,l||f===u.value||(u.value=f),u.defaultValue=f}l=u.name,l!==""&&(u.name=""),u.defaultChecked=!!u._wrapperState.initialChecked,l!==""&&(u.name=l)}function P4(u,f,l){if(f!=="number"||R3(u.ownerDocument)!==u)l==null?u.defaultValue=""+u._wrapperState.initialValue:u.defaultValue!==""+l&&(u.defaultValue=""+l)}var hy=Array.isArray;function Ui(u,f,l,r){if(u=u.options,f){f={};for(var n=0;n"+f.valueOf().toString()+"";for(f=q3.firstChild;u.firstChild;)u.removeChild(u.firstChild);for(;f.firstChild;)u.appendChild(f.firstChild)}});function y_(u,f){if(f){var l=u.firstChild;if(l&&l===u.lastChild&&l.nodeType===3){l.nodeValue=f;return}}u.textContent=f}var ay={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},sK=["Webkit","ms","Moz","O"];Object.keys(ay).forEach(function(u){sK.forEach(function(f){f=f+u.charAt(0).toUpperCase()+u.substring(1),ay[f]=ay[u]})});function yF(u,f,l){return f==null||typeof f==="boolean"||f===""?"":l||typeof f!=="number"||f===0||ay.hasOwnProperty(u)&&ay[u]?(""+f).trim():f+"px"}function _F(u,f){u=u.style;for(var l in f)if(f.hasOwnProperty(l)){var r=l.indexOf("--")===0,n=yF(l,f[l],r);l==="float"&&(l="cssFloat"),r?u.setProperty(l,n):u[l]=n}}var aK=Bf({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function R4(u,f){if(f){if(aK[u]&&(f.children!=null||f.dangerouslySetInnerHTML!=null))throw Error(Uu(137,u));if(f.dangerouslySetInnerHTML!=null){if(f.children!=null)throw Error(Uu(60));if(typeof f.dangerouslySetInnerHTML!=="object"||!("__html"in f.dangerouslySetInnerHTML))throw Error(Uu(61))}if(f.style!=null&&typeof f.style!=="object")throw Error(Uu(62))}}function x4(u,f){if(u.indexOf("-")===-1)return typeof f.is==="string";switch(u){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var h4=null;function V2(u){return u=u.target||u.srcElement||window,u.correspondingUseElement&&(u=u.correspondingUseElement),u.nodeType===3?u.parentNode:u}var b4=null,Qi=null,qi=null;function e7(u){if(u=z_(u)){if(typeof b4!=="function")throw Error(Uu(280));var f=u.stateNode;f&&(f=Ut(f),b4(u.stateNode,u.type,f))}}function $F(u){Qi?qi?qi.push(u):qi=[u]:Qi=u}function tF(){if(Qi){var u=Qi,f=qi;if(qi=Qi=null,e7(u),f)for(u=0;u>>=0,u===0?32:31-(_G(u)/$G|0)|0}var N3=64,W3=4194304;function by(u){switch(u&-u){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return u&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return u&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return u}}function v3(u,f){var l=u.pendingLanes;if(l===0)return 0;var r=0,n=u.suspendedLanes,i=u.pingedLanes,y=l&268435455;if(y!==0){var _=y&~n;_!==0?r=by(_):(i&=y,i!==0&&(r=by(i)))}else y=l&~n,y!==0?r=by(y):i!==0&&(r=by(i));if(r===0)return 0;if(f!==0&&f!==r&&(f&n)===0&&(n=r&-r,i=f&-f,n>=i||n===16&&(i&4194240)!==0))return f;if((r&4)!==0&&(r|=l&16),f=u.entangledLanes,f!==0)for(u=u.entanglements,f&=r;0l;l++)f.push(u);return f}function K_(u,f,l){u.pendingLanes|=f,f!==536870912&&(u.suspendedLanes=0,u.pingedLanes=0),u=u.eventTimes,f=31-Pr(f),u[f]=l}function jG(u,f){var l=u.pendingLanes&~f;u.pendingLanes=f,u.suspendedLanes=0,u.pingedLanes=0,u.expiredLanes&=f,u.mutableReadLanes&=f,u.entangledLanes&=f,f=u.entanglements;var r=u.eventTimes;for(u=u.expirationTimes;0=dy),$j=String.fromCharCode(32),tj=!1;function HF(u,f){switch(u){case"keyup":return CG.indexOf(f.keyCode)!==-1;case"keydown":return f.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function BF(u){return u=u.detail,typeof u==="object"&&"data"in u?u.data:null}var ii=!1;function xG(u,f){switch(u){case"compositionend":return BF(f);case"keypress":if(f.which!==32)return null;return tj=!0,$j;case"textInput":return u=f.data,u===$j&&tj?null:u;default:return null}}function hG(u,f){if(ii)return u==="compositionend"||!M2&&HF(u,f)?(u=ZF(),V3=p2=rn=null,ii=!1,u):null;switch(u){case"paste":return null;case"keypress":if(!(f.ctrlKey||f.altKey||f.metaKey)||f.ctrlKey&&f.altKey){if(f.char&&1=f)return{node:l,offset:f-u};u=r}u:{for(;l;){if(l.nextSibling){l=l.nextSibling;break u}l=l.parentNode}l=void 0}l=jj(l)}}function YF(u,f){return u&&f?u===f?!0:u&&u.nodeType===3?!1:f&&f.nodeType===3?YF(u,f.parentNode):("contains"in u)?u.contains(f):u.compareDocumentPosition?!!(u.compareDocumentPosition(f)&16):!1:!1}function SF(){for(var u=window,f=R3();f instanceof u.HTMLIFrameElement;){try{var l=typeof f.contentWindow.location.href==="string"}catch(r){l=!1}if(l)u=f.contentWindow;else break;f=R3(u.document)}return f}function C2(u){var f=u&&u.nodeName&&u.nodeName.toLowerCase();return f&&(f==="input"&&(u.type==="text"||u.type==="search"||u.type==="tel"||u.type==="url"||u.type==="password")||f==="textarea"||u.contentEditable==="true")}function dG(u){var f=SF(),l=u.focusedElem,r=u.selectionRange;if(f!==l&&l&&l.ownerDocument&&YF(l.ownerDocument.documentElement,l)){if(r!==null&&C2(l)){if(f=r.start,u=r.end,u===void 0&&(u=f),"selectionStart"in l)l.selectionStart=f,l.selectionEnd=Math.min(u,l.value.length);else if(u=(f=l.ownerDocument||document)&&f.defaultView||window,u.getSelection){u=u.getSelection();var n=l.textContent.length,i=Math.min(r.start,n);r=r.end===void 0?i:Math.min(r.end,n),!u.extend&&i>r&&(n=r,r=i,i=n),n=Fj(l,i);var y=Fj(l,r);n&&y&&(u.rangeCount!==1||u.anchorNode!==n.node||u.anchorOffset!==n.offset||u.focusNode!==y.node||u.focusOffset!==y.offset)&&(f=f.createRange(),f.setStart(n.node,n.offset),u.removeAllRanges(),i>r?(u.addRange(f),u.extend(y.node,y.offset)):(f.setEnd(y.node,y.offset),u.addRange(f)))}}f=[];for(u=l;u=u.parentNode;)u.nodeType===1&&f.push({element:u,left:u.scrollLeft,top:u.scrollTop});typeof l.focus==="function"&&l.focus();for(l=0;l=document.documentMode,yi=null,a4=null,u_=null,o4=!1;function Jj(u,f,l){var r=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;o4||yi==null||yi!==R3(r)||(r=yi,("selectionStart"in r)&&C2(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),u_&&j_(u_,r)||(u_=r,r=g3(a4,"onSelect"),0ti||(u.current=i2[ti],i2[ti]=null,ti--)}function Nf(u,f){ti++,i2[ti]=u.current,u.current=f}var Un={},Ll=qn(Un),xl=qn(!1),t1=Un;function Ki(u,f){var l=u.type.contextTypes;if(!l)return Un;var r=u.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===f)return r.__reactInternalMemoizedMaskedChildContext;var n={},i;for(i in l)n[i]=f[i];return r&&(u=u.stateNode,u.__reactInternalMemoizedUnmaskedChildContext=f,u.__reactInternalMemoizedMaskedChildContext=n),n}function hl(u){return u=u.childContextTypes,u!==null&&u!==void 0}function a3(){Kf(xl),Kf(Ll)}function wj(u,f,l){if(Ll.current!==Un)throw Error(Uu(168));Nf(Ll,f),Nf(xl,l)}function bF(u,f,l){var r=u.stateNode;if(f=f.childContextTypes,typeof r.getChildContext!=="function")return l;r=r.getChildContext();for(var n in r)if(!(n in f))throw Error(Uu(108,IK(u)||"Unknown",n));return Bf({},l,r)}function o3(u){return u=(u=u.stateNode)&&u.__reactInternalMemoizedMergedChildContext||Un,t1=Ll.current,Nf(Ll,u),Nf(xl,xl.current),!0}function Kj(u,f,l){var r=u.stateNode;if(!r)throw Error(Uu(169));l?(u=bF(u,f,t1),r.__reactInternalMemoizedMergedChildContext=u,Kf(xl),Kf(Ll),Nf(Ll,u)):Kf(xl),Nf(xl,l)}var w0=null,Qt=!1,K4=!1;function vF(u){w0===null?w0=[u]:w0.push(u)}function $z(u){Qt=!0,vF(u)}function Nn(){if(!K4&&w0!==null){K4=!0;var u=0,f=tf;try{var l=w0;for(tf=1;u>=y,n-=y,K0=1<<32-Pr(f)+n|l<E?(D=H,H=null):D=H.sibling;var h=F(J,H,q[E],W);if(h===null){H===null&&(H=D);break}u&&H&&h.alternate===null&&f(J,H),N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h,H=D}if(E===q.length)return l(J,H),Tf&&l1(J,E),z;if(H===null){for(;EE?(D=H,H=null):D=H.sibling;var V=F(J,H,h.value,W);if(V===null){H===null&&(H=D);break}u&&H&&V.alternate===null&&f(J,H),N=i(V,N,E),Z===null?z=V:Z.sibling=V,Z=V,H=D}if(h.done)return l(J,H),Tf&&l1(J,E),z;if(H===null){for(;!h.done;E++,h=q.next())h=j(J,h.value,W),h!==null&&(N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h);return Tf&&l1(J,E),z}for(H=r(J,H);!h.done;E++,h=q.next())h=U(H,J,E,h.value,W),h!==null&&(u&&h.alternate!==null&&H.delete(h.key===null?E:h.key),N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h);return u&&H.forEach(function(Y){return f(J,Y)}),Tf&&l1(J,E),z}function w(J,N,q,W){if(typeof q==="object"&&q!==null&&q.type===ni&&q.key===null&&(q=q.props.children),typeof q==="object"&&q!==null){switch(q.$$typeof){case U3:u:{for(var z=q.key,Z=N;Z!==null;){if(Z.key===z){if(z=q.type,z===ni){if(Z.tag===7){l(J,Z.sibling),N=n(Z,q.props.children),N.return=J,J=N;break u}}else if(Z.elementType===z||typeof z==="object"&&z!==null&&z.$$typeof===e0&&Tj(z)===Z.type){l(J,Z.sibling),N=n(Z,q.props),N.ref=My(J,Z,q),N.return=J,J=N;break u}l(J,Z);break}else f(J,Z);Z=Z.sibling}q.type===ni?(N=$1(q.props.children,J.mode,W,q.key),N.return=J,J=N):(W=C3(q.type,q.key,q.props,null,J.mode,W),W.ref=My(J,N,q),W.return=J,J=W)}return y(J);case ri:u:{for(Z=q.key;N!==null;){if(N.key===Z)if(N.tag===4&&N.stateNode.containerInfo===q.containerInfo&&N.stateNode.implementation===q.implementation){l(J,N.sibling),N=n(N,q.children||[]),N.return=J,J=N;break u}else{l(J,N);break}else f(J,N);N=N.sibling}N=B4(q,J.mode,W),N.return=J,J=N}return y(J);case e0:return Z=q._init,w(J,N,Z(q._payload),W)}if(hy(q))return Q(J,N,q,W);if(Sy(q))return L(J,N,q,W);E3(J,q)}return typeof q==="string"&&q!==""||typeof q==="number"?(q=""+q,N!==null&&N.tag===6?(l(J,N.sibling),N=n(N,q),N.return=J,J=N):(l(J,N),N=H4(q,J.mode,W),N.return=J,J=N),y(J)):l(J,N)}return w}var zi=sF(!0),aF=sF(!1),ut=qn(null),ft=null,ji=null,b2=null;function v2(){b2=ji=ft=null}function k2(u){var f=ut.current;Kf(ut),u._currentValue=f}function $2(u,f,l){for(;u!==null;){var r=u.alternate;if((u.childLanes&f)!==f?(u.childLanes|=f,r!==null&&(r.childLanes|=f)):r!==null&&(r.childLanes&f)!==f&&(r.childLanes|=f),u===l)break;u=u.return}}function Wi(u,f){ft=u,b2=ji=null,u=u.dependencies,u!==null&&u.firstContext!==null&&((u.lanes&f)!==0&&(Rl=!0),u.firstContext=null)}function zr(u){var f=u._currentValue;if(b2!==u)if(u={context:u,memoizedValue:f,next:null},ji===null){if(ft===null)throw Error(Uu(308));ji=u,ft.dependencies={lanes:0,firstContext:u}}else ji=ji.next=u;return f}var i1=null;function I2(u){i1===null?i1=[u]:i1.push(u)}function oF(u,f,l,r){var n=f.interleaved;return n===null?(l.next=l,I2(f)):(l.next=n.next,n.next=l),f.interleaved=l,Z0(u,r)}function Z0(u,f){u.lanes|=f;var l=u.alternate;l!==null&&(l.lanes|=f),l=u;for(u=u.return;u!==null;)u.childLanes|=f,l=u.alternate,l!==null&&(l.childLanes|=f),l=u,u=u.return;return l.tag===3?l.stateNode:null}var un=!1;function g2(u){u.updateQueue={baseState:u.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function dF(u,f){u=u.updateQueue,f.updateQueue===u&&(f.updateQueue={baseState:u.baseState,firstBaseUpdate:u.firstBaseUpdate,lastBaseUpdate:u.lastBaseUpdate,shared:u.shared,effects:u.effects})}function z0(u,f){return{eventTime:u,lane:f,tag:0,payload:null,callback:null,next:null}}function An(u,f,l){var r=u.updateQueue;if(r===null)return null;if(r=r.shared,(lf&2)!==0){var n=r.pending;return n===null?f.next=f:(f.next=n.next,n.next=f),r.pending=f,Z0(u,l)}return n=r.interleaved,n===null?(f.next=f,I2(r)):(f.next=n.next,n.next=f),r.interleaved=f,Z0(u,l)}function Y3(u,f,l){if(f=f.updateQueue,f!==null&&(f=f.shared,(l&4194240)!==0)){var r=f.lanes;r&=u.pendingLanes,l|=r,f.lanes=l,X2(u,l)}}function Ej(u,f){var{updateQueue:l,alternate:r}=u;if(r!==null&&(r=r.updateQueue,l===r)){var n=null,i=null;if(l=l.firstBaseUpdate,l!==null){do{var y={eventTime:l.eventTime,lane:l.lane,tag:l.tag,payload:l.payload,callback:l.callback,next:null};i===null?n=i=y:i=i.next=y,l=l.next}while(l!==null);i===null?n=i=f:i=i.next=f}else n=i=f;l={baseState:r.baseState,firstBaseUpdate:n,lastBaseUpdate:i,shared:r.shared,effects:r.effects},u.updateQueue=l;return}u=l.lastBaseUpdate,u===null?l.firstBaseUpdate=f:u.next=f,l.lastBaseUpdate=f}function lt(u,f,l,r){var n=u.updateQueue;un=!1;var{firstBaseUpdate:i,lastBaseUpdate:y}=n,_=n.shared.pending;if(_!==null){n.shared.pending=null;var $=_,A=$.next;$.next=null,y===null?i=A:y.next=A,y=$;var c=u.alternate;c!==null&&(c=c.updateQueue,_=c.lastBaseUpdate,_!==y&&(_===null?c.firstBaseUpdate=A:_.next=A,c.lastBaseUpdate=$))}if(i!==null){var j=n.baseState;y=0,c=A=$=null,_=i;do{var{lane:F,eventTime:U}=_;if((r&F)===F){c!==null&&(c=c.next={eventTime:U,lane:0,tag:_.tag,payload:_.payload,callback:_.callback,next:null});u:{var Q=u,L=_;switch(F=f,U=l,L.tag){case 1:if(Q=L.payload,typeof Q==="function"){j=Q.call(U,j,F);break u}j=Q;break u;case 3:Q.flags=Q.flags&-65537|128;case 0:if(Q=L.payload,F=typeof Q==="function"?Q.call(U,j,F):Q,F===null||F===void 0)break u;j=Bf({},j,F);break u;case 2:un=!0}}_.callback!==null&&_.lane!==0&&(u.flags|=64,F=n.effects,F===null?n.effects=[_]:F.push(_))}else U={eventTime:U,lane:F,tag:_.tag,payload:_.payload,callback:_.callback,next:null},c===null?(A=c=U,$=j):c=c.next=U,y|=F;if(_=_.next,_===null)if(_=n.shared.pending,_===null)break;else F=_,_=F.next,F.next=null,n.lastBaseUpdate=F,n.shared.pending=null}while(1);if(c===null&&($=j),n.baseState=$,n.firstBaseUpdate=A,n.lastBaseUpdate=c,f=n.shared.interleaved,f!==null){n=f;do y|=n.lane,n=n.next;while(n!==f)}else i===null&&(n.shared.lanes=0);j1|=y,u.lanes=y,u.memoizedState=j}}function Zj(u,f,l){if(u=f.effects,f.effects=null,u!==null)for(f=0;fl?l:4,u(!0);var r=z4.transition;z4.transition={};try{u(!1),f()}finally{tf=l,z4.transition=r}}function UJ(){return Tr().memoizedState}function jz(u,f,l){var r=jn(u);if(l={lane:r,action:l,hasEagerState:!1,eagerState:null,next:null},QJ(u))qJ(f,l);else if(l=oF(u,f,l,r),l!==null){var n=Bl();Mr(l,u,r,n),NJ(l,f,r)}}function Fz(u,f,l){var r=jn(u),n={lane:r,action:l,hasEagerState:!1,eagerState:null,next:null};if(QJ(u))qJ(f,n);else{var i=u.alternate;if(u.lanes===0&&(i===null||i.lanes===0)&&(i=f.lastRenderedReducer,i!==null))try{var y=f.lastRenderedState,_=i(y,l);if(n.hasEagerState=!0,n.eagerState=_,Cr(_,y)){var $=f.interleaved;$===null?(n.next=n,I2(f)):(n.next=$.next,$.next=n),f.interleaved=n;return}}catch(A){}finally{}l=oF(u,f,n,r),l!==null&&(n=Bl(),Mr(l,u,r,n),NJ(l,f,r))}}function QJ(u){var f=u.alternate;return u===Hf||f!==null&&f===Hf}function qJ(u,f){f_=nt=!0;var l=u.pending;l===null?f.next=f:(f.next=l.next,l.next=f),u.pending=f}function NJ(u,f,l){if((l&4194240)!==0){var r=f.lanes;r&=u.pendingLanes,l|=r,f.lanes=l,X2(u,l)}}var it={readContext:zr,useCallback:ql,useContext:ql,useEffect:ql,useImperativeHandle:ql,useInsertionEffect:ql,useLayoutEffect:ql,useMemo:ql,useReducer:ql,useRef:ql,useState:ql,useDebugValue:ql,useDeferredValue:ql,useTransition:ql,useMutableSource:ql,useSyncExternalStore:ql,useId:ql,unstable_isNewReconciler:!1},Jz={readContext:zr,useCallback:function(u,f){return u0().memoizedState=[u,f===void 0?null:f],u},useContext:zr,useEffect:Hj,useImperativeHandle:function(u,f,l){return l=l!==null&&l!==void 0?l.concat([u]):null,p3(4194308,4,AJ.bind(null,f,u),l)},useLayoutEffect:function(u,f){return p3(4194308,4,u,f)},useInsertionEffect:function(u,f){return p3(4,2,u,f)},useMemo:function(u,f){var l=u0();return f=f===void 0?null:f,u=u(),l.memoizedState=[u,f],u},useReducer:function(u,f,l){var r=u0();return f=l!==void 0?l(f):f,r.memoizedState=r.baseState=f,u={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:u,lastRenderedState:f},r.queue=u,u=u.dispatch=jz.bind(null,Hf,u),[r.memoizedState,u]},useRef:function(u){var f=u0();return u={current:u},f.memoizedState=u},useState:Oj,useDebugValue:l5,useDeferredValue:function(u){return u0().memoizedState=u},useTransition:function(){var u=Oj(!1),f=u[0];return u=cz.bind(null,u[1]),u0().memoizedState=u,[f,u]},useMutableSource:function(){},useSyncExternalStore:function(u,f,l){var r=Hf,n=u0();if(Tf){if(l===void 0)throw Error(Uu(407));l=l()}else{if(l=f(),ul===null)throw Error(Uu(349));(c1&30)!==0||lJ(r,f,l)}n.memoizedState=l;var i={value:l,getSnapshot:f};return n.queue=i,Hj(nJ.bind(null,r,i,u),[u]),r.flags|=2048,L_(9,rJ.bind(null,r,i,l,f),void 0,null),l},useId:function(){var u=u0(),f=ul.identifierPrefix;if(Tf){var l=G0,r=K0;l=(r&~(1<<32-Pr(r)-1)).toString(32)+l,f=":"+f+"R"+l,l=N_++,0",u=u.removeChild(u.firstChild)):typeof r.is==="string"?u=y.createElement(l,{is:r.is}):(u=y.createElement(l),l==="select"&&(y=u,r.multiple?y.multiple=!0:r.size&&(y.size=r.size))):u=y.createElementNS(u,l),u[u0]=f,u[j_]=r,EJ(u,f,!1,!1),f.stateNode=u;u:{switch(y=M4(l,r),l){case"dialog":Kf("cancel",u),Kf("close",u),n=r;break;case"iframe":case"object":case"embed":Kf("load",u),n=r;break;case"video":case"audio":for(n=0;nEi&&(f.flags|=128,r=!0,my(i,!1),f.lanes=4194304)}else{if(!r)if(u=lt(y),u!==null){if(f.flags|=128,r=!0,l=u.updateQueue,l!==null&&(f.updateQueue=l,f.flags|=4),my(i,!0),i.tail===null&&i.tailMode==="hidden"&&!y.alternate&&!Ef)return Nl(f),null}else 2*mf()-i.renderingStartTime>Ei&&l!==1073741824&&(f.flags|=128,r=!0,my(i,!1),f.lanes=4194304);i.isBackwards?(y.sibling=f.child,f.child=y):(l=i.last,l!==null?l.sibling=y:f.child=y,i.last=y)}if(i.tail!==null)return f=i.tail,i.rendering=f,i.tail=f.sibling,i.renderingStartTime=mf(),f.sibling=null,l=Of.current,Wf(Of,r?l&1|2:l&1),f;return Nl(f),null;case 22:case 23:return i5(),r=f.memoizedState!==null,u!==null&&u.memoizedState!==null!==r&&(f.flags|=8192),r&&(f.mode&1)!==0?(ir&1073741824)!==0&&(Nl(f),f.subtreeFlags&6&&(f.flags|=8192)):Nl(f),null;case 24:return null;case 25:return null}throw Error(Uu(156,f.tag))}function Lz(u,f){switch(M2(f),f.tag){case 1:return xl(f.type)&&s3(),u=f.flags,u&65536?(f.flags=u&-65537|128,f):null;case 3:return zi(),Gf(Rl),Gf(Ll),g2(),u=f.flags,(u&65536)!==0&&(u&128)===0?(f.flags=u&-65537|128,f):null;case 5:return I2(f),null;case 13:if(Gf(Of),u=f.memoizedState,u!==null&&u.dehydrated!==null){if(f.alternate===null)throw Error(Uu(340));Ki()}return u=f.flags,u&65536?(f.flags=u&-65537|128,f):null;case 19:return Gf(Of),null;case 4:return zi(),null;case 10:return h2(f.type._context),null;case 22:case 23:return i5(),null;case 24:return null;default:return null}}var Z3=!1,Wl=!1,wz=typeof WeakSet==="function"?WeakSet:Set,zu=null;function ji(u,f){var l=u.ref;if(l!==null)if(typeof l==="function")try{l(null)}catch(r){Df(u,f,r)}else l.current=null}function J2(u,f,l){try{l()}catch(r){Df(u,f,r)}}var Pj=!1;function Kz(u,f){if(o4=v3,u=XF(),m2(u)){if("selectionStart"in u)var l={start:u.selectionStart,end:u.selectionEnd};else u:{l=(l=u.ownerDocument)&&l.defaultView||window;var r=l.getSelection&&l.getSelection();if(r&&r.rangeCount!==0){l=r.anchorNode;var{anchorOffset:n,focusNode:i}=r;r=r.focusOffset;try{l.nodeType,i.nodeType}catch(W){l=null;break u}var y=0,_=-1,$=-1,A=0,c=0,j=u,F=null;f:for(;;){for(var U;;){if(j!==l||n!==0&&j.nodeType!==3||(_=y+n),j!==i||r!==0&&j.nodeType!==3||($=y+r),j.nodeType===3&&(y+=j.nodeValue.length),(U=j.firstChild)===null)break;F=j,j=U}for(;;){if(j===u)break f;if(F===l&&++A===n&&(_=y),F===i&&++c===r&&($=y),(U=j.nextSibling)!==null)break;j=F,F=j.parentNode}j=U}l=_===-1||$===-1?null:{start:_,end:$}}else l=null}l=l||{start:0,end:0}}else l=null;d4={focusedElem:u,selectionRange:l},v3=!1;for(zu=f;zu!==null;)if(f=zu,u=f.child,(f.subtreeFlags&1028)!==0&&u!==null)u.return=f,zu=u;else for(;zu!==null;){f=zu;try{var Q=f.alternate;if((f.flags&1024)!==0)switch(f.tag){case 0:case 11:case 15:break;case 1:if(Q!==null){var{memoizedProps:L,memoizedState:w}=Q,J=f.stateNode,N=J.getSnapshotBeforeUpdate(f.elementType===f.type?L:Sr(f.type,L),w);J.__reactInternalSnapshotBeforeUpdate=N}break;case 3:var q=f.stateNode.containerInfo;q.nodeType===1?q.textContent="":q.nodeType===9&&q.documentElement&&q.removeChild(q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(Uu(163))}}catch(W){Df(f,f.return,W)}if(u=f.sibling,u!==null){u.return=f.return,zu=u;break}zu=f.return}return Q=Pj,Pj=!1,Q}function ey(u,f,l){var r=f.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var n=r=r.next;do{if((n.tag&u)===u){var i=n.destroy;n.destroy=void 0,i!==void 0&&J2(f,l,i)}n=n.next}while(n!==r)}}function Nt(u,f){if(f=f.updateQueue,f=f!==null?f.lastEffect:null,f!==null){var l=f=f.next;do{if((l.tag&u)===u){var r=l.create;l.destroy=r()}l=l.next}while(l!==f)}}function U2(u){var f=u.ref;if(f!==null){var l=u.stateNode;switch(u.tag){case 5:u=l;break;default:u=l}typeof f==="function"?f(u):f.current=u}}function HJ(u){var f=u.alternate;f!==null&&(u.alternate=null,HJ(f)),u.child=null,u.deletions=null,u.sibling=null,u.tag===5&&(f=u.stateNode,f!==null&&(delete f[u0],delete f[j_],delete f[f2],delete f[nz],delete f[iz])),u.stateNode=null,u.return=null,u.dependencies=null,u.memoizedProps=null,u.memoizedState=null,u.pendingProps=null,u.stateNode=null,u.updateQueue=null}function BJ(u){return u.tag===5||u.tag===3||u.tag===4}function Mj(u){u:for(;;){for(;u.sibling===null;){if(u.return===null||BJ(u.return))return null;u=u.return}u.sibling.return=u.return;for(u=u.sibling;u.tag!==5&&u.tag!==6&&u.tag!==18;){if(u.flags&2)continue u;if(u.child===null||u.tag===4)continue u;else u.child.return=u,u=u.child}if(!(u.flags&2))return u.stateNode}}function Q2(u,f,l){var r=u.tag;if(r===5||r===6)u=u.stateNode,f?l.nodeType===8?l.parentNode.insertBefore(u,f):l.insertBefore(u,f):(l.nodeType===8?(f=l.parentNode,f.insertBefore(u,l)):(f=l,f.appendChild(u)),l=l._reactRootContainer,l!==null&&l!==void 0||f.onclick!==null||(f.onclick=g3));else if(r!==4&&(u=u.child,u!==null))for(Q2(u,f,l),u=u.sibling;u!==null;)Q2(u,f,l),u=u.sibling}function q2(u,f,l){var r=u.tag;if(r===5||r===6)u=u.stateNode,f?l.insertBefore(u,f):l.appendChild(u);else if(r!==4&&(u=u.child,u!==null))for(q2(u,f,l),u=u.sibling;u!==null;)q2(u,f,l),u=u.sibling}var $l=null,pr=!1;function s0(u,f,l){for(l=l.child;l!==null;)VJ(u,f,l),l=l.sibling}function VJ(u,f,l){if(f0&&typeof f0.onCommitFiberUnmount==="function")try{f0.onCommitFiberUnmount(At,l)}catch(_){}switch(l.tag){case 5:Wl||ji(l,f);case 6:var r=$l,n=pr;$l=null,s0(u,f,l),$l=r,pr=n,$l!==null&&(pr?(u=$l,l=l.stateNode,u.nodeType===8?u.parentNode.removeChild(l):u.removeChild(l)):$l.removeChild(l.stateNode));break;case 18:$l!==null&&(pr?(u=$l,l=l.stateNode,u.nodeType===8?N4(u.parentNode,l):u.nodeType===1&&N4(u,l),__(u)):N4($l,l.stateNode));break;case 4:r=$l,n=pr,$l=l.stateNode.containerInfo,pr=!0,s0(u,f,l),$l=r,pr=n;break;case 0:case 11:case 14:case 15:if(!Wl&&(r=l.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){n=r=r.next;do{var i=n,y=i.destroy;i=i.tag,y!==void 0&&((i&2)!==0?J2(l,f,y):(i&4)!==0&&J2(l,f,y)),n=n.next}while(n!==r)}s0(u,f,l);break;case 1:if(!Wl&&(ji(l,f),r=l.stateNode,typeof r.componentWillUnmount==="function"))try{r.props=l.memoizedProps,r.state=l.memoizedState,r.componentWillUnmount()}catch(_){Df(l,f,_)}s0(u,f,l);break;case 21:s0(u,f,l);break;case 22:l.mode&1?(Wl=(r=Wl)||l.memoizedState!==null,s0(u,f,l),Wl=r):s0(u,f,l);break;default:s0(u,f,l)}}function Cj(u){var f=u.updateQueue;if(f!==null){u.updateQueue=null;var l=u.stateNode;l===null&&(l=u.stateNode=new wz),f.forEach(function(r){var n=Vz.bind(null,u,r);l.has(r)||(l.add(r),r.then(n,n))})}}function Yr(u,f){var l=f.deletions;if(l!==null)for(var r=0;rn&&(n=y),r&=~i}if(r=n,r=mf()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3000>r?3000:4320>r?4320:1960*zz(r/1960))-r,10u?16:u,fn===null)var r=!1;else{if(u=fn,fn=null,_t=0,(lf&6)!==0)throw Error(Uu(331));var n=lf;lf|=4;for(zu=u.current;zu!==null;){var i=zu,y=i.child;if((zu.flags&16)!==0){var _=i.deletions;if(_!==null){for(var $=0;$<_.length;$++){var A=_[$];for(zu=A;zu!==null;){var c=zu;switch(c.tag){case 0:case 11:case 15:ey(8,c,i)}var j=c.child;if(j!==null)j.return=c,zu=j;else for(;zu!==null;){c=zu;var{sibling:F,return:U}=c;if(HJ(c),c===A){zu=null;break}if(F!==null){F.return=U,zu=F;break}zu=U}}}var Q=i.alternate;if(Q!==null){var L=Q.child;if(L!==null){Q.child=null;do{var w=L.sibling;L.sibling=null,L=w}while(L!==null)}}zu=i}}if((i.subtreeFlags&2064)!==0&&y!==null)y.return=i,zu=y;else u:for(;zu!==null;){if(i=zu,(i.flags&2048)!==0)switch(i.tag){case 0:case 11:case 15:ey(9,i,i.return)}var J=i.sibling;if(J!==null){J.return=i.return,zu=J;break u}zu=i.return}}var N=u.current;for(zu=N;zu!==null;){y=zu;var q=y.child;if((y.subtreeFlags&2064)!==0&&q!==null)q.return=y,zu=q;else u:for(y=N;zu!==null;){if(_=zu,(_.flags&2048)!==0)try{switch(_.tag){case 0:case 11:case 15:Nt(9,_)}}catch(z){Df(_,_.return,z)}if(_===y){zu=null;break u}var W=_.sibling;if(W!==null){W.return=_.return,zu=W;break u}zu=_.return}}if(lf=n,Un(),f0&&typeof f0.onPostCommitFiberRoot==="function")try{f0.onPostCommitFiberRoot(At,u)}catch(z){}r=!0}return r}finally{Af=l,Gr.transition=f}}return!1}function vj(u,f,l){f=Ti(l,f),f=NJ(u,f,1),u=_n(u,f,1),f=Hl(),u!==null&&(W_(u,1,f),hl(u,f))}function Df(u,f,l){if(u.tag===3)vj(u,u,l);else for(;f!==null;){if(f.tag===3){vj(f,u,l);break}else if(f.tag===1){var r=f.stateNode;if(typeof f.type.getDerivedStateFromError==="function"||typeof r.componentDidCatch==="function"&&($n===null||!$n.has(r))){u=Ti(l,u),u=WJ(f,u,1),f=_n(f,u,1),u=Hl(),f!==null&&(W_(f,1,u),hl(f,u));break}}f=f.return}}function Hz(u,f,l){var r=u.pingCache;r!==null&&r.delete(f),f=Hl(),u.pingedLanes|=u.suspendedLanes&l,fl===u&&(tl&l)===l&&(sf===4||sf===3&&(tl&130023424)===tl&&500>mf()-r5?n1(u,0):l5|=l),hl(u,f)}function MJ(u,f){f===0&&((u.mode&1)===0?f=1:(f=N3,N3<<=1,(N3&130023424)===0&&(N3=4194304)));var l=Hl();u=E0(u,f),u!==null&&(W_(u,f,l),hl(u,l))}function Bz(u){var f=u.memoizedState,l=0;f!==null&&(l=f.retryLane),MJ(u,l)}function Vz(u,f){var l=0;switch(u.tag){case 13:var{stateNode:r,memoizedState:n}=u;n!==null&&(l=n.retryLane);break;case 19:r=u.stateNode;break;default:throw Error(Uu(314))}r!==null&&r.delete(f),MJ(u,l)}var CJ;CJ=function(u,f,l){if(u!==null)if(u.memoizedProps!==f.pendingProps||Rl.current)Cl=!0;else{if((u.lanes&l)===0&&(f.flags&128)===0)return Cl=!1,Nz(u,f,l);Cl=(u.flags&131072)!==0?!0:!1}else Cl=!1,Ef&&(f.flags&1048576)!==0&&bF(f,d3,f.index);switch(f.lanes=0,f.tag){case 2:var r=f.type;p3(u,f),u=f.pendingProps;var n=wi(f,Ll.current);Ni(f,l),n=a2(null,f,r,u,n,l);var i=o2();return f.flags|=1,typeof n==="object"&&n!==null&&typeof n.render==="function"&&n.$$typeof===void 0?(f.tag=1,f.memoizedState=null,f.updateQueue=null,xl(r)?(i=!0,a3(f)):i=!1,f.memoizedState=n.state!==null&&n.state!==void 0?n.state:null,v2(f),n.updater=qt,f.stateNode=n,n._reactInternals=f,_2(f,r,u,l),f=A2(null,f,r,!0,i,l)):(f.tag=0,Ef&&i&&P2(f),Ol(null,f,n,l),f=f.child),f;case 16:r=f.elementType;u:{switch(p3(u,f),u=f.pendingProps,n=r._init,r=n(r._payload),f.type=r,n=f.tag=Xz(r),u=Sr(r,u),n){case 0:f=t2(null,f,r,u,l);break u;case 1:f=Sj(null,f,r,u,l);break u;case 11:f=Xj(null,f,r,u,l);break u;case 14:f=Yj(null,f,r,Sr(r.type,u),l);break u}throw Error(Uu(306,r,""))}return f;case 0:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),t2(u,f,r,n,l);case 1:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),Sj(u,f,r,n,l);case 3:u:{if(GJ(f),u===null)throw Error(Uu(387));r=f.pendingProps,i=f.memoizedState,n=i.element,aF(u,f),ft(f,r,null,l);var y=f.memoizedState;if(r=y.element,i.isDehydrated)if(i={element:r,isDehydrated:!1,cache:y.cache,pendingSuspenseBoundaries:y.pendingSuspenseBoundaries,transitions:y.transitions},f.updateQueue.baseState=i,f.memoizedState=i,f.flags&256){n=Ti(Error(Uu(423)),f),f=pj(u,f,r,l,n);break u}else if(r!==n){n=Ti(Error(Uu(424)),f),f=pj(u,f,r,l,n);break u}else for(yr=yn(f.stateNode.containerInfo.firstChild),_r=f,Ef=!0,mr=null,l=gF(f,null,r,l),f.child=l;l;)l.flags=l.flags&-3|4096,l=l.sibling;else{if(Ki(),r===n){f=Z0(u,f,l);break u}Ol(u,f,r,l)}f=f.child}return f;case 5:return oF(f),u===null&&n2(f),r=f.type,n=f.pendingProps,i=u!==null?u.memoizedProps:null,y=n.children,e4(r,n)?y=null:i!==null&&e4(r,i)&&(f.flags|=32),KJ(u,f),Ol(u,f,y,l),f.child;case 6:return u===null&&n2(f),null;case 13:return zJ(u,f,l);case 4:return k2(f,f.stateNode.containerInfo),r=f.pendingProps,u===null?f.child=Gi(f,null,r,l):Ol(u,f,r,l),f.child;case 11:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),Xj(u,f,r,n,l);case 7:return Ol(u,f,f.pendingProps,l),f.child;case 8:return Ol(u,f,f.pendingProps.children,l),f.child;case 12:return Ol(u,f,f.pendingProps.children,l),f.child;case 10:u:{if(r=f.type._context,n=f.pendingProps,i=f.memoizedProps,y=n.value,Wf(e3,r._currentValue),r._currentValue=y,i!==null)if(Cr(i.value,y)){if(i.children===n.children&&!Rl.current){f=Z0(u,f,l);break u}}else for(i=f.child,i!==null&&(i.return=f);i!==null;){var _=i.dependencies;if(_!==null){y=i.child;for(var $=_.firstContext;$!==null;){if($.context===r){if(i.tag===1){$=G0(-1,l&-l),$.tag=2;var A=i.updateQueue;if(A!==null){A=A.shared;var c=A.pending;c===null?$.next=$:($.next=c.next,c.next=$),A.pending=$}}i.lanes|=l,$=i.alternate,$!==null&&($.lanes|=l),i2(i.return,l,f),_.lanes|=l;break}$=$.next}}else if(i.tag===10)y=i.type===f.type?null:i.child;else if(i.tag===18){if(y=i.return,y===null)throw Error(Uu(341));y.lanes|=l,_=y.alternate,_!==null&&(_.lanes|=l),i2(y,l,f),y=i.sibling}else y=i.child;if(y!==null)y.return=i;else for(y=i;y!==null;){if(y===f){y=null;break}if(i=y.sibling,i!==null){i.return=y.return,y=i;break}y=y.return}i=y}Ol(u,f,n.children,l),f=f.child}return f;case 9:return n=f.type,r=f.pendingProps.children,Ni(f,l),n=zr(n),r=r(n),f.flags|=1,Ol(u,f,r,l),f.child;case 14:return r=f.type,n=Sr(r,f.pendingProps),n=Sr(r.type,n),Yj(u,f,r,n,l);case 15:return LJ(u,f,f.type,f.pendingProps,l);case 17:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),p3(u,f),f.tag=1,xl(r)?(u=!0,a3(f)):u=!1,Ni(f,l),qJ(f,r,n),_2(f,r,n,l),A2(null,f,r,!0,u,l);case 19:return TJ(u,f,l);case 22:return wJ(u,f,l)}throw Error(Uu(156,f.tag))};function RJ(u,f){return JF(u,f)}function Dz(u,f,l,r){this.tag=u,this.key=l,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=f,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Kr(u,f,l,r){return new Dz(u,f,l,r)}function _5(u){return u=u.prototype,!(!u||!u.isReactComponent)}function Xz(u){if(typeof u==="function")return _5(u)?1:0;if(u!==void 0&&u!==null){if(u=u.$$typeof,u===E2)return 11;if(u===Z2)return 14}return 2}function An(u,f){var l=u.alternate;return l===null?(l=Kr(u.tag,f,u.key,u.mode),l.elementType=u.elementType,l.type=u.type,l.stateNode=u.stateNode,l.alternate=u,u.alternate=l):(l.pendingProps=f,l.type=u.type,l.flags=0,l.subtreeFlags=0,l.deletions=null),l.flags=u.flags&14680064,l.childLanes=u.childLanes,l.lanes=u.lanes,l.child=u.child,l.memoizedProps=u.memoizedProps,l.memoizedState=u.memoizedState,l.updateQueue=u.updateQueue,f=u.dependencies,l.dependencies=f===null?null:{lanes:f.lanes,firstContext:f.firstContext},l.sibling=u.sibling,l.index=u.index,l.ref=u.ref,l}function M3(u,f,l,r,n,i){var y=2;if(r=u,typeof u==="function")_5(u)&&(y=1);else if(typeof u==="string")y=5;else u:switch(u){case ri:return i1(l.children,n,i,f);case T2:y=8,n|=8;break;case H4:return u=Kr(12,l,f,n|2),u.elementType=H4,u.lanes=i,u;case B4:return u=Kr(13,l,f,n),u.elementType=B4,u.lanes=i,u;case V4:return u=Kr(19,l,f,n),u.elementType=V4,u.lanes=i,u;case oj:return Lt(l,n,i,f);default:if(typeof u==="object"&&u!==null)switch(u.$$typeof){case sj:y=10;break u;case aj:y=9;break u;case E2:y=11;break u;case Z2:y=14;break u;case a0:y=16,r=null;break u}throw Error(Uu(130,u==null?u:typeof u,""))}return f=Kr(y,l,f,n),f.elementType=u,f.type=r,f.lanes=i,f}function i1(u,f,l,r){return u=Kr(7,u,r,f),u.lanes=l,u}function Lt(u,f,l,r){return u=Kr(22,u,r,f),u.elementType=oj,u.lanes=l,u.stateNode={isHidden:!1},u}function E4(u,f,l){return u=Kr(6,u,null,f),u.lanes=l,u}function Z4(u,f,l){return f=Kr(4,u.children!==null?u.children:[],u.key,f),f.lanes=l,f.stateNode={containerInfo:u.containerInfo,pendingChildren:null,implementation:u.implementation},f}function Yz(u,f,l,r,n){this.tag=f,this.containerInfo=u,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=c4(0),this.expirationTimes=c4(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=c4(0),this.identifierPrefix=r,this.onRecoverableError=n,this.mutableSourceEagerHydrationData=null}function $5(u,f,l,r,n,i,y,_,$){return u=new Yz(u,f,l,_,$),f===1?(f=1,i===!0&&(f|=8)):f=0,i=Kr(3,null,null,f),u.current=i,i.stateNode=u,i.memoizedState={element:r,isDehydrated:l,cache:null,transitions:null,pendingSuspenseBoundaries:null},v2(i),u}function Sz(u,f,l){var r=3{function kJ(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=="function")return;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(kJ)}catch(u){console.error(u)}}kJ(),IJ.exports=vJ()});var sJ=nr((F5)=>{var gJ=j5();F5.createRoot=gJ.createRoot,F5.hydrateRoot=gJ.hydrateRoot;var Cz});var gQ=nr((y6)=>{var rO=qf(),nO=Symbol.for("react.element"),iO=Symbol.for("react.fragment"),yO=Object.prototype.hasOwnProperty,_O=rO.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,$O={key:!0,ref:!0,__self:!0,__source:!0};function IQ(u,f,l){var r,n={},i=null,y=null;l!==void 0&&(i=""+l),f.key!==void 0&&(i=""+f.key),f.ref!==void 0&&(y=f.ref);for(r in f)yO.call(f,r)&&!$O.hasOwnProperty(r)&&(n[r]=f[r]);if(u&&u.defaultProps)for(r in f=u.defaultProps,f)n[r]===void 0&&(n[r]=f[r]);return{$$typeof:nO,type:u,key:i,ref:y,props:n,_owner:_O.current}}y6.Fragment=iO;y6.jsx=IQ;y6.jsxs=IQ});var aQ=nr((om,sQ)=>{sQ.exports=gQ()});var ZN=nr((EN)=>{var $y=qf();function TV(u,f){return u===f&&(u!==0||1/u===1/f)||u!==u&&f!==f}var EV=typeof Object.is==="function"?Object.is:TV,ZV=$y.useState,OV=$y.useEffect,HV=$y.useLayoutEffect,BV=$y.useDebugValue;function VV(u,f){var l=f(),r=ZV({inst:{value:l,getSnapshot:f}}),n=r[0].inst,i=r[1];return HV(function(){n.value=l,n.getSnapshot=f,i9(n)&&i({inst:n})},[u,l,f]),OV(function(){return i9(n)&&i({inst:n}),u(function(){i9(n)&&i({inst:n})})},[u]),BV(l),l}function i9(u){var f=u.getSnapshot;u=u.value;try{var l=f();return!EV(u,l)}catch(r){return!0}}function DV(u,f){return f()}var XV=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?DV:VV;EN.useSyncExternalStore=$y.useSyncExternalStore!==void 0?$y.useSyncExternalStore:XV});var HN=nr((bh,ON)=>{ON.exports=ZN()});var VN=nr((BN)=>{var e6=qf(),YV=HN();function SV(u,f){return u===f&&(u!==0||1/u===1/f)||u!==u&&f!==f}var pV=typeof Object.is==="function"?Object.is:SV,mV=YV.useSyncExternalStore,PV=e6.useRef,MV=e6.useEffect,CV=e6.useMemo,RV=e6.useDebugValue;BN.useSyncExternalStoreWithSelector=function(u,f,l,r,n){var i=PV(null);if(i.current===null){var y={hasValue:!1,value:null};i.current=y}else y=i.current;i=CV(function(){function $(U){if(!A){if(A=!0,c=U,U=r(U),n!==void 0&&y.hasValue){var Q=y.value;if(n(Q,U))return j=Q}return j=U}if(Q=j,pV(c,U))return Q;var L=r(U);if(n!==void 0&&n(Q,L))return c=U,Q;return c=U,j=L}var A=!1,c,j,F=l===void 0?null:l;return[function(){return $(f())},F===null?void 0:function(){return $(F())}]},[f,l,r,n]);var _=mV(u,i[0],i[1]);return MV(function(){y.hasValue=!0,y.value=_},[_]),RV(_),_}});var XN=nr((kh,DN)=>{DN.exports=VN()});var bn=Pu(qf(),1);var y3="北京时间";var SK={timeZone:"Asia/Shanghai",hour12:!1},pK={timeZone:"Asia/Shanghai",hour12:!1},mK=new Intl.DateTimeFormat("en-CA",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23"});function s8(u){if(u===null||u===void 0||u==="")return null;let f=u instanceof Date?u:new Date(u);return Number.isNaN(f.getTime())?null:f}function D7(u){let f=s8(u);if(!f)return null;return mK.formatToParts(f).reduce((l,r)=>{if(r.type!=="literal")l[r.type]=r.value;return l},{})}function Nu(u){let f=s8(u);return f?f.toLocaleString("zh-CN",SK):"--"}function tf(u){let f=s8(u);return f?f.toLocaleTimeString("zh-CN",pK):"--"}function a8(u){let f=D7(u);if(!f)return"";let l=f.hour==="24"?"00":f.hour;return`${f.year}-${f.month}-${f.day}T${l}:${f.minute}`}function X7(u=new Date){let f=D7(u);if(!f)return"";return`${f.year}-${f.month}-${f.day}`}function Y7(u){if(!u)return null;let f=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(u);if(!f)return null;let[,l,r,n,i,y,_="00"]=f,$=Date.UTC(Number(l),Number(r)-1,Number(n),Number(i)-8,Number(y),Number(_)),A=new Date($),c=a8(A);return Number.isNaN(A.getTime())||c!==`${l}-${r}-${n}T${i}:${y}`?null:A.toISOString()}var rw=Pu(sJ(),1);var Zt=Pu(qf(),1);var aJ=Pu(qf(),1),G_=aJ.default.createElement;function Rz({active:u=!0,label:f="正在加载"}){if(!u)return null;return G_("span",{className:"loading-spinner-indicator",role:"status","aria-label":f,title:f,"data-testid":"loading-title-indicator"},G_("span",{className:"loading-spinner-ring","aria-hidden":!0}))}function nf({title:u,children:f,loading:l,level:r=2,className:n="",label:i="正在加载"}){return G_(r===3?"h3":"h2",{className:`loading-title ${l?"is-loading":""} ${n}`.trim()},G_("span",{className:"loading-title-text"},f??u),G_(Rz,{active:Boolean(l),label:i}))}class Hi extends Error{unideskRequestError=!0;meta;constructor(u,f){super(u);this.name="UniDeskRequestError",this.meta=f}}function xz(u){return new Promise((f)=>setTimeout(f,u))}function E_(u,f="操作失败"){return u instanceof Error?u.message:String(u||f)}function Tt(u,f=500){if(u===null||u===void 0)return"";let l=typeof u==="string"?u:JSON.stringify(u),r=String(l||"").replace(/\s+/gu," ").trim();return r.length>f?`${r.slice(0,f)}...`:r}function hz(u){try{let f=typeof location<"u"&&location.origin?location.origin:"http://localhost";return new URL(u,f).toString()}catch{return u}}function oJ(u){return String(u.method||"GET").toUpperCase()}function bz(u){if(u===null||u===void 0)return!1;if(typeof u!=="object")return!1;if(typeof Blob<"u"&&u instanceof Blob)return!1;if(typeof FormData<"u"&&u instanceof FormData)return!1;if(typeof URLSearchParams<"u"&&u instanceof URLSearchParams)return!1;if(typeof ArrayBuffer<"u"&&u instanceof ArrayBuffer)return!1;return!0}function dJ(u){let f=new Headers(u.headers||{}),l=bz(u.body)?JSON.stringify(u.body):u.body;if(l&&!f.has("content-type")&&typeof l==="string")f.set("content-type","application/json");return{...u,credentials:u.credentials||"same-origin",body:l,headers:f}}function eJ(u){if(u?.error&&typeof u.error==="object"&&typeof u.error.message==="string")return u.error.message;if(typeof u?.error==="string")return u.error;if(typeof u?.message==="string")return u.message;if(typeof u?.detail==="string")return u.detail;return""}function vz(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return!1;return f.some((l)=>l!==!1&&u[l]===!1)}function z_(u,f,l,r,n={}){return{kind:u,method:l,url:hz(f),occurredAt:r.toISOString(),...n}}function T_(u,f){if(!u)return"请求失败";return`HTTP ${u}${f?` ${f}`:""}`}function uU(u){try{return{body:u?JSON.parse(u):null,parseError:""}}catch(f){return{body:{text:u},parseError:E_(f,"parse failed")}}}async function Eu(u,f={},l=0){let{failureFields:r=["ok"],strictJson:n=!1,retryInvalidJson:i=0,retryDelayMs:y=120,invalidJsonPrefix:_="服务返回了无效 JSON",invalidJsonPreview:$=!1,responsePreviewLength:A=500,...c}=f,j=oJ(c),F=new Date,U;try{U=await fetch(u,dJ(c))}catch(w){let J=E_(w,"网络请求失败");throw new Hi(J,z_("network",u,j,F,{upstreamMessage:J}))}let Q=await U.text(),L=uU(Q);if(L.parseError){if(n&&j==="GET"&&l=300)?T_(u.meta.status,u.meta.statusText):"应用请求失败",i=u.meta.status?T_(u.meta.status):"",y=($)=>!$||$===n||$===i,_=!y(u.message)?u.message:y(u.meta.upstreamMessage)?"":u.meta.upstreamMessage||"";return{title:n,message:_,status:u.meta.status,statusText:u.meta.statusText,method:u.meta.method,url:u.meta.url,occurredAt:kz(u.meta.occurredAt),responsePreview:u.meta.responsePreview,parseError:u.meta.parseError,structured:!0}}let r=E_(u,f).split(/\r?\n/u);return{title:r[0]||f,message:r.slice(1).join(` -`),structured:r.length>1}}function Iz(u,f="操作失败"){let l=J5(u,f),r=[l.title];if(l.message)r.push(`原因: ${l.message}`);if(l.method||l.url)r.push(`请求: ${[l.method,l.url].filter(Boolean).join(" ")}`);if(l.status)r.push(`状态: ${T_(l.status,l.statusText)}`);if(l.occurredAt)r.push(`时间: ${l.occurredAt}`);if(l.parseError)r.push(`解析错误: ${l.parseError}`);if(l.responsePreview&&l.responsePreview!==l.message)r.push(`响应预览: ${l.responsePreview}`);return r.filter(Boolean).join(` -`)}function Hu(u,f="操作失败"){return lU(u)?Iz(u,f):E_(u,f)}var rU=Pu(qf(),1);var Qn=rU.default.createElement;function Z_(u,f){return f?[Qn("dt",{key:`${u}-label`},u),Qn("dd",{key:u},f)]:null}function yf({error:u,wide:f=!1,fallback:l="操作失败",className:r=""}){if(!u)return null;let n=J5(u,l),i=[Z_("请求",[n.method,n.url].filter(Boolean).join(" ")),Z_("状态",n.status?`HTTP ${n.status}${n.statusText?` ${n.statusText}`:""}`:""),Z_("时间",n.occurredAt),Z_("解析错误",n.parseError),Z_("响应预览",n.responsePreview)].filter(Boolean);return Qn("div",{className:`form-error unidesk-error${f?" wide":""}${r?` ${r}`:""}`,role:"alert","data-testid":"unidesk-error"},Qn("div",{className:"unidesk-error-title"},Qn("strong",null,n.title),n.status?Qn("span",{className:"unidesk-error-code"},`HTTP ${n.status}`):null),n.message?Qn("pre",{className:"unidesk-error-message"},n.message):null,i.length>0?Qn("dl",{className:"unidesk-error-details"},i):null)}var r0=Pu(qf(),1),nU=r0.default.createContext(null);function iU({children:u}){let[f,l]=r0.default.useState([]),[r,n]=r0.default.useState(Date.now()),i=r0.default.useCallback((j,F)=>{let Q={id:`notif_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:j,message:F,timestamp:Date.now()};l((L)=>{let w=[...L,Q];if(w.length>50)return w.slice(-50);return w})},[]),y=r0.default.useCallback((j)=>{l((F)=>F.filter((U)=>U.id!==j))},[]),_=r0.default.useCallback(()=>{l([]),n(Date.now())},[]),$=r0.default.useMemo(()=>{return f.filter((j)=>j.timestamp>r).length},[f,r]),A=$>0,c={notifications:f,addNotification:i,removeNotification:y,clearNotifications:_,unreadCount:$,hasUnread:A};return gz(nU.Provider,{value:c},u)}var gz=r0.default.createElement;function Vl(){let u=r0.default.useContext(nU);if(!u)throw Error("useNotification must be used within NotificationProvider");return u}var R=Zt.default.createElement,{useEffect:Et}=Zt.default,Bi=Zt.default.useState;function wl(u,f={}){return Eu(u,{failureFields:["ok","success"],...f})}function Dl(u,f){return`${u}/microservices/baidu-netdisk/proxy${f}`}function sz(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}function qn(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=["B","KB","MB","GB","TB"],r=f,n=0;while(r>=1024&&n{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function Di({title:u,text:f}){return R("div",{className:"empty-state"},R("strong",null,u),R("span",null,f))}function Xi({title:u,text:f,href:l,badge:r,testId:n}){return R("a",{className:"doc-link-card",href:l,target:"_blank",rel:"noreferrer","data-testid":n},R("span",null,r||"DOC"),R("strong",null,u),R("p",null,f),R("code",null,l))}function az(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function oz(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function dz(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function ez(u){return Array.isArray(u?.files)?u.files:[]}function uT(u){return Array.isArray(u?.jobs)?u.jobs:[]}function fT(u,f){if(!u||u===f)return f;let l=u.replace(/\/+$/u,""),r=l.slice(0,l.lastIndexOf("/"))||f;return r.lengthx.id==="baidu-netdisk")||null,[n,i]=Bi({loading:!1,actionLoading:!1,error:"",message:"",health:null,account:null,files:null,transfers:null,logs:null,selfTest:null,refreshedAt:null}),[y,_]=Bi("/"),[$,A]=Bi(null),[c,j]=Bi(""),[F,U]=Bi({localPath:"sample.txt",remotePath:"/sample.txt"}),[Q,L]=Bi({fsId:"",localPath:"downloads/"}),{addNotification:w}=Vl(),J=n.health?.baidu?.appRoot||n.account?.rootPath||"/";Et(()=>{U((x)=>{let fu=new Set(["/sample.txt","/apps/UniDeskBaiduNetdisk/sample.txt"]);if(x.remotePath&&!fu.has(x.remotePath))return x;let $u=U5(J,"sample.txt");return x.remotePath===$u?x:{...x,remotePath:$u}})},[J]);async function N(x=y){let $u=await wl(Dl(l,`/api/files?dir=${encodeURIComponent(x||J)}&limit=100`));i((tu)=>({...tu,files:$u}))}async function q(){let x=await wl(Dl(l,"/api/transfers?limit=80"));i((fu)=>({...fu,transfers:x}))}async function W(){if(!r)return;i((x)=>({...x,loading:!0,error:"",message:""}));try{let x=await wl(`${l}/microservices/baidu-netdisk/health`),fu=x?.baidu?.appRoot||J,$u=null,tu=null;if(x?.auth?.loggedIn){$u=await wl(Dl(l,"/api/account?refresh=1"));let qu=y&&y.startsWith(fu)?y:fu;_(qu),tu=await wl(Dl(l,`/api/files?dir=${encodeURIComponent(qu)}&limit=100`))}else _(fu);let ju=await wl(Dl(l,"/api/transfers?limit=80")),Gu=await wl(Dl(l,"/logs?limit=60"));i((qu)=>({...qu,loading:!1,health:x,account:$u?.account||null,files:tu,transfers:ju,logs:Gu,refreshedAt:new Date}))}catch(x){i((fu)=>({...fu,loading:!1,error:Hu(x,"百度网盘服务加载失败")}))}}async function z(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{let x=await wl(Dl(l,"/api/auth/device/start"),{method:"POST",body:{}});A(x.session||null),i((fu)=>({...fu,actionLoading:!1,message:"设备码已生成,请扫码授权"}))}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Hu(x,"创建设备码失败")}))}}async function Z(x=!1){if(!$?.id)return;if(x)i((fu)=>({...fu,actionLoading:!0,error:""}));try{let fu=await wl(Dl(l,`/api/auth/device/status?sessionId=${encodeURIComponent($.id)}`));if(A(fu.session||null),fu.session?.status==="succeeded")i(($u)=>({...$u,actionLoading:!1,message:"授权成功,正在刷新账号与文件列表"})),await W();else if(x)i(($u)=>({...$u,actionLoading:!1}))}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"轮询登录状态失败")}))}}async function H(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/auth/logout"),{method:"POST",body:{}}),A(null),i((x)=>({...x,actionLoading:!1,account:null,files:null,message:"本地 token 已清除"})),await W()}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Hu(x,"退出登录失败")}))}}async function E(x){x.preventDefault();let fu=c.trim();if(!fu)return;i(($u)=>({...$u,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/folders"),{method:"POST",body:{path:U5(y,fu)}}),j(""),i(($u)=>({...$u,actionLoading:!1,message:"文件夹已创建"})),await N(y)}catch($u){i((tu)=>({...tu,actionLoading:!1,error:Hu($u,"创建文件夹失败")}))}}async function D(x){if(!x)return;i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/files/manage"),{method:"POST",body:{opera:"delete",filelist:[{path:x}],async:1}}),i((fu)=>({...fu,actionLoading:!1,message:"删除任务已提交"})),await N(y)}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"删除失败")}))}}async function h(x){x.preventDefault(),i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/transfers/upload-from-path"),{method:"POST",body:F}),i((fu)=>({...fu,actionLoading:!1,message:"上传任务已入队"})),await q()}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"上传任务创建失败")}))}}async function V(x){x.preventDefault(),i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/transfers/download-to-path"),{method:"POST",body:Q}),i((fu)=>({...fu,actionLoading:!1,message:"下载任务已入队"})),await q()}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"下载任务创建失败")}))}}async function Y(x,fu){i(($u)=>({...$u,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,`/api/transfers/${encodeURIComponent(x)}/${fu}`),{method:"POST",body:{}}),i(($u)=>({...$u,actionLoading:!1,message:fu==="cancel"?"已请求取消任务":"任务已重新入队"})),await q()}catch($u){i((tu)=>({...tu,actionLoading:!1,error:Hu($u,"任务操作失败")}))}}async function p(){i((x)=>({...x,actionLoading:!0,error:"",message:"正在运行上传/下载自测..."}));try{let x=await wl(Dl(l,"/api/self-test"),{method:"POST",body:{}});i((fu)=>({...fu,actionLoading:!1,selfTest:x,message:`上传/下载自测通过:${x.remotePath||""}`})),await N(y),await q()}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Hu(x,"上传/下载自测失败")}))}}if(Et(()=>{if(!r)return;W();return},[r?.id,r?.runtime?.providerStatus]),Et(()=>{if(!$?.id||$.status!=="pending")return;let x=window.setInterval(()=>void Z(!1),Math.max(5000,Number($.pollIntervalSeconds||5)*1000));return()=>window.clearInterval(x)},[$?.id,$?.status,$?.pollIntervalSeconds]),Et(()=>{if(!r)return;let x=window.setInterval(()=>void q(),5000);return()=>window.clearInterval(x)},[r?.id]),!r)return R(Di,{title:"Baidu Netdisk 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=baidu-netdisk"});let O=az(r),m=dz(r),X=oz(r),v=n.health||{},T=n.account||v.auth?.account||null,S=v.auth||{},k=ez(n.files),I=uT(n.transfers),b=T?.quota||{},o=Boolean(S.loggedIn||T),s=Boolean(S.configured);return R("div",{className:"baidu-netdisk-page","data-testid":"baidu-netdisk-page"},R(J1,{title:"Baidu Netdisk 工作台",eyebrow:"Containerized Storage Gateway",loading:n.loading,actions:R("div",{className:"panel-actions"},R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-env-setup.md",target:"_blank",rel:"noreferrer","data-testid":"baidu-netdisk-config-doc-link"},"配置文档"),R("button",{type:"button",className:"ghost-btn",onClick:W,disabled:n.loading,"data-testid":"baidu-netdisk-refresh"},n.loading?"刷新中":"刷新"),R(H0,{title:"Baidu Netdisk 用户服务",data:r,onOpen:f,testId:"raw-baidu-netdisk-service"}))},R("div",{className:"baidu-netdisk-hero"},R("div",null,R("div",{className:"node-version-line"},R(F1,{status:O.providerStatus==="online"?"online":"warn"},O.providerStatus||"unknown"),R("span",null,r.providerId),R(F1,{status:X.public?"warn":"private"},X.public?"公网暴露":"仅 UniDesk frontend 代理访问")),R("p",{className:"muted paragraph"},r.description)),R("div",{className:"microservice-ref-card"},R("span",null,"Repo"),R("strong",null,m.url||"--"),R("code",null,m.commitId||"--")),R("div",{className:"microservice-ref-card"},R("span",null,"Private Backend"),R("strong",null,`${X.nodeBindHost||"--"}:${X.nodePort||"--"}`),R("code",null,`${m.composeFile||"--"} / ${m.composeService||"--"}`))),R(yf,{error:n.error,wide:!0})),R("div",{className:"metric-grid"},R(Vi,{label:"Health",value:v.ok?"OK":"--",hint:v.storage?.postgres||"postgres",tone:v.ok?"ok":"warn"}),R(Vi,{label:"OAuth",value:s?"已配置":"待配置",hint:s?"client + secret + token key":"需要设置 UNIDESK_BAIDU_NETDISK_*",tone:s?"ok":"warn"}),R(Vi,{label:"Login",value:o?"已登录":"未登录",hint:T?.username||"Device Code QR",tone:o?"ok":"warn"}),R(Vi,{label:"Work Root",value:lT(J),hint:J}),R(Vi,{label:"Quota",value:qn(b.used),hint:b.total?`${b.usedPercent||0}% / ${qn(b.total)}`:"授权后刷新"}),R(Vi,{label:"Transfers",value:sz(I.length),hint:`running ${n.transfers?.counts?.running||0} / failed ${n.transfers?.counts?.failed||0}`})),R(J1,{title:"文件浏览器",eyebrow:y,className:"baidu-files-panel",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"ghost-btn",onClick:()=>{let x=fT(y,J);_(x),N(x)},disabled:!o||y===J},"上级"),R("button",{type:"button",className:"ghost-btn",onClick:()=>N(y),disabled:!o},"刷新文件"),R(H0,{title:"Baidu Files",data:n.files,onOpen:f,testId:"raw-baidu-files"}))},R("form",{className:"baidu-pathbar",onSubmit:(x)=>{x.preventDefault(),N(y)}},R("input",{value:y,onChange:(x)=>_(x.target.value),disabled:!o}),R("button",{type:"submit",className:"ghost-btn",disabled:!o},"打开路径")),R("form",{className:"baidu-pathbar",onSubmit:E},R("input",{value:c,onChange:(x)=>j(x.target.value),placeholder:"新文件夹名称",disabled:!o}),R("button",{type:"submit",className:"primary-btn",disabled:!o||!c.trim()},"新建文件夹")),!o?R(Di,{title:"等待授权",text:"登录后通过 /api/files 读取工作目录文件列表"}):k.length===0?R(Di,{title:"目录为空",text:"可以从 staging 目录上传文件或新建文件夹"}):R("div",{className:"table-wrap","data-testid":"baidu-netdisk-file-table"},R("table",null,R("thead",null,R("tr",null,R("th",null,"名称"),R("th",null,"类型"),R("th",null,"大小"),R("th",null,"修改时间"),R("th",null,"fs_id"),R("th",null,"操作"))),R("tbody",null,k.map((x)=>R("tr",{key:x.fsId||x.path},R("td",null,R("strong",null,x.serverFilename||x.path),R("code",null,x.path||"--")),R("td",null,R(F1,{status:x.isDir?"queued":"private"},x.isDir?"DIR":"FILE")),R("td",null,x.isDir?"--":qn(x.size)),R("td",null,x.serverMtime?Nu(x.serverMtime*1000):"--"),R("td",null,R("code",null,x.fsId||"--")),R("td",null,R("div",{className:"inline-actions"},x.isDir?R("button",{type:"button",className:"ghost-btn",onClick:()=>{_(x.path),N(x.path)}},"打开"):R("button",{type:"button",className:"ghost-btn",onClick:()=>L((fu)=>({...fu,fsId:x.fsId}))},"填入下载"),R("button",{type:"button",className:"ghost-btn",onClick:()=>D(x.path),disabled:n.actionLoading},"删除"))))))))),R("div",{className:"baidu-netdisk-grid"},R(J1,{title:"配置与文档",eyebrow:"Deployment References",className:"baidu-docs-panel",actions:R("div",{className:"panel-actions inline-actions"},R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-env-setup.md",target:"_blank",rel:"noreferrer"},"打开环境配置"),R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-user-service.md",target:"_blank",rel:"noreferrer"},"打开服务方案"))},R("p",{className:"muted paragraph"},s?"OAuth 运行时变量已配置;如需轮换密钥、迁移部署或排查代理边界,可直接打开下面的项目内文档。":"首次使用请先按环境变量配置文档填入百度应用 client id / secret,然后重建 baidu-netdisk 服务并刷新本页。"),R("div",{className:"baidu-doc-grid","data-testid":"baidu-netdisk-doc-links"},R(Xi,{title:"环境变量配置",text:"填写 UNIDESK_BAIDU_NETDISK_CLIENT_ID、CLIENT_SECRET、TOKEN_KEY,并执行重建与健康检查。",href:"/docs/issue/baidu-netdisk-env-setup.md",badge:"SETUP",testId:"baidu-netdisk-env-doc-card"}),R(Xi,{title:"服务方案与 API",text:"说明 OAuth Device Code、根目录工作区、staging 上传下载任务和后端 API 设计。",href:"/docs/issue/baidu-netdisk-user-service.md",badge:"DESIGN"}),R(Xi,{title:"用户服务安全边界",text:"查看 UniDesk microservice 私有代理、允许路径、frontendOnly 和密钥边界规则。",href:"/docs/reference/microservices.md",badge:"REF"}),R(Xi,{title:"部署与重建流程",text:"查看 server rebuild、Compose 编排、健康检查和交付验证的长期规则。",href:"/docs/reference/deployment.md",badge:"DEPLOY"}),R(Xi,{title:"CLI 验证命令",text:"查看 microservice health/proxy、server rebuild、job status 等命令入口。",href:"/docs/reference/cli.md",badge:"CLI"}),R(Xi,{title:"百度设备码模式",text:"打开百度官方 OAuth Device Code 文档,对照扫码登录和轮询参数。",href:"https://pan.baidu.com/union/doc/fl1x114ti",badge:"OFFICIAL"}))),R(J1,{title:"设备码登录",eyebrow:"OAuth Device Code",className:"baidu-login-panel",loading:n.actionLoading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"primary-btn",onClick:z,disabled:n.actionLoading||!s,"data-testid":"baidu-netdisk-start-login"},"生成二维码"),$?.id?R("button",{type:"button",className:"ghost-btn",onClick:()=>Z(!0),disabled:n.actionLoading},"检查状态"):null,o?R("button",{type:"button",className:"ghost-btn",onClick:H,disabled:n.actionLoading},"清除本地登录"):null,R(H0,{title:"Baidu Device Session",data:$||S.latestSession,onOpen:f,testId:"raw-baidu-device-session"}))},R("div",{className:"baidu-login-card","data-testid":"baidu-netdisk-login-card"},R("div",{className:"baidu-qr-frame"},$?.qrcodeUrl?R("img",{src:$.qrcodeUrl,alt:"百度网盘设备码授权二维码","data-testid":"baidu-netdisk-qrcode"}):R(Di,{title:s?"等待二维码":"OAuth 未配置",text:s?"点击生成二维码后使用百度网盘或百度 App 扫码":"设置 client id、secret 和 token key 后重建服务"})),R("div",{className:"claudeqq-login-copy"},R("div",{className:"node-version-line"},R(F1,{status:o?"online":$?.status==="pending"?"warn":"unknown"},o?"已登录":$?.status||"未开始"),R("span",null,$?.secondsRemaining!==void 0?`${$.secondsRemaining}s`:"--"),R("span",null,"scope basic,netdisk")),R("p",{className:"muted paragraph"},o?"access token / refresh token 已加密保存到 PostgreSQL;前端只看到脱敏登录态。":"后端使用百度 OAuth Device Code 轮询换取 token;二维码过期后重新生成即可。"),R("div",{className:"microservice-ref-card"},R("span",null,"User Code"),R("strong",null,$?.userCode||"--"),R("code",null,$?.verificationUrl||"https://openapi.baidu.com/device")),R("div",{className:"microservice-ref-card"},R("span",null,"Expires"),R("strong",null,$?.expiresAt?Nu($.expiresAt):"--"),R("code",null,$?.error||"no token exposed"))))),R(J1,{title:"账号与容量",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Account",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(H0,{title:"Baidu Account",data:T,onOpen:f,testId:"raw-baidu-account"}))},T?R("div",{className:"baidu-account-card"},R("div",{className:"node-version-line"},R(F1,{status:"online"},"connected"),R("span",null,T.baiduUid||"--"),R("span",null,`VIP ${T.vipType??"--"}`)),R("h3",null,T.username||"Baidu Netdisk"),R("p",{className:"muted paragraph"},`工作目录固定在 ${T.rootPath||J};v1 上传/下载只读写容器 staging 目录,不把大文件字节流穿过 UniDesk proxy。`),R("div",{className:"quota-bar"},R("span",{style:{width:`${Math.max(0,Math.min(100,Number(b.usedPercent||0)))}%`}})),R("div",{className:"microservice-ref-card"},R("span",null,"Quota"),R("strong",null,`${qn(b.used)} / ${qn(b.total)}`),R("code",null,`${b.usedPercent||0}% used`))):R(Di,{title:"尚未登录",text:"扫码授权后这里会显示账号、UID、会员状态和容量"})),R(J1,{title:"传输任务",eyebrow:"staging path jobs",className:"baidu-transfers-panel",loading:n.actionLoading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"primary-btn",onClick:p,disabled:!o||n.actionLoading,"data-testid":"baidu-netdisk-self-test"},"运行自测"),R("button",{type:"button",className:"ghost-btn",onClick:q},"刷新任务"),R(H0,{title:"Baidu Transfers",data:n.transfers,onOpen:f,testId:"raw-baidu-transfers"}))},R("div",{className:"baidu-transfer-forms"},R("form",{className:"stack-form",onSubmit:h,"data-testid":"baidu-upload-form"},R("label",null,"容器 staging 文件",R("input",{value:F.localPath,onChange:(x)=>U((fu)=>({...fu,localPath:x.target.value})),placeholder:"sample.txt"})),R("label",null,"百度网盘目标路径",R("input",{value:F.remotePath,onChange:(x)=>U((fu)=>({...fu,remotePath:x.target.value})),placeholder:U5(J,"sample.txt")})),R("button",{type:"submit",className:"primary-btn",disabled:!o||n.actionLoading},"上传 staging 文件")),R("form",{className:"stack-form",onSubmit:V,"data-testid":"baidu-download-form"},R("label",null,"文件 fs_id",R("input",{value:Q.fsId,onChange:(x)=>L((fu)=>({...fu,fsId:x.target.value})),placeholder:"从文件表填入"})),R("label",null,"保存到 staging 路径",R("input",{value:Q.localPath,onChange:(x)=>L((fu)=>({...fu,localPath:x.target.value})),placeholder:"downloads/"})),R("button",{type:"submit",className:"primary-btn",disabled:!o||!Q.fsId||n.actionLoading},"下载到 staging"))),n.selfTest?R("div",{className:"baidu-account-card","data-testid":"baidu-netdisk-self-test-result"},R("div",{className:"node-version-line"},R(F1,{status:n.selfTest.ok?"online":"warn"},n.selfTest.ok?"self-test ok":"self-test"),R("span",null,qn(n.selfTest.sizeBytes))),R("h3",null,n.selfTest.remotePath||"Baidu self-test"),R("div",{className:"microservice-ref-card"},R("span",null,"fs_id"),R("strong",null,n.selfTest.fsId||"--"),R("code",null,n.selfTest.downloadedPath||"--")),R("div",{className:"microservice-ref-card"},R("span",null,"MD5"),R("strong",null,n.selfTest.downloadedMd5||"--"),R("code",null,n.selfTest.expectedMd5||"--")),R(H0,{title:"Baidu Self Test",data:n.selfTest,onOpen:f,testId:"raw-baidu-self-test"})):null,I.length===0?R(Di,{title:"暂无传输任务",text:"上传/下载任务会在后端容器内执行,避免大文件穿过 UniDesk proxy"}):R("div",{className:"table-wrap","data-testid":"baidu-transfer-table"},R("table",null,R("thead",null,R("tr",null,R("th",null,"状态"),R("th",null,"方向"),R("th",null,"路径"),R("th",null,"进度"),R("th",null,"时间"),R("th",null,"操作"))),R("tbody",null,I.map((x)=>R("tr",{key:x.id},R("td",null,R(F1,{status:x.status},x.status)),R("td",null,x.direction),R("td",null,R("strong",null,x.remotePath||x.fsId||"--"),R("code",null,x.localPath||"--"),x.error?R("span",{className:"form-error"},x.error):null),R("td",null,R(rT,{percent:x.progressPercent}),R("span",{className:"muted"},`${qn(x.bytesDone)} / ${qn(x.sizeBytes)}`)),R("td",null,Nu(x.updatedAt)),R("td",null,R("div",{className:"inline-actions"},["queued","running"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>Y(x.id,"cancel")},"取消"):null,["failed","canceled"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>Y(x.id,"retry")},"重试"):null,R(H0,{title:`Transfer ${x.id}`,data:x,onOpen:f}))))))))),R(J1,{title:"安全与日志",eyebrow:"redacted diagnostics",className:"baidu-wide-panel",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(H0,{title:"Baidu Health",data:v,onOpen:f,testId:"raw-baidu-health"}),R(H0,{title:"Baidu Logs",data:n.logs,onOpen:f,testId:"raw-baidu-logs"}))},R("div",{className:"policy-grid"},R("article",null,R("b",null,"私有后端"),R("span",null,"4244 只在 Compose 网络 expose,浏览器经 UniDesk 同源代理访问")),R("article",null,R("b",null,"Token 加密"),R("span",null,"access/refresh token 使用 BAIDU_NETDISK_TOKEN_KEY 加密后写入 PostgreSQL")),R("article",null,R("b",null,"无浏览器大文件流"),R("span",null,"上传/下载以容器 staging 目录为边界,避免 proxy 文本通道传输大字节流"))))))}var Bt=Pu(qf(),1);var a=Bt.default.createElement,{useEffect:nT}=Bt.default,Ot=Bt.default.useState,U1={label:"主用户私聊账号",userId:645275593};function Q5(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}async function Nn(u,f={}){return Eu(u,{failureFields:["ok","success"],...f})}async function iT(u){let f=await fetch(u,{credentials:"same-origin"}),l=await f.text();try{return l?JSON.parse(l):{ok:f.ok,status:f.status}}catch{return{ok:f.ok,status:f.status,text:l}}}function Ht({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return a("span",{className:`status-badge ${l}`},f||u||"unknown")}function Yi({label:u,value:f,hint:l,tone:r}){return a("article",{className:`metric-card ${r||""}`},a("div",{className:"metric-label"},u),a("div",{className:"metric-value"},f),a("div",{className:"metric-hint"},l))}function Si({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return a("section",{className:`panel ${n||""}`},a("div",{className:"panel-head"},a("div",null,f?a("p",{className:"panel-eyebrow"},f):null,a(nf,{title:u,loading:i})),l?a("div",{className:"panel-actions"},l):null),a("div",{className:"panel-body"},r))}function O_({title:u,data:f,onOpen:l,testId:r}){return a("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function H_({title:u,text:f}){return a("div",{className:"empty-state"},a("strong",null,u),a("span",null,f))}function yT(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function _T(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function $T(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Wn(u,f){return`${u}/microservices/claudeqq/proxy${f}`}function tT(u){return Array.isArray(u?.events)?u.events.slice(0,80):[]}function AT(u){return Array.isArray(u?.subscriptions)?u.subscriptions.slice(0,50):[]}function cT(u){return Array.isArray(u?.messages)?u.messages.slice(0,30):[]}function _U(u){let f=u?.text??u?.message??u?.raw?.raw_message;if(typeof f!=="string")return"--";return f.length>180?`${f.slice(0,177)}...`:f}function $U(u){let f=u?.groupId??u?.group_id??(u?.message_type==="group"?u?.target_id:void 0),l=u?.userId??u?.user_id??(u?.message_type==="private"?u?.target_id:void 0);if(f)return`群 ${f}`;if(l)return`私聊 ${l}`;return"--"}function tU({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((T)=>T.id==="claudeqq")||null,[n,i]=Ot({loading:!1,qrLoading:!1,error:"",health:null,status:null,napcatLogin:null,napcatQrcode:null,qrcodeFetched:!1,qrcodeRefreshedAt:null,events:null,subscriptions:null,sent:null,refreshedAt:null}),[y,_]=Ot({targetType:"private",targetId:String(U1.userId),message:""}),[$,A]=Ot({name:"unidesk-callback",targetUrl:"",eventTypes:"message",secret:""}),[c,j]=Ot(""),{addNotification:F}=Vl();async function U(){if(!r)return;i((T)=>({...T,loading:!0,error:""}));try{let[T,S,k,I,b]=await Promise.all([iT(`${l}/microservices/claudeqq/health`),Nn(Wn(l,"/api/server/status")),Nn(Wn(l,"/api/events/recent?limit=60")),Nn(Wn(l,"/api/events/subscriptions")),Nn(Wn(l,"/api/messages/sent?limit=20"))]);if(i((o)=>({...o,loading:!1,error:"",health:T,status:S,events:k,subscriptions:I,sent:b,refreshedAt:new Date})),!n.qrcodeFetched)Q(!1)}catch(T){i((S)=>({...S,loading:!1,error:Hu(T,"ClaudeQQ 加载失败")}))}}async function Q(T=!0){if(!r)return;i((S)=>({...S,qrLoading:!0,error:T?"":S.error}));try{let S=await Nn(Wn(l,"/api/napcat/login")),k=S?.napcat?.qrcode||S?.qrcode||null;i((I)=>({...I,qrLoading:!1,error:"",napcatLogin:S,napcatQrcode:k,qrcodeFetched:!0,qrcodeRefreshedAt:new Date}))}catch(S){i((k)=>({...k,qrLoading:!1,error:T||!k.napcatQrcode?Hu(S,"NapCat 二维码加载失败"):k.error}))}}async function L(T){T.preventDefault(),j("");let S=Number(y.targetId);if(!Number.isFinite(S)||S<=0||y.message.trim().length===0){i((k)=>({...k,error:"请填写 QQ 目标和消息内容"}));return}try{await Nn(Wn(l,"/api/push/text"),{method:"POST",body:JSON.stringify({userId:y.targetType==="private"?S:void 0,groupId:y.targetType==="group"?S:void 0,message:y.message})});let k="消息推送请求已提交";_((I)=>({...I,targetType:"private",targetId:String(U1.userId),message:""})),j(k),F("success",k),await U()}catch(k){i((I)=>({...I,error:Hu(k,"发送失败")}))}}async function w(T){if(T.preventDefault(),j(""),$.targetUrl.trim().length===0){i((S)=>({...S,error:"请填写订阅回调 URL"}));return}try{await Nn(Wn(l,"/api/events/subscriptions"),{method:"POST",body:JSON.stringify({name:$.name,targetUrl:$.targetUrl,eventTypes:$.eventTypes.split(",").map((k)=>k.trim()).filter(Boolean),secret:$.secret||void 0,enabled:!0})});let S="事件订阅已创建";j(S),F("success",S),await U()}catch(S){i((k)=>({...k,error:Hu(S,"订阅失败")}))}}async function J(T){if(!T)return;j("");try{await Nn(Wn(l,`/api/events/subscriptions/${encodeURIComponent(T)}`),{method:"DELETE"});let S="事件订阅已删除";j(S),F("success",S),await U()}catch(S){i((k)=>({...k,error:Hu(S,"删除订阅失败")}))}}if(nT(()=>{if(!r)return;U();return},[r?.id,r?.runtime?.providerStatus]),!r)return a(H_,{title:"ClaudeQQ 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=claudeqq"});let N=yT(r),q=$T(r),W=_T(r),z=n.health||{},Z=n.status||{},H=n.napcatLogin||{},E=z.napcat||Z.napcat||{},D={...H.napcat||{},...E,qrcode:n.napcatQrcode||{},webui:E.webui||H.napcat?.webui},h=H.login||{},V=n.napcatQrcode||{},Y=tT(n.events),p=AT(n.subscriptions),O=cT(n.sent),m=Boolean(D.httpConnected||h.ready),X=String(D.loginState||h.state||(m?"logged_in":"unknown")),v=Boolean(V.available&&V.dataUrl);return a("div",{className:"claudeqq-page","data-testid":"claudeqq-page"},a(Si,{title:"ClaudeQQ 工作台",eyebrow:"D601 QQ Event Gateway",loading:n.loading,actions:a("div",{className:"panel-actions"},a("button",{type:"button",className:"ghost-btn",onClick:U,disabled:n.loading,"data-testid":"claudeqq-refresh-button"},n.loading?"刷新中":"刷新"),a(O_,{title:"ClaudeQQ 用户服务",data:r,onOpen:f,testId:"raw-claudeqq-service"}))},a("div",{className:"findjob-hero"},a("div",null,a("div",{className:"node-version-line"},a(Ht,{status:N.providerStatus==="online"?"online":"warn"},N.providerStatus||"unknown"),a("span",null,r.providerId),a("span",null,W.public?"公网暴露":"仅 UniDesk frontend 代理访问")),a("p",{className:"muted paragraph"},r.description)),a("div",{className:"microservice-ref-card"},a("span",null,"Repo"),a("strong",null,q.url||"--"),a("code",null,q.commitId||"--")),a("div",{className:"microservice-ref-card"},a("span",null,"D601 Docker"),a("strong",null,`${W.nodeBindHost||"--"}:${W.nodePort||"--"}`),a("code",null,`${q.composeFile||"--"} / ${q.composeService||"--"}`))),a(yf,{error:n.error,wide:!0})),a("div",{className:"metric-grid"},a(Yi,{label:"Health",value:z.ok||z.status==="ok"?"OK":"--",hint:"D601 /health",tone:z.ok||z.status==="ok"?"ok":"warn"}),a(Yi,{label:"NapCat HTTP",value:D.httpConnected||D.http?.connected?"OK":"离线",hint:`${D.httpHost||z.napcat?.httpHost||"--"}:${D.httpPort||z.napcat?.httpPort||"--"}`}),a(Yi,{label:"NapCat WS",value:D.wsConnected||D.ws?.connected?"OK":"离线",hint:`${D.wsHost||z.napcat?.wsHost||"--"}:${D.wsPort||z.napcat?.wsPort||"--"}`}),a(Yi,{label:"事件缓存",value:Q5(n.events?.count??Y.length),hint:"recent QQ events"}),a(Yi,{label:"订阅",value:Q5(n.subscriptions?.count??p.length),hint:"webhook subscribers"}),a(Yi,{label:"已发送",value:Q5(n.sent?.count??O.length),hint:"sent message log"})),a("div",{className:"findjob-grid"},a(Si,{title:"NapCat 容器登录",eyebrow:"QR Login",className:"claudeqq-login-panel",loading:n.qrLoading,actions:a("div",{className:"panel-actions inline-actions"},a("button",{type:"button",className:"ghost-btn",onClick:()=>Q(!0),disabled:n.qrLoading,"data-testid":"claudeqq-napcat-refresh"},n.qrLoading?"刷新中":"手动刷新二维码"),a(O_,{title:"NapCat Login",data:n.napcatLogin,onOpen:f,testId:"raw-claudeqq-napcat-login"}))},a("div",{className:"claudeqq-login-card","data-testid":"claudeqq-napcat-login"},a("div",{className:"claudeqq-qr-frame"},v?a("img",{src:V.dataUrl,alt:"NapCat QQ 登录二维码","data-testid":"claudeqq-napcat-qrcode"}):a(H_,{title:"等待二维码",text:"NapCat 容器启动后会把登录二维码写入 cache/qrcode.png"})),a("div",{className:"claudeqq-login-copy"},a("div",{className:"node-version-line"},a(Ht,{status:m?"online":v?"warn":"unknown"},m?"已登录":v?"待扫码":"等待二维码"),a("span",null,X),a("span",null,"D601 containerized")),a("p",{className:"muted paragraph"},m?"NapCat 已登录,ClaudeQQ 可通过容器内 HTTP/WS 链路收发 QQ 消息。":"用手机 QQ 扫描二维码授权登录。二维码只在首次加载或手动刷新时更新,D601 的 NapCat 端口仍只绑定 127.0.0.1。"),a("div",{className:"microservice-ref-card"},a("span",null,"NapCat WebUI"),a("strong",null,D.webui?.url||"http://napcat:6099/webui"),a("code",null,"local-only / proxied QR login")),a("div",{className:"microservice-ref-card"},a("span",null,"QR Source"),a("strong",null,V.modifiedAt?Nu(V.modifiedAt):n.qrcodeRefreshedAt?Nu(n.qrcodeRefreshedAt):"--"),a("code",null,V.file||"/napcat/cache/qrcode.png"))))),a(Si,{title:"消息推送",eyebrow:"Push API"},a("div",{className:"microservice-ref-card"},a("span",null,U1.label),a("strong",null,String(U1.userId)),a("code",null,"private userId / 默认推送测试目标")),a("form",{className:"stack-form",onSubmit:L,"data-testid":"claudeqq-push-form"},a("label",null,"目标类型",a("select",{value:y.targetType,onChange:(T)=>_((S)=>({...S,targetType:T.target.value}))},a("option",{value:"private"},"私聊 userId"),a("option",{value:"group"},"群 groupId"))),a("label",null,"QQ ID",a("input",{value:y.targetId,onChange:(T)=>_((S)=>({...S,targetId:T.target.value})),placeholder:String(U1.userId)})),a("label",null,"消息内容",a("textarea",{value:y.message,onChange:(T)=>_((S)=>({...S,message:T.target.value})),rows:4,placeholder:"通过 ClaudeQQ 推送一条 QQ 消息"})),a("button",{type:"submit",className:"primary-btn"},"发送 QQ 消息")),a("p",{className:"muted paragraph"},`主 server 和其他用户服务可通过 UniDesk 同源代理调用 /api/push/text;当前人工推送测试默认使用 ${U1.label} ${U1.userId},不需要暴露 D601 后端端口。`)),a(Si,{title:"QQ 事件订阅",eyebrow:"Webhook Subscription",loading:n.loading},a("form",{className:"stack-form",onSubmit:w,"data-testid":"claudeqq-subscription-form"},a("label",null,"订阅名称",a("input",{value:$.name,onChange:(T)=>A((S)=>({...S,name:T.target.value}))})),a("label",null,"回调 URL",a("input",{value:$.targetUrl,onChange:(T)=>A((S)=>({...S,targetUrl:T.target.value})),placeholder:"http://host.docker.internal:18080/..."})),a("label",null,"事件类型",a("input",{value:$.eventTypes,onChange:(T)=>A((S)=>({...S,eventTypes:T.target.value})),placeholder:"message,notice"})),a("label",null,"签名密钥",a("input",{value:$.secret,onChange:(T)=>A((S)=>({...S,secret:T.target.value})),placeholder:"可选,生成 x-claudeqq-signature"})),a("button",{type:"submit",className:"primary-btn"},"创建订阅")),p.length===0?a(H_,{title:"暂无订阅",text:"可以为 main server 或其他用户服务注册 HTTP webhook"}):a("div",{className:"table-wrap","data-testid":"claudeqq-subscription-table"},a("table",null,a("thead",null,a("tr",null,a("th",null,"名称"),a("th",null,"状态"),a("th",null,"事件"),a("th",null,"回调"),a("th",null,"最近投递"),a("th",null,"操作"))),a("tbody",null,p.map((T)=>a("tr",{key:T.id},a("td",null,a("strong",null,T.name||T.id),a("code",null,T.id||"--")),a("td",null,a(Ht,{status:T.enabled?"online":"warn"},T.enabled?"enabled":"disabled")),a("td",null,Array.isArray(T.eventTypes)?T.eventTypes.join(", "):"message"),a("td",null,T.targetUrl||"--"),a("td",null,T.lastDelivery?`${T.lastDelivery.ok?"OK":"FAIL"} ${Nu(T.lastDelivery.at)}`:"--"),a("td",null,a("button",{type:"button",className:"ghost-btn",onClick:()=>J(T.id)},"删除"))))))),a("div",{className:"panel-actions inline-actions"},a(O_,{title:"ClaudeQQ Subscriptions",data:n.subscriptions,onOpen:f,testId:"raw-claudeqq-subscriptions"}))),a(Si,{title:"最近 QQ 事件",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Event Stream",loading:n.loading},Y.length===0?a(H_,{title:"暂无事件",text:"等待 NapCat WebSocket 上报 QQ 消息事件,或通过订阅 API 消费后续事件"}):a("div",{className:"table-wrap","data-testid":"claudeqq-event-list"},a("table",null,a("thead",null,a("tr",null,a("th",null,"时间"),a("th",null,"类型"),a("th",null,"会话"),a("th",null,"消息"),a("th",null,"ID"))),a("tbody",null,Y.map((T)=>a("tr",{key:T.id},a("td",null,Nu(T.receivedAt||T.timestamp)),a("td",null,a(Ht,{status:T.postType||T.eventType},T.postType||T.eventType||"--")),a("td",null,$U(T)),a("td",null,_U(T)),a("td",null,a("code",null,T.messageId||T.id||"--"))))))),a("div",{className:"panel-actions inline-actions"},a(O_,{title:"ClaudeQQ Events",data:n.events,onOpen:f,testId:"raw-claudeqq-events"}))),a(Si,{title:"已发送消息",eyebrow:`${O.length} Sent`,loading:n.loading},O.length===0?a(H_,{title:"暂无发送记录",text:"发送日志来自 ClaudeQQ bot_workspace/messages/sent_messages.jsonl"}):a("div",{className:"table-wrap"},a("table",null,a("thead",null,a("tr",null,a("th",null,"时间"),a("th",null,"目标"),a("th",null,"消息"),a("th",null,"结果"))),a("tbody",null,O.map((T,S)=>a("tr",{key:T.id||S},a("td",null,Nu(T.timestamp||T.sentAt||T.createdAt)),a("td",null,$U(T)),a("td",null,_U(T)),a("td",null,T.status||T.messageId||T.message_id||"--")))))),a("div",{className:"panel-actions inline-actions"},a(O_,{title:"ClaudeQQ Sent Messages",data:n.sent,onOpen:f,testId:"raw-claudeqq-sent"})))))}var P_=Pu(qf(),1);var jU=Pu(qf(),1),Uf=jU.default.createElement;function FU({markdown:u,className:f,testId:l}){let r=String(u??"").trimEnd(),n=["markdown-body",f].filter(Boolean).join(" ");return Uf("div",{className:n,"data-testid":l},JU(r,"md"))}function JU(u,f){let l=jT(u).split(` -`),r=[],n=0;while(n\s?/u.test(i)){let j=[];while(n\s?(.*)$/u);if(U!==null){j.push(U[1]),n+=1;continue}if(F.trim().length===0){j.push(""),n+=1;continue}break}r.push(Uf("blockquote",{key:`${f}-quote-${n}`},JU(j.join(` -`),`${f}-quote-${n}`)));continue}if(QU(l,n)){let j=n,F=B_(l[n]??""),U=B_(l[n+1]??"");n+=2;let Q=[];while(n0)Q.push(B_(l[n]??"")),n+=1;r.push(qT(F,U,Q,`${f}-table-${j}`));continue}let $=Dt(i);if($!==null){let j=n,F=$.ordered,U=$.start,Q=[];while(nUT(w,`${f}-list-${j}-${J}`))));continue}let A=n,c=[];while(n0&&!JT(l,n))c.push(l[n].trim()),n+=1;if(c.length===0)c.push(i.trim()),n+=1;r.push(Uf("p",{key:`${f}-p-${A}`},n0(c.join(` -`),`${f}-p-${A}`)))}return r}function jT(u){return String(u||"").replace(/\r\n/gu,` +`+i.stack}return{value:u,source:f,stack:n,digest:null}}function Z4(u,f,l){return{value:u,source:null,stack:l!=null?l:null,digest:f!=null?f:null}}function c2(u,f){try{console.error(f.value)}catch(l){setTimeout(function(){throw l})}}var qz=typeof WeakMap==="function"?WeakMap:Map;function LJ(u,f,l){l=z0(-1,l),l.tag=3,l.payload={element:null};var r=f.value;return l.callback=function(){_t||(_t=!0,w2=r),c2(u,f)},l}function wJ(u,f,l){l=z0(-1,l),l.tag=3;var r=u.type.getDerivedStateFromError;if(typeof r==="function"){var n=f.value;l.payload=function(){return r(n)},l.callback=function(){c2(u,f)}}var i=u.stateNode;return i!==null&&typeof i.componentDidCatch==="function"&&(l.callback=function(){c2(u,f),typeof r!=="function"&&(cn===null?cn=new Set([this]):cn.add(this));var y=f.stack;this.componentDidCatch(f.value,{componentStack:y!==null?y:""})}),l}function Dj(u,f,l){var r=u.pingCache;if(r===null){r=u.pingCache=new qz;var n=new Set;r.set(f,n)}else n=r.get(f),n===void 0&&(n=new Set,r.set(f,n));n.has(l)||(n.add(l),u=Vz.bind(null,u,f,l),f.then(u,u))}function Xj(u){do{var f;if(f=u.tag===13)f=u.memoizedState,f=f!==null?f.dehydrated!==null?!0:!1:!0;if(f)return u;u=u.return}while(u!==null);return null}function Yj(u,f,l,r,n){if((u.mode&1)===0)return u===f?u.flags|=65536:(u.flags|=128,l.flags|=131072,l.flags&=-52805,l.tag===1&&(l.alternate===null?l.tag=17:(f=z0(-1,1),f.tag=2,An(l,f,1))),l.lanes|=1),u;return u.flags|=65536,u.lanes=n,u}var Nz=H0.ReactCurrentOwner,Rl=!1;function Hl(u,f,l,r){f.child=u===null?aF(f,null,l,r):zi(f,u.child,l,r)}function Sj(u,f,l,r,n){l=l.render;var i=f.ref;if(Wi(f,n),r=e2(u,f,l,r,i,n),l=u5(),u!==null&&!Rl)return f.updateQueue=u.updateQueue,f.flags&=-2053,u.lanes&=~n,O0(u,f,n);return Tf&&l&&R2(f),f.flags|=1,Hl(u,f,r,n),f.child}function pj(u,f,l,r,n){if(u===null){var i=l.type;if(typeof i==="function"&&!A5(i)&&i.defaultProps===void 0&&l.compare===null&&l.defaultProps===void 0)return f.tag=15,f.type=i,KJ(u,f,i,r,n);return u=C3(l.type,null,r,f,f.mode,n),u.ref=f.ref,u.return=f,f.child=u}if(i=u.child,(u.lanes&n)===0){var y=i.memoizedProps;if(l=l.compare,l=l!==null?l:j_,l(y,r)&&u.ref===f.ref)return O0(u,f,n)}return f.flags|=1,u=Fn(i,r),u.ref=f.ref,u.return=f,f.child=u}function KJ(u,f,l,r,n){if(u!==null){var i=u.memoizedProps;if(j_(i,r)&&u.ref===f.ref)if(Rl=!1,f.pendingProps=r=i,(u.lanes&n)!==0)(u.flags&131072)!==0&&(Rl=!0);else return f.lanes=u.lanes,O0(u,f,n)}return j2(u,f,l,r,n)}function GJ(u,f,l){var r=f.pendingProps,n=r.children,i=u!==null?u.memoizedState:null;if(r.mode==="hidden")if((f.mode&1)===0)f.memoizedState={baseLanes:0,cachePool:null,transitions:null},Nf(Ji,ir),ir|=l;else{if((l&1073741824)===0)return u=i!==null?i.baseLanes|l:l,f.lanes=f.childLanes=1073741824,f.memoizedState={baseLanes:u,cachePool:null,transitions:null},f.updateQueue=null,Nf(Ji,ir),ir|=u,null;f.memoizedState={baseLanes:0,cachePool:null,transitions:null},r=i!==null?i.baseLanes:l,Nf(Ji,ir),ir|=r}else i!==null?(r=i.baseLanes|l,f.memoizedState=null):r=l,Nf(Ji,ir),ir|=r;return Hl(u,f,n,l),f.child}function zJ(u,f){var l=f.ref;if(u===null&&l!==null||u!==null&&u.ref!==l)f.flags|=512,f.flags|=2097152}function j2(u,f,l,r,n){var i=hl(l)?t1:Ll.current;if(i=Ki(f,i),Wi(f,n),l=e2(u,f,l,r,i,n),r=u5(),u!==null&&!Rl)return f.updateQueue=u.updateQueue,f.flags&=-2053,u.lanes&=~n,O0(u,f,n);return Tf&&r&&R2(f),f.flags|=1,Hl(u,f,l,n),f.child}function mj(u,f,l,r,n){if(hl(l)){var i=!0;o3(f)}else i=!1;if(Wi(f,n),f.stateNode===null)m3(u,f),WJ(f,l,r),A2(f,l,r,n),r=!0;else if(u===null){var{stateNode:y,memoizedProps:_}=f;y.props=_;var $=y.context,A=l.contextType;typeof A==="object"&&A!==null?A=zr(A):(A=hl(l)?t1:Ll.current,A=Ki(f,A));var c=l.getDerivedStateFromProps,j=typeof c==="function"||typeof y.getSnapshotBeforeUpdate==="function";j||typeof y.UNSAFE_componentWillReceiveProps!=="function"&&typeof y.componentWillReceiveProps!=="function"||(_!==r||$!==A)&&Vj(f,y,r,A),un=!1;var F=f.memoizedState;y.state=F,lt(f,r,y,n),$=f.memoizedState,_!==r||F!==$||xl.current||un?(typeof c==="function"&&(t2(f,l,c,r),$=f.memoizedState),(_=un||Bj(f,l,_,r,F,$,A))?(j||typeof y.UNSAFE_componentWillMount!=="function"&&typeof y.componentWillMount!=="function"||(typeof y.componentWillMount==="function"&&y.componentWillMount(),typeof y.UNSAFE_componentWillMount==="function"&&y.UNSAFE_componentWillMount()),typeof y.componentDidMount==="function"&&(f.flags|=4194308)):(typeof y.componentDidMount==="function"&&(f.flags|=4194308),f.memoizedProps=r,f.memoizedState=$),y.props=r,y.state=$,y.context=A,r=_):(typeof y.componentDidMount==="function"&&(f.flags|=4194308),r=!1)}else{y=f.stateNode,dF(u,f),_=f.memoizedProps,A=f.type===f.elementType?_:Sr(f.type,_),y.props=A,j=f.pendingProps,F=y.context,$=l.contextType,typeof $==="object"&&$!==null?$=zr($):($=hl(l)?t1:Ll.current,$=Ki(f,$));var U=l.getDerivedStateFromProps;(c=typeof U==="function"||typeof y.getSnapshotBeforeUpdate==="function")||typeof y.UNSAFE_componentWillReceiveProps!=="function"&&typeof y.componentWillReceiveProps!=="function"||(_!==j||F!==$)&&Vj(f,y,r,$),un=!1,F=f.memoizedState,y.state=F,lt(f,r,y,n);var Q=f.memoizedState;_!==j||F!==Q||xl.current||un?(typeof U==="function"&&(t2(f,l,U,r),Q=f.memoizedState),(A=un||Bj(f,l,A,r,F,Q,$)||!1)?(c||typeof y.UNSAFE_componentWillUpdate!=="function"&&typeof y.componentWillUpdate!=="function"||(typeof y.componentWillUpdate==="function"&&y.componentWillUpdate(r,Q,$),typeof y.UNSAFE_componentWillUpdate==="function"&&y.UNSAFE_componentWillUpdate(r,Q,$)),typeof y.componentDidUpdate==="function"&&(f.flags|=4),typeof y.getSnapshotBeforeUpdate==="function"&&(f.flags|=1024)):(typeof y.componentDidUpdate!=="function"||_===u.memoizedProps&&F===u.memoizedState||(f.flags|=4),typeof y.getSnapshotBeforeUpdate!=="function"||_===u.memoizedProps&&F===u.memoizedState||(f.flags|=1024),f.memoizedProps=r,f.memoizedState=Q),y.props=r,y.state=Q,y.context=$,r=A):(typeof y.componentDidUpdate!=="function"||_===u.memoizedProps&&F===u.memoizedState||(f.flags|=4),typeof y.getSnapshotBeforeUpdate!=="function"||_===u.memoizedProps&&F===u.memoizedState||(f.flags|=1024),r=!1)}return F2(u,f,l,r,i,n)}function F2(u,f,l,r,n,i){zJ(u,f);var y=(f.flags&128)!==0;if(!r&&!y)return n&&Kj(f,l,!1),O0(u,f,i);r=f.stateNode,Nz.current=f;var _=y&&typeof l.getDerivedStateFromError!=="function"?null:r.render();return f.flags|=1,u!==null&&y?(f.child=zi(f,u.child,null,i),f.child=zi(f,null,_,i)):Hl(u,f,_,i),f.memoizedState=r.state,n&&Kj(f,l,!0),f.child}function TJ(u){var f=u.stateNode;f.pendingContext?wj(u,f.pendingContext,f.pendingContext!==f.context):f.context&&wj(u,f.context,!1),s2(u,f.containerInfo)}function Pj(u,f,l,r,n){return Gi(),h2(n),f.flags|=256,Hl(u,f,l,r),f.child}var J2={dehydrated:null,treeContext:null,retryLane:0};function U2(u){return{baseLanes:u,cachePool:null,transitions:null}}function EJ(u,f,l){var r=f.pendingProps,n=Of.current,i=!1,y=(f.flags&128)!==0,_;if((_=y)||(_=u!==null&&u.memoizedState===null?!1:(n&2)!==0),_)i=!0,f.flags&=-129;else if(u===null||u.memoizedState!==null)n|=1;if(Nf(Of,n&1),u===null){if(_2(f),u=f.memoizedState,u!==null&&(u=u.dehydrated,u!==null))return(f.mode&1)===0?f.lanes=1:u.data==="$!"?f.lanes=8:f.lanes=1073741824,null;return y=r.children,u=r.fallback,i?(r=f.mode,i=f.child,y={mode:"hidden",children:y},(r&1)===0&&i!==null?(i.childLanes=0,i.pendingProps=y):i=wt(y,r,0,null),u=$1(u,r,l,null),i.return=f,u.return=f,i.sibling=u,f.child=i,f.child.memoizedState=U2(l),f.memoizedState=J2,u):r5(f,y)}if(n=u.memoizedState,n!==null&&(_=n.dehydrated,_!==null))return Wz(u,f,y,r,_,n,l);if(i){i=r.fallback,y=f.mode,n=u.child,_=n.sibling;var $={mode:"hidden",children:r.children};return(y&1)===0&&f.child!==n?(r=f.child,r.childLanes=0,r.pendingProps=$,f.deletions=null):(r=Fn(n,$),r.subtreeFlags=n.subtreeFlags&14680064),_!==null?i=Fn(_,i):(i=$1(i,y,l,null),i.flags|=2),i.return=f,r.return=f,r.sibling=i,f.child=r,r=i,i=f.child,y=u.child.memoizedState,y=y===null?U2(l):{baseLanes:y.baseLanes|l,cachePool:null,transitions:y.transitions},i.memoizedState=y,i.childLanes=u.childLanes&~l,f.memoizedState=J2,r}return i=u.child,u=i.sibling,r=Fn(i,{mode:"visible",children:r.children}),(f.mode&1)===0&&(r.lanes=l),r.return=f,r.sibling=null,u!==null&&(l=f.deletions,l===null?(f.deletions=[u],f.flags|=16):l.push(u)),f.child=r,f.memoizedState=null,r}function r5(u,f){return f=wt({mode:"visible",children:f},u.mode,0,null),f.return=u,u.child=f}function Z3(u,f,l,r){return r!==null&&h2(r),zi(f,u.child,null,l),u=r5(f,f.pendingProps.children),u.flags|=2,f.memoizedState=null,u}function Wz(u,f,l,r,n,i,y){if(l){if(f.flags&256)return f.flags&=-257,r=Z4(Error(Uu(422))),Z3(u,f,y,r);if(f.memoizedState!==null)return f.child=u.child,f.flags|=128,null;return i=r.fallback,n=f.mode,r=wt({mode:"visible",children:r.children},n,0,null),i=$1(i,n,y,null),i.flags|=2,r.return=f,i.return=f,r.sibling=i,f.child=r,(f.mode&1)!==0&&zi(f,u.child,null,y),f.child.memoizedState=U2(y),f.memoizedState=J2,i}if((f.mode&1)===0)return Z3(u,f,y,null);if(n.data==="$!"){if(r=n.nextSibling&&n.nextSibling.dataset,r)var _=r.dgst;return r=_,i=Error(Uu(419)),r=Z4(i,r,void 0),Z3(u,f,y,r)}if(_=(y&u.childLanes)!==0,Rl||_){if(r=ul,r!==null){switch(y&-y){case 4:n=2;break;case 16:n=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:n=32;break;case 536870912:n=268435456;break;default:n=0}n=(n&(r.suspendedLanes|y))!==0?0:n,n!==0&&n!==i.retryLane&&(i.retryLane=n,Z0(u,n),Mr(r,u,n,-1))}return t5(),r=Z4(Error(Uu(421))),Z3(u,f,y,r)}if(n.data==="$?")return f.flags|=128,f.child=u.child,f=Dz.bind(null,u),n._reactRetry=f,null;return u=i.treeContext,yr=tn(n.nextSibling),_r=f,Tf=!0,mr=null,u!==null&&(Lr[wr++]=K0,Lr[wr++]=G0,Lr[wr++]=A1,K0=u.id,G0=u.overflow,A1=f),f=r5(f,r.children),f.flags|=4096,f}function Mj(u,f,l){u.lanes|=f;var r=u.alternate;r!==null&&(r.lanes|=f),$2(u.return,f,l)}function O4(u,f,l,r,n){var i=u.memoizedState;i===null?u.memoizedState={isBackwards:f,rendering:null,renderingStartTime:0,last:r,tail:l,tailMode:n}:(i.isBackwards=f,i.rendering=null,i.renderingStartTime=0,i.last=r,i.tail=l,i.tailMode=n)}function ZJ(u,f,l){var r=f.pendingProps,n=r.revealOrder,i=r.tail;if(Hl(u,f,r.children,l),r=Of.current,(r&2)!==0)r=r&1|2,f.flags|=128;else{if(u!==null&&(u.flags&128)!==0)u:for(u=f.child;u!==null;){if(u.tag===13)u.memoizedState!==null&&Mj(u,l,f);else if(u.tag===19)Mj(u,l,f);else if(u.child!==null){u.child.return=u,u=u.child;continue}if(u===f)break u;for(;u.sibling===null;){if(u.return===null||u.return===f)break u;u=u.return}u.sibling.return=u.return,u=u.sibling}r&=1}if(Nf(Of,r),(f.mode&1)===0)f.memoizedState=null;else switch(n){case"forwards":l=f.child;for(n=null;l!==null;)u=l.alternate,u!==null&&rt(u)===null&&(n=l),l=l.sibling;l=n,l===null?(n=f.child,f.child=null):(n=l.sibling,l.sibling=null),O4(f,!1,n,l,i);break;case"backwards":l=null,n=f.child;for(f.child=null;n!==null;){if(u=n.alternate,u!==null&&rt(u)===null){f.child=n;break}u=n.sibling,n.sibling=l,l=n,n=u}O4(f,!0,l,null,i);break;case"together":O4(f,!1,null,null,void 0);break;default:f.memoizedState=null}return f.child}function m3(u,f){(f.mode&1)===0&&u!==null&&(u.alternate=null,f.alternate=null,f.flags|=2)}function O0(u,f,l){if(u!==null&&(f.dependencies=u.dependencies),j1|=f.lanes,(l&f.childLanes)===0)return null;if(u!==null&&f.child!==u.child)throw Error(Uu(153));if(f.child!==null){u=f.child,l=Fn(u,u.pendingProps),f.child=l;for(l.return=f;u.sibling!==null;)u=u.sibling,l=l.sibling=Fn(u,u.pendingProps),l.return=f;l.sibling=null}return f.child}function Lz(u,f,l){switch(f.tag){case 3:TJ(f),Gi();break;case 5:eF(f);break;case 1:hl(f.type)&&o3(f);break;case 4:s2(f,f.stateNode.containerInfo);break;case 10:var r=f.type._context,n=f.memoizedProps.value;Nf(ut,r._currentValue),r._currentValue=n;break;case 13:if(r=f.memoizedState,r!==null){if(r.dehydrated!==null)return Nf(Of,Of.current&1),f.flags|=128,null;if((l&f.child.childLanes)!==0)return EJ(u,f,l);return Nf(Of,Of.current&1),u=O0(u,f,l),u!==null?u.sibling:null}Nf(Of,Of.current&1);break;case 19:if(r=(l&f.childLanes)!==0,(u.flags&128)!==0){if(r)return ZJ(u,f,l);f.flags|=128}if(n=f.memoizedState,n!==null&&(n.rendering=null,n.tail=null,n.lastEffect=null),Nf(Of,Of.current),r)break;else return null;case 22:case 23:return f.lanes=0,GJ(u,f,l)}return O0(u,f,l)}var OJ,Q2,HJ,BJ;OJ=function(u,f){for(var l=f.child;l!==null;){if(l.tag===5||l.tag===6)u.appendChild(l.stateNode);else if(l.tag!==4&&l.child!==null){l.child.return=l,l=l.child;continue}if(l===f)break;for(;l.sibling===null;){if(l.return===null||l.return===f)return;l=l.return}l.sibling.return=l.return,l=l.sibling}};Q2=function(){};HJ=function(u,f,l,r){var n=u.memoizedProps;if(n!==r){u=f.stateNode,y1(r0.current);var i=null;switch(l){case"input":n=p4(u,n),r=p4(u,r),i=[];break;case"select":n=Bf({},n,{value:void 0}),r=Bf({},r,{value:void 0}),i=[];break;case"textarea":n=M4(u,n),r=M4(u,r),i=[];break;default:typeof n.onClick!=="function"&&typeof r.onClick==="function"&&(u.onclick=s3)}R4(l,r);var y;l=null;for(A in n)if(!r.hasOwnProperty(A)&&n.hasOwnProperty(A)&&n[A]!=null)if(A==="style"){var _=n[A];for(y in _)_.hasOwnProperty(y)&&(l||(l={}),l[y]="")}else A!=="dangerouslySetInnerHTML"&&A!=="children"&&A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&A!=="autoFocus"&&(i_.hasOwnProperty(A)?i||(i=[]):(i=i||[]).push(A,null));for(A in r){var $=r[A];if(_=n!=null?n[A]:void 0,r.hasOwnProperty(A)&&$!==_&&($!=null||_!=null))if(A==="style")if(_){for(y in _)!_.hasOwnProperty(y)||$&&$.hasOwnProperty(y)||(l||(l={}),l[y]="");for(y in $)$.hasOwnProperty(y)&&_[y]!==$[y]&&(l||(l={}),l[y]=$[y])}else l||(i||(i=[]),i.push(A,l)),l=$;else A==="dangerouslySetInnerHTML"?($=$?$.__html:void 0,_=_?_.__html:void 0,$!=null&&_!==$&&(i=i||[]).push(A,$)):A==="children"?typeof $!=="string"&&typeof $!=="number"||(i=i||[]).push(A,""+$):A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&(i_.hasOwnProperty(A)?($!=null&&A==="onScroll"&&wf("scroll",u),i||_===$||(i=[])):(i=i||[]).push(A,$))}l&&(i=i||[]).push("style",l);var A=i;if(f.updateQueue=A)f.flags|=4}};BJ=function(u,f,l,r){l!==r&&(f.flags|=4)};function Cy(u,f){if(!Tf)switch(u.tailMode){case"hidden":f=u.tail;for(var l=null;f!==null;)f.alternate!==null&&(l=f),f=f.sibling;l===null?u.tail=null:l.sibling=null;break;case"collapsed":l=u.tail;for(var r=null;l!==null;)l.alternate!==null&&(r=l),l=l.sibling;r===null?f||u.tail===null?u.tail=null:u.tail.sibling=null:r.sibling=null}}function Nl(u){var f=u.alternate!==null&&u.alternate.child===u.child,l=0,r=0;if(f)for(var n=u.child;n!==null;)l|=n.lanes|n.childLanes,r|=n.subtreeFlags&14680064,r|=n.flags&14680064,n.return=u,n=n.sibling;else for(n=u.child;n!==null;)l|=n.lanes|n.childLanes,r|=n.subtreeFlags,r|=n.flags,n.return=u,n=n.sibling;return u.subtreeFlags|=r,u.childLanes=l,f}function wz(u,f,l){var r=f.pendingProps;switch(x2(f),f.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Nl(f),null;case 1:return hl(f.type)&&a3(),Nl(f),null;case 3:if(r=f.stateNode,Ti(),Kf(xl),Kf(Ll),o2(),r.pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),u===null||u.child===null)T3(f)?f.flags|=4:u===null||u.memoizedState.isDehydrated&&(f.flags&256)===0||(f.flags|=1024,mr!==null&&(z2(mr),mr=null));return Q2(u,f),Nl(f),null;case 5:a2(f);var n=y1(q_.current);if(l=f.type,u!==null&&f.stateNode!=null)HJ(u,f,l,r,n),u.ref!==f.ref&&(f.flags|=512,f.flags|=2097152);else{if(!r){if(f.stateNode===null)throw Error(Uu(166));return Nl(f),null}if(u=y1(r0.current),T3(f)){r=f.stateNode,l=f.type;var i=f.memoizedProps;switch(r[f0]=f,r[U_]=i,u=(f.mode&1)!==0,l){case"dialog":wf("cancel",r),wf("close",r);break;case"iframe":case"object":case"embed":wf("load",r);break;case"video":case"audio":for(n=0;n",u=u.removeChild(u.firstChild)):typeof r.is==="string"?u=y.createElement(l,{is:r.is}):(u=y.createElement(l),l==="select"&&(y=u,r.multiple?y.multiple=!0:r.size&&(y.size=r.size))):u=y.createElementNS(u,l),u[f0]=f,u[U_]=r,OJ(u,f,!1,!1),f.stateNode=u;u:{switch(y=x4(l,r),l){case"dialog":wf("cancel",u),wf("close",u),n=r;break;case"iframe":case"object":case"embed":wf("load",u),n=r;break;case"video":case"audio":for(n=0;nZi&&(f.flags|=128,r=!0,Cy(i,!1),f.lanes=4194304)}else{if(!r)if(u=rt(y),u!==null){if(f.flags|=128,r=!0,l=u.updateQueue,l!==null&&(f.updateQueue=l,f.flags|=4),Cy(i,!0),i.tail===null&&i.tailMode==="hidden"&&!y.alternate&&!Tf)return Nl(f),null}else 2*mf()-i.renderingStartTime>Zi&&l!==1073741824&&(f.flags|=128,r=!0,Cy(i,!1),f.lanes=4194304);i.isBackwards?(y.sibling=f.child,f.child=y):(l=i.last,l!==null?l.sibling=y:f.child=y,i.last=y)}if(i.tail!==null)return f=i.tail,i.rendering=f,i.tail=f.sibling,i.renderingStartTime=mf(),f.sibling=null,l=Of.current,Nf(Of,r?l&1|2:l&1),f;return Nl(f),null;case 22:case 23:return $5(),r=f.memoizedState!==null,u!==null&&u.memoizedState!==null!==r&&(f.flags|=8192),r&&(f.mode&1)!==0?(ir&1073741824)!==0&&(Nl(f),f.subtreeFlags&6&&(f.flags|=8192)):Nl(f),null;case 24:return null;case 25:return null}throw Error(Uu(156,f.tag))}function Kz(u,f){switch(x2(f),f.tag){case 1:return hl(f.type)&&a3(),u=f.flags,u&65536?(f.flags=u&-65537|128,f):null;case 3:return Ti(),Kf(xl),Kf(Ll),o2(),u=f.flags,(u&65536)!==0&&(u&128)===0?(f.flags=u&-65537|128,f):null;case 5:return a2(f),null;case 13:if(Kf(Of),u=f.memoizedState,u!==null&&u.dehydrated!==null){if(f.alternate===null)throw Error(Uu(340));Gi()}return u=f.flags,u&65536?(f.flags=u&-65537|128,f):null;case 19:return Kf(Of),null;case 4:return Ti(),null;case 10:return k2(f.type._context),null;case 22:case 23:return $5(),null;case 24:return null;default:return null}}var O3=!1,Wl=!1,Gz=typeof WeakSet==="function"?WeakSet:Set,Tu=null;function Fi(u,f){var l=u.ref;if(l!==null)if(typeof l==="function")try{l(null)}catch(r){Df(u,f,r)}else l.current=null}function q2(u,f,l){try{l()}catch(r){Df(u,f,r)}}var Cj=!1;function zz(u,f){if(u2=k3,u=SF(),C2(u)){if("selectionStart"in u)var l={start:u.selectionStart,end:u.selectionEnd};else u:{l=(l=u.ownerDocument)&&l.defaultView||window;var r=l.getSelection&&l.getSelection();if(r&&r.rangeCount!==0){l=r.anchorNode;var{anchorOffset:n,focusNode:i}=r;r=r.focusOffset;try{l.nodeType,i.nodeType}catch(W){l=null;break u}var y=0,_=-1,$=-1,A=0,c=0,j=u,F=null;f:for(;;){for(var U;;){if(j!==l||n!==0&&j.nodeType!==3||(_=y+n),j!==i||r!==0&&j.nodeType!==3||($=y+r),j.nodeType===3&&(y+=j.nodeValue.length),(U=j.firstChild)===null)break;F=j,j=U}for(;;){if(j===u)break f;if(F===l&&++A===n&&(_=y),F===i&&++c===r&&($=y),(U=j.nextSibling)!==null)break;j=F,F=j.parentNode}j=U}l=_===-1||$===-1?null:{start:_,end:$}}else l=null}l=l||{start:0,end:0}}else l=null;f2={focusedElem:u,selectionRange:l},k3=!1;for(Tu=f;Tu!==null;)if(f=Tu,u=f.child,(f.subtreeFlags&1028)!==0&&u!==null)u.return=f,Tu=u;else for(;Tu!==null;){f=Tu;try{var Q=f.alternate;if((f.flags&1024)!==0)switch(f.tag){case 0:case 11:case 15:break;case 1:if(Q!==null){var{memoizedProps:L,memoizedState:w}=Q,J=f.stateNode,N=J.getSnapshotBeforeUpdate(f.elementType===f.type?L:Sr(f.type,L),w);J.__reactInternalSnapshotBeforeUpdate=N}break;case 3:var q=f.stateNode.containerInfo;q.nodeType===1?q.textContent="":q.nodeType===9&&q.documentElement&&q.removeChild(q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(Uu(163))}}catch(W){Df(f,f.return,W)}if(u=f.sibling,u!==null){u.return=f.return,Tu=u;break}Tu=f.return}return Q=Cj,Cj=!1,Q}function l_(u,f,l){var r=f.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var n=r=r.next;do{if((n.tag&u)===u){var i=n.destroy;n.destroy=void 0,i!==void 0&&q2(f,l,i)}n=n.next}while(n!==r)}}function Wt(u,f){if(f=f.updateQueue,f=f!==null?f.lastEffect:null,f!==null){var l=f=f.next;do{if((l.tag&u)===u){var r=l.create;l.destroy=r()}l=l.next}while(l!==f)}}function N2(u){var f=u.ref;if(f!==null){var l=u.stateNode;switch(u.tag){case 5:u=l;break;default:u=l}typeof f==="function"?f(u):f.current=u}}function VJ(u){var f=u.alternate;f!==null&&(u.alternate=null,VJ(f)),u.child=null,u.deletions=null,u.sibling=null,u.tag===5&&(f=u.stateNode,f!==null&&(delete f[f0],delete f[U_],delete f[n2],delete f[yz],delete f[_z])),u.stateNode=null,u.return=null,u.dependencies=null,u.memoizedProps=null,u.memoizedState=null,u.pendingProps=null,u.stateNode=null,u.updateQueue=null}function DJ(u){return u.tag===5||u.tag===3||u.tag===4}function Rj(u){u:for(;;){for(;u.sibling===null;){if(u.return===null||DJ(u.return))return null;u=u.return}u.sibling.return=u.return;for(u=u.sibling;u.tag!==5&&u.tag!==6&&u.tag!==18;){if(u.flags&2)continue u;if(u.child===null||u.tag===4)continue u;else u.child.return=u,u=u.child}if(!(u.flags&2))return u.stateNode}}function W2(u,f,l){var r=u.tag;if(r===5||r===6)u=u.stateNode,f?l.nodeType===8?l.parentNode.insertBefore(u,f):l.insertBefore(u,f):(l.nodeType===8?(f=l.parentNode,f.insertBefore(u,l)):(f=l,f.appendChild(u)),l=l._reactRootContainer,l!==null&&l!==void 0||f.onclick!==null||(f.onclick=s3));else if(r!==4&&(u=u.child,u!==null))for(W2(u,f,l),u=u.sibling;u!==null;)W2(u,f,l),u=u.sibling}function L2(u,f,l){var r=u.tag;if(r===5||r===6)u=u.stateNode,f?l.insertBefore(u,f):l.appendChild(u);else if(r!==4&&(u=u.child,u!==null))for(L2(u,f,l),u=u.sibling;u!==null;)L2(u,f,l),u=u.sibling}var _l=null,pr=!1;function d0(u,f,l){for(l=l.child;l!==null;)XJ(u,f,l),l=l.sibling}function XJ(u,f,l){if(l0&&typeof l0.onCommitFiberUnmount==="function")try{l0.onCommitFiberUnmount(ct,l)}catch(_){}switch(l.tag){case 5:Wl||Fi(l,f);case 6:var r=_l,n=pr;_l=null,d0(u,f,l),_l=r,pr=n,_l!==null&&(pr?(u=_l,l=l.stateNode,u.nodeType===8?u.parentNode.removeChild(l):u.removeChild(l)):_l.removeChild(l.stateNode));break;case 18:_l!==null&&(pr?(u=_l,l=l.stateNode,u.nodeType===8?w4(u.parentNode,l):u.nodeType===1&&w4(u,l),A_(u)):w4(_l,l.stateNode));break;case 4:r=_l,n=pr,_l=l.stateNode.containerInfo,pr=!0,d0(u,f,l),_l=r,pr=n;break;case 0:case 11:case 14:case 15:if(!Wl&&(r=l.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){n=r=r.next;do{var i=n,y=i.destroy;i=i.tag,y!==void 0&&((i&2)!==0?q2(l,f,y):(i&4)!==0&&q2(l,f,y)),n=n.next}while(n!==r)}d0(u,f,l);break;case 1:if(!Wl&&(Fi(l,f),r=l.stateNode,typeof r.componentWillUnmount==="function"))try{r.props=l.memoizedProps,r.state=l.memoizedState,r.componentWillUnmount()}catch(_){Df(l,f,_)}d0(u,f,l);break;case 21:d0(u,f,l);break;case 22:l.mode&1?(Wl=(r=Wl)||l.memoizedState!==null,d0(u,f,l),Wl=r):d0(u,f,l);break;default:d0(u,f,l)}}function xj(u){var f=u.updateQueue;if(f!==null){u.updateQueue=null;var l=u.stateNode;l===null&&(l=u.stateNode=new Gz),f.forEach(function(r){var n=Xz.bind(null,u,r);l.has(r)||(l.add(r),r.then(n,n))})}}function Yr(u,f){var l=f.deletions;if(l!==null)for(var r=0;rn&&(n=y),r&=~i}if(r=n,r=mf()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3000>r?3000:4320>r?4320:1960*Ez(r/1960))-r,10u?16:u,nn===null)var r=!1;else{if(u=nn,nn=null,$t=0,(lf&6)!==0)throw Error(Uu(331));var n=lf;lf|=4;for(Tu=u.current;Tu!==null;){var i=Tu,y=i.child;if((Tu.flags&16)!==0){var _=i.deletions;if(_!==null){for(var $=0;$<_.length;$++){var A=_[$];for(Tu=A;Tu!==null;){var c=Tu;switch(c.tag){case 0:case 11:case 15:l_(8,c,i)}var j=c.child;if(j!==null)j.return=c,Tu=j;else for(;Tu!==null;){c=Tu;var{sibling:F,return:U}=c;if(VJ(c),c===A){Tu=null;break}if(F!==null){F.return=U,Tu=F;break}Tu=U}}}var Q=i.alternate;if(Q!==null){var L=Q.child;if(L!==null){Q.child=null;do{var w=L.sibling;L.sibling=null,L=w}while(L!==null)}}Tu=i}}if((i.subtreeFlags&2064)!==0&&y!==null)y.return=i,Tu=y;else u:for(;Tu!==null;){if(i=Tu,(i.flags&2048)!==0)switch(i.tag){case 0:case 11:case 15:l_(9,i,i.return)}var J=i.sibling;if(J!==null){J.return=i.return,Tu=J;break u}Tu=i.return}}var N=u.current;for(Tu=N;Tu!==null;){y=Tu;var q=y.child;if((y.subtreeFlags&2064)!==0&&q!==null)q.return=y,Tu=q;else u:for(y=N;Tu!==null;){if(_=Tu,(_.flags&2048)!==0)try{switch(_.tag){case 0:case 11:case 15:Wt(9,_)}}catch(z){Df(_,_.return,z)}if(_===y){Tu=null;break u}var W=_.sibling;if(W!==null){W.return=_.return,Tu=W;break u}Tu=_.return}}if(lf=n,Nn(),l0&&typeof l0.onPostCommitFiberRoot==="function")try{l0.onPostCommitFiberRoot(ct,u)}catch(z){}r=!0}return r}finally{tf=l,Gr.transition=f}}return!1}function Ij(u,f,l){f=Ei(l,f),f=LJ(u,f,1),u=An(u,f,1),f=Bl(),u!==null&&(K_(u,1,f),bl(u,f))}function Df(u,f,l){if(u.tag===3)Ij(u,u,l);else for(;f!==null;){if(f.tag===3){Ij(f,u,l);break}else if(f.tag===1){var r=f.stateNode;if(typeof f.type.getDerivedStateFromError==="function"||typeof r.componentDidCatch==="function"&&(cn===null||!cn.has(r))){u=Ei(l,u),u=wJ(f,u,1),f=An(f,u,1),u=Bl(),f!==null&&(K_(f,1,u),bl(f,u));break}}f=f.return}}function Vz(u,f,l){var r=u.pingCache;r!==null&&r.delete(f),f=Bl(),u.pingedLanes|=u.suspendedLanes&l,ul===u&&($l&l)===l&&(gf===4||gf===3&&($l&130023424)===$l&&500>mf()-y5?_1(u,0):i5|=l),bl(u,f)}function RJ(u,f){f===0&&((u.mode&1)===0?f=1:(f=W3,W3<<=1,(W3&130023424)===0&&(W3=4194304)));var l=Bl();u=Z0(u,f),u!==null&&(K_(u,f,l),bl(u,l))}function Dz(u){var f=u.memoizedState,l=0;f!==null&&(l=f.retryLane),RJ(u,l)}function Xz(u,f){var l=0;switch(u.tag){case 13:var{stateNode:r,memoizedState:n}=u;n!==null&&(l=n.retryLane);break;case 19:r=u.stateNode;break;default:throw Error(Uu(314))}r!==null&&r.delete(f),RJ(u,l)}var xJ;xJ=function(u,f,l){if(u!==null)if(u.memoizedProps!==f.pendingProps||xl.current)Rl=!0;else{if((u.lanes&l)===0&&(f.flags&128)===0)return Rl=!1,Lz(u,f,l);Rl=(u.flags&131072)!==0?!0:!1}else Rl=!1,Tf&&(f.flags&1048576)!==0&&kF(f,e3,f.index);switch(f.lanes=0,f.tag){case 2:var r=f.type;m3(u,f),u=f.pendingProps;var n=Ki(f,Ll.current);Wi(f,l),n=e2(null,f,r,u,n,l);var i=u5();return f.flags|=1,typeof n==="object"&&n!==null&&typeof n.render==="function"&&n.$$typeof===void 0?(f.tag=1,f.memoizedState=null,f.updateQueue=null,hl(r)?(i=!0,o3(f)):i=!1,f.memoizedState=n.state!==null&&n.state!==void 0?n.state:null,g2(f),n.updater=Nt,f.stateNode=n,n._reactInternals=f,A2(f,r,u,l),f=F2(null,f,r,!0,i,l)):(f.tag=0,Tf&&i&&R2(f),Hl(null,f,n,l),f=f.child),f;case 16:r=f.elementType;u:{switch(m3(u,f),u=f.pendingProps,n=r._init,r=n(r._payload),f.type=r,n=f.tag=Sz(r),u=Sr(r,u),n){case 0:f=j2(null,f,r,u,l);break u;case 1:f=mj(null,f,r,u,l);break u;case 11:f=Sj(null,f,r,u,l);break u;case 14:f=pj(null,f,r,Sr(r.type,u),l);break u}throw Error(Uu(306,r,""))}return f;case 0:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),j2(u,f,r,n,l);case 1:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),mj(u,f,r,n,l);case 3:u:{if(TJ(f),u===null)throw Error(Uu(387));r=f.pendingProps,i=f.memoizedState,n=i.element,dF(u,f),lt(f,r,null,l);var y=f.memoizedState;if(r=y.element,i.isDehydrated)if(i={element:r,isDehydrated:!1,cache:y.cache,pendingSuspenseBoundaries:y.pendingSuspenseBoundaries,transitions:y.transitions},f.updateQueue.baseState=i,f.memoizedState=i,f.flags&256){n=Ei(Error(Uu(423)),f),f=Pj(u,f,r,l,n);break u}else if(r!==n){n=Ei(Error(Uu(424)),f),f=Pj(u,f,r,l,n);break u}else for(yr=tn(f.stateNode.containerInfo.firstChild),_r=f,Tf=!0,mr=null,l=aF(f,null,r,l),f.child=l;l;)l.flags=l.flags&-3|4096,l=l.sibling;else{if(Gi(),r===n){f=O0(u,f,l);break u}Hl(u,f,r,l)}f=f.child}return f;case 5:return eF(f),u===null&&_2(f),r=f.type,n=f.pendingProps,i=u!==null?u.memoizedProps:null,y=n.children,l2(r,n)?y=null:i!==null&&l2(r,i)&&(f.flags|=32),zJ(u,f),Hl(u,f,y,l),f.child;case 6:return u===null&&_2(f),null;case 13:return EJ(u,f,l);case 4:return s2(f,f.stateNode.containerInfo),r=f.pendingProps,u===null?f.child=zi(f,null,r,l):Hl(u,f,r,l),f.child;case 11:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),Sj(u,f,r,n,l);case 7:return Hl(u,f,f.pendingProps,l),f.child;case 8:return Hl(u,f,f.pendingProps.children,l),f.child;case 12:return Hl(u,f,f.pendingProps.children,l),f.child;case 10:u:{if(r=f.type._context,n=f.pendingProps,i=f.memoizedProps,y=n.value,Nf(ut,r._currentValue),r._currentValue=y,i!==null)if(Cr(i.value,y)){if(i.children===n.children&&!xl.current){f=O0(u,f,l);break u}}else for(i=f.child,i!==null&&(i.return=f);i!==null;){var _=i.dependencies;if(_!==null){y=i.child;for(var $=_.firstContext;$!==null;){if($.context===r){if(i.tag===1){$=z0(-1,l&-l),$.tag=2;var A=i.updateQueue;if(A!==null){A=A.shared;var c=A.pending;c===null?$.next=$:($.next=c.next,c.next=$),A.pending=$}}i.lanes|=l,$=i.alternate,$!==null&&($.lanes|=l),$2(i.return,l,f),_.lanes|=l;break}$=$.next}}else if(i.tag===10)y=i.type===f.type?null:i.child;else if(i.tag===18){if(y=i.return,y===null)throw Error(Uu(341));y.lanes|=l,_=y.alternate,_!==null&&(_.lanes|=l),$2(y,l,f),y=i.sibling}else y=i.child;if(y!==null)y.return=i;else for(y=i;y!==null;){if(y===f){y=null;break}if(i=y.sibling,i!==null){i.return=y.return,y=i;break}y=y.return}i=y}Hl(u,f,n.children,l),f=f.child}return f;case 9:return n=f.type,r=f.pendingProps.children,Wi(f,l),n=zr(n),r=r(n),f.flags|=1,Hl(u,f,r,l),f.child;case 14:return r=f.type,n=Sr(r,f.pendingProps),n=Sr(r.type,n),pj(u,f,r,n,l);case 15:return KJ(u,f,f.type,f.pendingProps,l);case 17:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),m3(u,f),f.tag=1,hl(r)?(u=!0,o3(f)):u=!1,Wi(f,l),WJ(f,r,n),A2(f,r,n,l),F2(null,f,r,!0,u,l);case 19:return ZJ(u,f,l);case 22:return GJ(u,f,l)}throw Error(Uu(156,f.tag))};function hJ(u,f){return QF(u,f)}function Yz(u,f,l,r){this.tag=u,this.key=l,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=f,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Kr(u,f,l,r){return new Yz(u,f,l,r)}function A5(u){return u=u.prototype,!(!u||!u.isReactComponent)}function Sz(u){if(typeof u==="function")return A5(u)?1:0;if(u!==void 0&&u!==null){if(u=u.$$typeof,u===H2)return 11;if(u===B2)return 14}return 2}function Fn(u,f){var l=u.alternate;return l===null?(l=Kr(u.tag,f,u.key,u.mode),l.elementType=u.elementType,l.type=u.type,l.stateNode=u.stateNode,l.alternate=u,u.alternate=l):(l.pendingProps=f,l.type=u.type,l.flags=0,l.subtreeFlags=0,l.deletions=null),l.flags=u.flags&14680064,l.childLanes=u.childLanes,l.lanes=u.lanes,l.child=u.child,l.memoizedProps=u.memoizedProps,l.memoizedState=u.memoizedState,l.updateQueue=u.updateQueue,f=u.dependencies,l.dependencies=f===null?null:{lanes:f.lanes,firstContext:f.firstContext},l.sibling=u.sibling,l.index=u.index,l.ref=u.ref,l}function C3(u,f,l,r,n,i){var y=2;if(r=u,typeof u==="function")A5(u)&&(y=1);else if(typeof u==="string")y=5;else u:switch(u){case ni:return $1(l.children,n,i,f);case O2:y=8,n|=8;break;case D4:return u=Kr(12,l,f,n|2),u.elementType=D4,u.lanes=i,u;case X4:return u=Kr(13,l,f,n),u.elementType=X4,u.lanes=i,u;case Y4:return u=Kr(19,l,f,n),u.elementType=Y4,u.lanes=i,u;case ej:return wt(l,n,i,f);default:if(typeof u==="object"&&u!==null)switch(u.$$typeof){case oj:y=10;break u;case dj:y=9;break u;case H2:y=11;break u;case B2:y=14;break u;case e0:y=16,r=null;break u}throw Error(Uu(130,u==null?u:typeof u,""))}return f=Kr(y,l,f,n),f.elementType=u,f.type=r,f.lanes=i,f}function $1(u,f,l,r){return u=Kr(7,u,r,f),u.lanes=l,u}function wt(u,f,l,r){return u=Kr(22,u,r,f),u.elementType=ej,u.lanes=l,u.stateNode={isHidden:!1},u}function H4(u,f,l){return u=Kr(6,u,null,f),u.lanes=l,u}function B4(u,f,l){return f=Kr(4,u.children!==null?u.children:[],u.key,f),f.lanes=l,f.stateNode={containerInfo:u.containerInfo,pendingChildren:null,implementation:u.implementation},f}function pz(u,f,l,r,n){this.tag=f,this.containerInfo=u,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=J4(0),this.expirationTimes=J4(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=J4(0),this.identifierPrefix=r,this.onRecoverableError=n,this.mutableSourceEagerHydrationData=null}function c5(u,f,l,r,n,i,y,_,$){return u=new pz(u,f,l,_,$),f===1?(f=1,i===!0&&(f|=8)):f=0,i=Kr(3,null,null,f),u.current=i,i.stateNode=u,i.memoizedState={element:r,isDehydrated:l,cache:null,transitions:null,pendingSuspenseBoundaries:null},g2(i),u}function mz(u,f,l){var r=3{function gJ(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=="function")return;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(gJ)}catch(u){console.error(u)}}gJ(),sJ.exports=IJ()});var oJ=nr((Q5)=>{var aJ=U5();Q5.createRoot=aJ.createRoot,Q5.hydrateRoot=aJ.hydrateRoot;var xz});var aQ=nr(($6)=>{var iO=Qf(),yO=Symbol.for("react.element"),_O=Symbol.for("react.fragment"),$O=Object.prototype.hasOwnProperty,tO=iO.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,AO={key:!0,ref:!0,__self:!0,__source:!0};function sQ(u,f,l){var r,n={},i=null,y=null;l!==void 0&&(i=""+l),f.key!==void 0&&(i=""+f.key),f.ref!==void 0&&(y=f.ref);for(r in f)$O.call(f,r)&&!AO.hasOwnProperty(r)&&(n[r]=f[r]);if(u&&u.defaultProps)for(r in f=u.defaultProps,f)n[r]===void 0&&(n[r]=f[r]);return{$$typeof:yO,type:u,key:i,ref:y,props:n,_owner:tO.current}}$6.Fragment=_O;$6.jsx=sQ;$6.jsxs=sQ});var dQ=nr((em,oQ)=>{oQ.exports=aQ()});var HN=nr((ON)=>{var ty=Qf();function ZV(u,f){return u===f&&(u!==0||1/u===1/f)||u!==u&&f!==f}var OV=typeof Object.is==="function"?Object.is:ZV,HV=ty.useState,BV=ty.useEffect,VV=ty.useLayoutEffect,DV=ty.useDebugValue;function XV(u,f){var l=f(),r=HV({inst:{value:l,getSnapshot:f}}),n=r[0].inst,i=r[1];return VV(function(){n.value=l,n.getSnapshot=f,_9(n)&&i({inst:n})},[u,l,f]),BV(function(){return _9(n)&&i({inst:n}),u(function(){_9(n)&&i({inst:n})})},[u]),DV(l),l}function _9(u){var f=u.getSnapshot;u=u.value;try{var l=f();return!OV(u,l)}catch(r){return!0}}function YV(u,f){return f()}var SV=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?YV:XV;ON.useSyncExternalStore=ty.useSyncExternalStore!==void 0?ty.useSyncExternalStore:SV});var VN=nr((kh,BN)=>{BN.exports=HN()});var XN=nr((DN)=>{var f8=Qf(),pV=VN();function mV(u,f){return u===f&&(u!==0||1/u===1/f)||u!==u&&f!==f}var PV=typeof Object.is==="function"?Object.is:mV,MV=pV.useSyncExternalStore,CV=f8.useRef,RV=f8.useEffect,xV=f8.useMemo,hV=f8.useDebugValue;DN.useSyncExternalStoreWithSelector=function(u,f,l,r,n){var i=CV(null);if(i.current===null){var y={hasValue:!1,value:null};i.current=y}else y=i.current;i=xV(function(){function $(U){if(!A){if(A=!0,c=U,U=r(U),n!==void 0&&y.hasValue){var Q=y.value;if(n(Q,U))return j=Q}return j=U}if(Q=j,PV(c,U))return Q;var L=r(U);if(n!==void 0&&n(Q,L))return c=U,Q;return c=U,j=L}var A=!1,c,j,F=l===void 0?null:l;return[function(){return $(f())},F===null?void 0:function(){return $(F())}]},[f,l,r,n]);var _=MV(u,i[0],i[1]);return RV(function(){y.hasValue=!0,y.value=_},[_]),hV(_),_}});var SN=nr((gh,YN)=>{YN.exports=XN()});var In=Pu(Qf(),1);var _3="北京时间";var mK={timeZone:"Asia/Shanghai",hour12:!1},PK={timeZone:"Asia/Shanghai",hour12:!1},MK=new Intl.DateTimeFormat("en-CA",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23"});function d8(u){if(u===null||u===void 0||u==="")return null;let f=u instanceof Date?u:new Date(u);return Number.isNaN(f.getTime())?null:f}function Y7(u){let f=d8(u);if(!f)return null;return MK.formatToParts(f).reduce((l,r)=>{if(r.type!=="literal")l[r.type]=r.value;return l},{})}function Nu(u){let f=d8(u);return f?f.toLocaleString("zh-CN",mK):"--"}function $f(u){let f=d8(u);return f?f.toLocaleTimeString("zh-CN",PK):"--"}function e8(u){let f=Y7(u);if(!f)return"";let l=f.hour==="24"?"00":f.hour;return`${f.year}-${f.month}-${f.day}T${l}:${f.minute}`}function S7(u=new Date){let f=Y7(u);if(!f)return"";return`${f.year}-${f.month}-${f.day}`}function p7(u){if(!u)return null;let f=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(u);if(!f)return null;let[,l,r,n,i,y,_="00"]=f,$=Date.UTC(Number(l),Number(r)-1,Number(n),Number(i)-8,Number(y),Number(_)),A=new Date($),c=e8(A);return Number.isNaN(A.getTime())||c!==`${l}-${r}-${n}T${i}:${y}`?null:A.toISOString()}var iw=Pu(oJ(),1);var Ot=Pu(Qf(),1);var dJ=Pu(Qf(),1),E_=dJ.default.createElement;function hz({active:u=!0,label:f="正在加载"}){if(!u)return null;return E_("span",{className:"loading-spinner-indicator",role:"status","aria-label":f,title:f,"data-testid":"loading-title-indicator"},E_("span",{className:"loading-spinner-ring","aria-hidden":!0}))}function nf({title:u,children:f,loading:l,level:r=2,className:n="",label:i="正在加载"}){return E_(r===3?"h3":"h2",{className:`loading-title ${l?"is-loading":""} ${n}`.trim()},E_("span",{className:"loading-title-text"},f??u),E_(hz,{active:Boolean(l),label:i}))}class Bi extends Error{unideskRequestError=!0;meta;constructor(u,f){super(u);this.name="UniDeskRequestError",this.meta=f}}function bz(u){return new Promise((f)=>setTimeout(f,u))}function H_(u,f="操作失败"){return u instanceof Error?u.message:String(u||f)}function Et(u,f=500){if(u===null||u===void 0)return"";let l=typeof u==="string"?u:JSON.stringify(u),r=String(l||"").replace(/\s+/gu," ").trim();return r.length>f?`${r.slice(0,f)}...`:r}function vz(u){try{let f=typeof location<"u"&&location.origin?location.origin:"http://localhost";return new URL(u,f).toString()}catch{return u}}function eJ(u){return String(u.method||"GET").toUpperCase()}function kz(u){if(u===null||u===void 0)return!1;if(typeof u!=="object")return!1;if(typeof Blob<"u"&&u instanceof Blob)return!1;if(typeof FormData<"u"&&u instanceof FormData)return!1;if(typeof URLSearchParams<"u"&&u instanceof URLSearchParams)return!1;if(typeof ArrayBuffer<"u"&&u instanceof ArrayBuffer)return!1;return!0}function uU(u){let f=new Headers(u.headers||{}),l=kz(u.body)?JSON.stringify(u.body):u.body;if(l&&!f.has("content-type")&&typeof l==="string")f.set("content-type","application/json");return{...u,credentials:u.credentials||"same-origin",body:l,headers:f}}function fU(u){if(u?.error&&typeof u.error==="object"&&typeof u.error.message==="string")return u.error.message;if(typeof u?.error==="string")return u.error;if(typeof u?.message==="string")return u.message;if(typeof u?.detail==="string")return u.detail;return""}function Iz(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return!1;return f.some((l)=>l!==!1&&u[l]===!1)}function Z_(u,f,l,r,n={}){return{kind:u,method:l,url:vz(f),occurredAt:r.toISOString(),...n}}function O_(u,f){if(!u)return"请求失败";return`HTTP ${u}${f?` ${f}`:""}`}function lU(u){try{return{body:u?JSON.parse(u):null,parseError:""}}catch(f){return{body:{text:u},parseError:H_(f,"parse failed")}}}async function Eu(u,f={},l=0){let{failureFields:r=["ok"],strictJson:n=!1,retryInvalidJson:i=0,retryDelayMs:y=120,invalidJsonPrefix:_="服务返回了无效 JSON",invalidJsonPreview:$=!1,responsePreviewLength:A=500,...c}=f,j=eJ(c),F=new Date,U;try{U=await fetch(u,uU(c))}catch(w){let J=H_(w,"网络请求失败");throw new Bi(J,Z_("network",u,j,F,{upstreamMessage:J}))}let Q=await U.text(),L=lU(Q);if(L.parseError){if(n&&j==="GET"&&l=300)?O_(u.meta.status,u.meta.statusText):"应用请求失败",i=u.meta.status?O_(u.meta.status):"",y=($)=>!$||$===n||$===i,_=!y(u.message)?u.message:y(u.meta.upstreamMessage)?"":u.meta.upstreamMessage||"";return{title:n,message:_,status:u.meta.status,statusText:u.meta.statusText,method:u.meta.method,url:u.meta.url,occurredAt:gz(u.meta.occurredAt),responsePreview:u.meta.responsePreview,parseError:u.meta.parseError,structured:!0}}let r=H_(u,f).split(/\r?\n/u);return{title:r[0]||f,message:r.slice(1).join(` +`),structured:r.length>1}}function sz(u,f="操作失败"){let l=q5(u,f),r=[l.title];if(l.message)r.push(`原因: ${l.message}`);if(l.method||l.url)r.push(`请求: ${[l.method,l.url].filter(Boolean).join(" ")}`);if(l.status)r.push(`状态: ${O_(l.status,l.statusText)}`);if(l.occurredAt)r.push(`时间: ${l.occurredAt}`);if(l.parseError)r.push(`解析错误: ${l.parseError}`);if(l.responsePreview&&l.responsePreview!==l.message)r.push(`响应预览: ${l.responsePreview}`);return r.filter(Boolean).join(` +`)}function Zu(u,f="操作失败"){return nU(u)?sz(u,f):H_(u,f)}var iU=Pu(Qf(),1);var Wn=iU.default.createElement;function B_(u,f){return f?[Wn("dt",{key:`${u}-label`},u),Wn("dd",{key:u},f)]:null}function yf({error:u,wide:f=!1,fallback:l="操作失败",className:r=""}){if(!u)return null;let n=q5(u,l),i=[B_("请求",[n.method,n.url].filter(Boolean).join(" ")),B_("状态",n.status?`HTTP ${n.status}${n.statusText?` ${n.statusText}`:""}`:""),B_("时间",n.occurredAt),B_("解析错误",n.parseError),B_("响应预览",n.responsePreview)].filter(Boolean);return Wn("div",{className:`form-error unidesk-error${f?" wide":""}${r?` ${r}`:""}`,role:"alert","data-testid":"unidesk-error"},Wn("div",{className:"unidesk-error-title"},Wn("strong",null,n.title),n.status?Wn("span",{className:"unidesk-error-code"},`HTTP ${n.status}`):null),n.message?Wn("pre",{className:"unidesk-error-message"},n.message):null,i.length>0?Wn("dl",{className:"unidesk-error-details"},i):null)}var n0=Pu(Qf(),1),yU=n0.default.createContext(null);function _U({children:u}){let[f,l]=n0.default.useState([]),[r,n]=n0.default.useState(Date.now()),i=n0.default.useCallback((j,F)=>{let Q={id:`notif_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:j,message:F,timestamp:Date.now()};l((L)=>{let w=[...L,Q];if(w.length>50)return w.slice(-50);return w})},[]),y=n0.default.useCallback((j)=>{l((F)=>F.filter((U)=>U.id!==j))},[]),_=n0.default.useCallback(()=>{l([]),n(Date.now())},[]),$=n0.default.useMemo(()=>{return f.filter((j)=>j.timestamp>r).length},[f,r]),A=$>0,c={notifications:f,addNotification:i,removeNotification:y,clearNotifications:_,unreadCount:$,hasUnread:A};return az(yU.Provider,{value:c},u)}var az=n0.default.createElement;function Dl(){let u=n0.default.useContext(yU);if(!u)throw Error("useNotification must be used within NotificationProvider");return u}var R=Ot.default.createElement,{useEffect:Zt}=Ot.default,Vi=Ot.default.useState;function wl(u,f={}){return Eu(u,{failureFields:["ok","success"],...f})}function Xl(u,f){return`${u}/microservices/baidu-netdisk/proxy${f}`}function oz(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}function Ln(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=["B","KB","MB","GB","TB"],r=f,n=0;while(r>=1024&&n{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function Xi({title:u,text:f}){return R("div",{className:"empty-state"},R("strong",null,u),R("span",null,f))}function Yi({title:u,text:f,href:l,badge:r,testId:n}){return R("a",{className:"doc-link-card",href:l,target:"_blank",rel:"noreferrer","data-testid":n},R("span",null,r||"DOC"),R("strong",null,u),R("p",null,f),R("code",null,l))}function dz(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function ez(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function uT(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function fT(u){return Array.isArray(u?.files)?u.files:[]}function lT(u){return Array.isArray(u?.jobs)?u.jobs:[]}function rT(u,f){if(!u||u===f)return f;let l=u.replace(/\/+$/u,""),r=l.slice(0,l.lastIndexOf("/"))||f;return r.lengthx.id==="baidu-netdisk")||null,[n,i]=Vi({loading:!1,actionLoading:!1,error:"",message:"",health:null,account:null,files:null,transfers:null,logs:null,selfTest:null,refreshedAt:null}),[y,_]=Vi("/"),[$,A]=Vi(null),[c,j]=Vi(""),[F,U]=Vi({localPath:"sample.txt",remotePath:"/sample.txt"}),[Q,L]=Vi({fsId:"",localPath:"downloads/"}),{addNotification:w}=Dl(),J=n.health?.baidu?.appRoot||n.account?.rootPath||"/";Zt(()=>{U((x)=>{let fu=new Set(["/sample.txt","/apps/UniDeskBaiduNetdisk/sample.txt"]);if(x.remotePath&&!fu.has(x.remotePath))return x;let $u=N5(J,"sample.txt");return x.remotePath===$u?x:{...x,remotePath:$u}})},[J]);async function N(x=y){let $u=await wl(Xl(l,`/api/files?dir=${encodeURIComponent(x||J)}&limit=100`));i((tu)=>({...tu,files:$u}))}async function q(){let x=await wl(Xl(l,"/api/transfers?limit=80"));i((fu)=>({...fu,transfers:x}))}async function W(){if(!r)return;i((x)=>({...x,loading:!0,error:"",message:""}));try{let x=await wl(`${l}/microservices/baidu-netdisk/health`),fu=x?.baidu?.appRoot||J,$u=null,tu=null;if(x?.auth?.loggedIn){$u=await wl(Xl(l,"/api/account?refresh=1"));let qu=y&&y.startsWith(fu)?y:fu;_(qu),tu=await wl(Xl(l,`/api/files?dir=${encodeURIComponent(qu)}&limit=100`))}else _(fu);let ju=await wl(Xl(l,"/api/transfers?limit=80")),Gu=await wl(Xl(l,"/logs?limit=60"));i((qu)=>({...qu,loading:!1,health:x,account:$u?.account||null,files:tu,transfers:ju,logs:Gu,refreshedAt:new Date}))}catch(x){i((fu)=>({...fu,loading:!1,error:Zu(x,"百度网盘服务加载失败")}))}}async function z(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{let x=await wl(Xl(l,"/api/auth/device/start"),{method:"POST",body:{}});A(x.session||null),i((fu)=>({...fu,actionLoading:!1,message:"设备码已生成,请扫码授权"}))}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Zu(x,"创建设备码失败")}))}}async function Z(x=!1){if(!$?.id)return;if(x)i((fu)=>({...fu,actionLoading:!0,error:""}));try{let fu=await wl(Xl(l,`/api/auth/device/status?sessionId=${encodeURIComponent($.id)}`));if(A(fu.session||null),fu.session?.status==="succeeded")i(($u)=>({...$u,actionLoading:!1,message:"授权成功,正在刷新账号与文件列表"})),await W();else if(x)i(($u)=>({...$u,actionLoading:!1}))}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Zu(fu,"轮询登录状态失败")}))}}async function H(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{await wl(Xl(l,"/api/auth/logout"),{method:"POST",body:{}}),A(null),i((x)=>({...x,actionLoading:!1,account:null,files:null,message:"本地 token 已清除"})),await W()}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Zu(x,"退出登录失败")}))}}async function E(x){x.preventDefault();let fu=c.trim();if(!fu)return;i(($u)=>({...$u,actionLoading:!0,error:"",message:""}));try{await wl(Xl(l,"/api/folders"),{method:"POST",body:{path:N5(y,fu)}}),j(""),i(($u)=>({...$u,actionLoading:!1,message:"文件夹已创建"})),await N(y)}catch($u){i((tu)=>({...tu,actionLoading:!1,error:Zu($u,"创建文件夹失败")}))}}async function D(x){if(!x)return;i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await wl(Xl(l,"/api/files/manage"),{method:"POST",body:{opera:"delete",filelist:[{path:x}],async:1}}),i((fu)=>({...fu,actionLoading:!1,message:"删除任务已提交"})),await N(y)}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Zu(fu,"删除失败")}))}}async function h(x){x.preventDefault(),i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await wl(Xl(l,"/api/transfers/upload-from-path"),{method:"POST",body:F}),i((fu)=>({...fu,actionLoading:!1,message:"上传任务已入队"})),await q()}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Zu(fu,"上传任务创建失败")}))}}async function V(x){x.preventDefault(),i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await wl(Xl(l,"/api/transfers/download-to-path"),{method:"POST",body:Q}),i((fu)=>({...fu,actionLoading:!1,message:"下载任务已入队"})),await q()}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Zu(fu,"下载任务创建失败")}))}}async function Y(x,fu){i(($u)=>({...$u,actionLoading:!0,error:"",message:""}));try{await wl(Xl(l,`/api/transfers/${encodeURIComponent(x)}/${fu}`),{method:"POST",body:{}}),i(($u)=>({...$u,actionLoading:!1,message:fu==="cancel"?"已请求取消任务":"任务已重新入队"})),await q()}catch($u){i((tu)=>({...tu,actionLoading:!1,error:Zu($u,"任务操作失败")}))}}async function p(){i((x)=>({...x,actionLoading:!0,error:"",message:"正在运行上传/下载自测..."}));try{let x=await wl(Xl(l,"/api/self-test"),{method:"POST",body:{}});i((fu)=>({...fu,actionLoading:!1,selfTest:x,message:`上传/下载自测通过:${x.remotePath||""}`})),await N(y),await q()}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Zu(x,"上传/下载自测失败")}))}}if(Zt(()=>{if(!r)return;W();return},[r?.id,r?.runtime?.providerStatus]),Zt(()=>{if(!$?.id||$.status!=="pending")return;let x=window.setInterval(()=>void Z(!1),Math.max(5000,Number($.pollIntervalSeconds||5)*1000));return()=>window.clearInterval(x)},[$?.id,$?.status,$?.pollIntervalSeconds]),Zt(()=>{if(!r)return;let x=window.setInterval(()=>void q(),5000);return()=>window.clearInterval(x)},[r?.id]),!r)return R(Xi,{title:"Baidu Netdisk 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=baidu-netdisk"});let O=dz(r),m=uT(r),X=ez(r),v=n.health||{},T=n.account||v.auth?.account||null,S=v.auth||{},k=fT(n.files),I=lT(n.transfers),b=T?.quota||{},o=Boolean(S.loggedIn||T),g=Boolean(S.configured);return R("div",{className:"baidu-netdisk-page","data-testid":"baidu-netdisk-page"},R(q1,{title:"Baidu Netdisk 工作台",eyebrow:"Containerized Storage Gateway",loading:n.loading,actions:R("div",{className:"panel-actions"},R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-env-setup.md",target:"_blank",rel:"noreferrer","data-testid":"baidu-netdisk-config-doc-link"},"配置文档"),R("button",{type:"button",className:"ghost-btn",onClick:W,disabled:n.loading,"data-testid":"baidu-netdisk-refresh"},n.loading?"刷新中":"刷新"),R(B0,{title:"Baidu Netdisk 用户服务",data:r,onOpen:f,testId:"raw-baidu-netdisk-service"}))},R("div",{className:"baidu-netdisk-hero"},R("div",null,R("div",{className:"node-version-line"},R(Q1,{status:O.providerStatus==="online"?"online":"warn"},O.providerStatus||"unknown"),R("span",null,r.providerId),R(Q1,{status:X.public?"warn":"private"},X.public?"公网暴露":"仅 UniDesk frontend 代理访问")),R("p",{className:"muted paragraph"},r.description)),R("div",{className:"microservice-ref-card"},R("span",null,"Repo"),R("strong",null,m.url||"--"),R("code",null,m.commitId||"--")),R("div",{className:"microservice-ref-card"},R("span",null,"Private Backend"),R("strong",null,`${X.nodeBindHost||"--"}:${X.nodePort||"--"}`),R("code",null,`${m.composeFile||"--"} / ${m.composeService||"--"}`))),R(yf,{error:n.error,wide:!0})),R("div",{className:"metric-grid"},R(Di,{label:"Health",value:v.ok?"OK":"--",hint:v.storage?.postgres||"postgres",tone:v.ok?"ok":"warn"}),R(Di,{label:"OAuth",value:g?"已配置":"待配置",hint:g?"client + secret + token key":"需要设置 UNIDESK_BAIDU_NETDISK_*",tone:g?"ok":"warn"}),R(Di,{label:"Login",value:o?"已登录":"未登录",hint:T?.username||"Device Code QR",tone:o?"ok":"warn"}),R(Di,{label:"Work Root",value:nT(J),hint:J}),R(Di,{label:"Quota",value:Ln(b.used),hint:b.total?`${b.usedPercent||0}% / ${Ln(b.total)}`:"授权后刷新"}),R(Di,{label:"Transfers",value:oz(I.length),hint:`running ${n.transfers?.counts?.running||0} / failed ${n.transfers?.counts?.failed||0}`})),R(q1,{title:"文件浏览器",eyebrow:y,className:"baidu-files-panel",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"ghost-btn",onClick:()=>{let x=rT(y,J);_(x),N(x)},disabled:!o||y===J},"上级"),R("button",{type:"button",className:"ghost-btn",onClick:()=>N(y),disabled:!o},"刷新文件"),R(B0,{title:"Baidu Files",data:n.files,onOpen:f,testId:"raw-baidu-files"}))},R("form",{className:"baidu-pathbar",onSubmit:(x)=>{x.preventDefault(),N(y)}},R("input",{value:y,onChange:(x)=>_(x.target.value),disabled:!o}),R("button",{type:"submit",className:"ghost-btn",disabled:!o},"打开路径")),R("form",{className:"baidu-pathbar",onSubmit:E},R("input",{value:c,onChange:(x)=>j(x.target.value),placeholder:"新文件夹名称",disabled:!o}),R("button",{type:"submit",className:"primary-btn",disabled:!o||!c.trim()},"新建文件夹")),!o?R(Xi,{title:"等待授权",text:"登录后通过 /api/files 读取工作目录文件列表"}):k.length===0?R(Xi,{title:"目录为空",text:"可以从 staging 目录上传文件或新建文件夹"}):R("div",{className:"table-wrap","data-testid":"baidu-netdisk-file-table"},R("table",null,R("thead",null,R("tr",null,R("th",null,"名称"),R("th",null,"类型"),R("th",null,"大小"),R("th",null,"修改时间"),R("th",null,"fs_id"),R("th",null,"操作"))),R("tbody",null,k.map((x)=>R("tr",{key:x.fsId||x.path},R("td",null,R("strong",null,x.serverFilename||x.path),R("code",null,x.path||"--")),R("td",null,R(Q1,{status:x.isDir?"queued":"private"},x.isDir?"DIR":"FILE")),R("td",null,x.isDir?"--":Ln(x.size)),R("td",null,x.serverMtime?Nu(x.serverMtime*1000):"--"),R("td",null,R("code",null,x.fsId||"--")),R("td",null,R("div",{className:"inline-actions"},x.isDir?R("button",{type:"button",className:"ghost-btn",onClick:()=>{_(x.path),N(x.path)}},"打开"):R("button",{type:"button",className:"ghost-btn",onClick:()=>L((fu)=>({...fu,fsId:x.fsId}))},"填入下载"),R("button",{type:"button",className:"ghost-btn",onClick:()=>D(x.path),disabled:n.actionLoading},"删除"))))))))),R("div",{className:"baidu-netdisk-grid"},R(q1,{title:"配置与文档",eyebrow:"Deployment References",className:"baidu-docs-panel",actions:R("div",{className:"panel-actions inline-actions"},R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-env-setup.md",target:"_blank",rel:"noreferrer"},"打开环境配置"),R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-user-service.md",target:"_blank",rel:"noreferrer"},"打开服务方案"))},R("p",{className:"muted paragraph"},g?"OAuth 运行时变量已配置;如需轮换密钥、迁移部署或排查代理边界,可直接打开下面的项目内文档。":"首次使用请先按环境变量配置文档填入百度应用 client id / secret,然后重建 baidu-netdisk 服务并刷新本页。"),R("div",{className:"baidu-doc-grid","data-testid":"baidu-netdisk-doc-links"},R(Yi,{title:"环境变量配置",text:"填写 UNIDESK_BAIDU_NETDISK_CLIENT_ID、CLIENT_SECRET、TOKEN_KEY,并执行重建与健康检查。",href:"/docs/issue/baidu-netdisk-env-setup.md",badge:"SETUP",testId:"baidu-netdisk-env-doc-card"}),R(Yi,{title:"服务方案与 API",text:"说明 OAuth Device Code、根目录工作区、staging 上传下载任务和后端 API 设计。",href:"/docs/issue/baidu-netdisk-user-service.md",badge:"DESIGN"}),R(Yi,{title:"用户服务安全边界",text:"查看 UniDesk microservice 私有代理、允许路径、frontendOnly 和密钥边界规则。",href:"/docs/reference/microservices.md",badge:"REF"}),R(Yi,{title:"部署与重建流程",text:"查看 server rebuild、Compose 编排、健康检查和交付验证的长期规则。",href:"/docs/reference/deployment.md",badge:"DEPLOY"}),R(Yi,{title:"CLI 验证命令",text:"查看 microservice health/proxy、server rebuild、job status 等命令入口。",href:"/docs/reference/cli.md",badge:"CLI"}),R(Yi,{title:"百度设备码模式",text:"打开百度官方 OAuth Device Code 文档,对照扫码登录和轮询参数。",href:"https://pan.baidu.com/union/doc/fl1x114ti",badge:"OFFICIAL"}))),R(q1,{title:"设备码登录",eyebrow:"OAuth Device Code",className:"baidu-login-panel",loading:n.actionLoading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"primary-btn",onClick:z,disabled:n.actionLoading||!g,"data-testid":"baidu-netdisk-start-login"},"生成二维码"),$?.id?R("button",{type:"button",className:"ghost-btn",onClick:()=>Z(!0),disabled:n.actionLoading},"检查状态"):null,o?R("button",{type:"button",className:"ghost-btn",onClick:H,disabled:n.actionLoading},"清除本地登录"):null,R(B0,{title:"Baidu Device Session",data:$||S.latestSession,onOpen:f,testId:"raw-baidu-device-session"}))},R("div",{className:"baidu-login-card","data-testid":"baidu-netdisk-login-card"},R("div",{className:"baidu-qr-frame"},$?.qrcodeUrl?R("img",{src:$.qrcodeUrl,alt:"百度网盘设备码授权二维码","data-testid":"baidu-netdisk-qrcode"}):R(Xi,{title:g?"等待二维码":"OAuth 未配置",text:g?"点击生成二维码后使用百度网盘或百度 App 扫码":"设置 client id、secret 和 token key 后重建服务"})),R("div",{className:"claudeqq-login-copy"},R("div",{className:"node-version-line"},R(Q1,{status:o?"online":$?.status==="pending"?"warn":"unknown"},o?"已登录":$?.status||"未开始"),R("span",null,$?.secondsRemaining!==void 0?`${$.secondsRemaining}s`:"--"),R("span",null,"scope basic,netdisk")),R("p",{className:"muted paragraph"},o?"access token / refresh token 已加密保存到 PostgreSQL;前端只看到脱敏登录态。":"后端使用百度 OAuth Device Code 轮询换取 token;二维码过期后重新生成即可。"),R("div",{className:"microservice-ref-card"},R("span",null,"User Code"),R("strong",null,$?.userCode||"--"),R("code",null,$?.verificationUrl||"https://openapi.baidu.com/device")),R("div",{className:"microservice-ref-card"},R("span",null,"Expires"),R("strong",null,$?.expiresAt?Nu($.expiresAt):"--"),R("code",null,$?.error||"no token exposed"))))),R(q1,{title:"账号与容量",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Account",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(B0,{title:"Baidu Account",data:T,onOpen:f,testId:"raw-baidu-account"}))},T?R("div",{className:"baidu-account-card"},R("div",{className:"node-version-line"},R(Q1,{status:"online"},"connected"),R("span",null,T.baiduUid||"--"),R("span",null,`VIP ${T.vipType??"--"}`)),R("h3",null,T.username||"Baidu Netdisk"),R("p",{className:"muted paragraph"},`工作目录固定在 ${T.rootPath||J};v1 上传/下载只读写容器 staging 目录,不把大文件字节流穿过 UniDesk proxy。`),R("div",{className:"quota-bar"},R("span",{style:{width:`${Math.max(0,Math.min(100,Number(b.usedPercent||0)))}%`}})),R("div",{className:"microservice-ref-card"},R("span",null,"Quota"),R("strong",null,`${Ln(b.used)} / ${Ln(b.total)}`),R("code",null,`${b.usedPercent||0}% used`))):R(Xi,{title:"尚未登录",text:"扫码授权后这里会显示账号、UID、会员状态和容量"})),R(q1,{title:"传输任务",eyebrow:"staging path jobs",className:"baidu-transfers-panel",loading:n.actionLoading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"primary-btn",onClick:p,disabled:!o||n.actionLoading,"data-testid":"baidu-netdisk-self-test"},"运行自测"),R("button",{type:"button",className:"ghost-btn",onClick:q},"刷新任务"),R(B0,{title:"Baidu Transfers",data:n.transfers,onOpen:f,testId:"raw-baidu-transfers"}))},R("div",{className:"baidu-transfer-forms"},R("form",{className:"stack-form",onSubmit:h,"data-testid":"baidu-upload-form"},R("label",null,"容器 staging 文件",R("input",{value:F.localPath,onChange:(x)=>U((fu)=>({...fu,localPath:x.target.value})),placeholder:"sample.txt"})),R("label",null,"百度网盘目标路径",R("input",{value:F.remotePath,onChange:(x)=>U((fu)=>({...fu,remotePath:x.target.value})),placeholder:N5(J,"sample.txt")})),R("button",{type:"submit",className:"primary-btn",disabled:!o||n.actionLoading},"上传 staging 文件")),R("form",{className:"stack-form",onSubmit:V,"data-testid":"baidu-download-form"},R("label",null,"文件 fs_id",R("input",{value:Q.fsId,onChange:(x)=>L((fu)=>({...fu,fsId:x.target.value})),placeholder:"从文件表填入"})),R("label",null,"保存到 staging 路径",R("input",{value:Q.localPath,onChange:(x)=>L((fu)=>({...fu,localPath:x.target.value})),placeholder:"downloads/"})),R("button",{type:"submit",className:"primary-btn",disabled:!o||!Q.fsId||n.actionLoading},"下载到 staging"))),n.selfTest?R("div",{className:"baidu-account-card","data-testid":"baidu-netdisk-self-test-result"},R("div",{className:"node-version-line"},R(Q1,{status:n.selfTest.ok?"online":"warn"},n.selfTest.ok?"self-test ok":"self-test"),R("span",null,Ln(n.selfTest.sizeBytes))),R("h3",null,n.selfTest.remotePath||"Baidu self-test"),R("div",{className:"microservice-ref-card"},R("span",null,"fs_id"),R("strong",null,n.selfTest.fsId||"--"),R("code",null,n.selfTest.downloadedPath||"--")),R("div",{className:"microservice-ref-card"},R("span",null,"MD5"),R("strong",null,n.selfTest.downloadedMd5||"--"),R("code",null,n.selfTest.expectedMd5||"--")),R(B0,{title:"Baidu Self Test",data:n.selfTest,onOpen:f,testId:"raw-baidu-self-test"})):null,I.length===0?R(Xi,{title:"暂无传输任务",text:"上传/下载任务会在后端容器内执行,避免大文件穿过 UniDesk proxy"}):R("div",{className:"table-wrap","data-testid":"baidu-transfer-table"},R("table",null,R("thead",null,R("tr",null,R("th",null,"状态"),R("th",null,"方向"),R("th",null,"路径"),R("th",null,"进度"),R("th",null,"时间"),R("th",null,"操作"))),R("tbody",null,I.map((x)=>R("tr",{key:x.id},R("td",null,R(Q1,{status:x.status},x.status)),R("td",null,x.direction),R("td",null,R("strong",null,x.remotePath||x.fsId||"--"),R("code",null,x.localPath||"--"),x.error?R("span",{className:"form-error"},x.error):null),R("td",null,R(iT,{percent:x.progressPercent}),R("span",{className:"muted"},`${Ln(x.bytesDone)} / ${Ln(x.sizeBytes)}`)),R("td",null,Nu(x.updatedAt)),R("td",null,R("div",{className:"inline-actions"},["queued","running"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>Y(x.id,"cancel")},"取消"):null,["failed","canceled"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>Y(x.id,"retry")},"重试"):null,R(B0,{title:`Transfer ${x.id}`,data:x,onOpen:f}))))))))),R(q1,{title:"安全与日志",eyebrow:"redacted diagnostics",className:"baidu-wide-panel",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(B0,{title:"Baidu Health",data:v,onOpen:f,testId:"raw-baidu-health"}),R(B0,{title:"Baidu Logs",data:n.logs,onOpen:f,testId:"raw-baidu-logs"}))},R("div",{className:"policy-grid"},R("article",null,R("b",null,"私有后端"),R("span",null,"4244 只在 Compose 网络 expose,浏览器经 UniDesk 同源代理访问")),R("article",null,R("b",null,"Token 加密"),R("span",null,"access/refresh token 使用 BAIDU_NETDISK_TOKEN_KEY 加密后写入 PostgreSQL")),R("article",null,R("b",null,"无浏览器大文件流"),R("span",null,"上传/下载以容器 staging 目录为边界,避免 proxy 文本通道传输大字节流"))))))}var Vt=Pu(Qf(),1);var a=Vt.default.createElement,{useEffect:yT}=Vt.default,Ht=Vt.default.useState,N1={label:"主用户私聊账号",userId:645275593};function W5(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}async function wn(u,f={}){return Eu(u,{failureFields:["ok","success"],...f})}async function _T(u){let f=await fetch(u,{credentials:"same-origin"}),l=await f.text();try{return l?JSON.parse(l):{ok:f.ok,status:f.status}}catch{return{ok:f.ok,status:f.status,text:l}}}function Bt({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return a("span",{className:`status-badge ${l}`},f||u||"unknown")}function Si({label:u,value:f,hint:l,tone:r}){return a("article",{className:`metric-card ${r||""}`},a("div",{className:"metric-label"},u),a("div",{className:"metric-value"},f),a("div",{className:"metric-hint"},l))}function pi({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return a("section",{className:`panel ${n||""}`},a("div",{className:"panel-head"},a("div",null,f?a("p",{className:"panel-eyebrow"},f):null,a(nf,{title:u,loading:i})),l?a("div",{className:"panel-actions"},l):null),a("div",{className:"panel-body"},r))}function V_({title:u,data:f,onOpen:l,testId:r}){return a("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function D_({title:u,text:f}){return a("div",{className:"empty-state"},a("strong",null,u),a("span",null,f))}function $T(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function tT(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function AT(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Kn(u,f){return`${u}/microservices/claudeqq/proxy${f}`}function cT(u){return Array.isArray(u?.events)?u.events.slice(0,80):[]}function jT(u){return Array.isArray(u?.subscriptions)?u.subscriptions.slice(0,50):[]}function FT(u){return Array.isArray(u?.messages)?u.messages.slice(0,30):[]}function tU(u){let f=u?.text??u?.message??u?.raw?.raw_message;if(typeof f!=="string")return"--";return f.length>180?`${f.slice(0,177)}...`:f}function AU(u){let f=u?.groupId??u?.group_id??(u?.message_type==="group"?u?.target_id:void 0),l=u?.userId??u?.user_id??(u?.message_type==="private"?u?.target_id:void 0);if(f)return`群 ${f}`;if(l)return`私聊 ${l}`;return"--"}function cU({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((T)=>T.id==="claudeqq")||null,[n,i]=Ht({loading:!1,qrLoading:!1,error:"",health:null,status:null,napcatLogin:null,napcatQrcode:null,qrcodeFetched:!1,qrcodeRefreshedAt:null,events:null,subscriptions:null,sent:null,refreshedAt:null}),[y,_]=Ht({targetType:"private",targetId:String(N1.userId),message:""}),[$,A]=Ht({name:"unidesk-callback",targetUrl:"",eventTypes:"message",secret:""}),[c,j]=Ht(""),{addNotification:F}=Dl();async function U(){if(!r)return;i((T)=>({...T,loading:!0,error:""}));try{let[T,S,k,I,b]=await Promise.all([_T(`${l}/microservices/claudeqq/health`),wn(Kn(l,"/api/server/status")),wn(Kn(l,"/api/events/recent?limit=60")),wn(Kn(l,"/api/events/subscriptions")),wn(Kn(l,"/api/messages/sent?limit=20"))]);if(i((o)=>({...o,loading:!1,error:"",health:T,status:S,events:k,subscriptions:I,sent:b,refreshedAt:new Date})),!n.qrcodeFetched)Q(!1)}catch(T){i((S)=>({...S,loading:!1,error:Zu(T,"ClaudeQQ 加载失败")}))}}async function Q(T=!0){if(!r)return;i((S)=>({...S,qrLoading:!0,error:T?"":S.error}));try{let S=await wn(Kn(l,"/api/napcat/login")),k=S?.napcat?.qrcode||S?.qrcode||null;i((I)=>({...I,qrLoading:!1,error:"",napcatLogin:S,napcatQrcode:k,qrcodeFetched:!0,qrcodeRefreshedAt:new Date}))}catch(S){i((k)=>({...k,qrLoading:!1,error:T||!k.napcatQrcode?Zu(S,"NapCat 二维码加载失败"):k.error}))}}async function L(T){T.preventDefault(),j("");let S=Number(y.targetId);if(!Number.isFinite(S)||S<=0||y.message.trim().length===0){i((k)=>({...k,error:"请填写 QQ 目标和消息内容"}));return}try{await wn(Kn(l,"/api/push/text"),{method:"POST",body:JSON.stringify({userId:y.targetType==="private"?S:void 0,groupId:y.targetType==="group"?S:void 0,message:y.message})});let k="消息推送请求已提交";_((I)=>({...I,targetType:"private",targetId:String(N1.userId),message:""})),j(k),F("success",k),await U()}catch(k){i((I)=>({...I,error:Zu(k,"发送失败")}))}}async function w(T){if(T.preventDefault(),j(""),$.targetUrl.trim().length===0){i((S)=>({...S,error:"请填写订阅回调 URL"}));return}try{await wn(Kn(l,"/api/events/subscriptions"),{method:"POST",body:JSON.stringify({name:$.name,targetUrl:$.targetUrl,eventTypes:$.eventTypes.split(",").map((k)=>k.trim()).filter(Boolean),secret:$.secret||void 0,enabled:!0})});let S="事件订阅已创建";j(S),F("success",S),await U()}catch(S){i((k)=>({...k,error:Zu(S,"订阅失败")}))}}async function J(T){if(!T)return;j("");try{await wn(Kn(l,`/api/events/subscriptions/${encodeURIComponent(T)}`),{method:"DELETE"});let S="事件订阅已删除";j(S),F("success",S),await U()}catch(S){i((k)=>({...k,error:Zu(S,"删除订阅失败")}))}}if(yT(()=>{if(!r)return;U();return},[r?.id,r?.runtime?.providerStatus]),!r)return a(D_,{title:"ClaudeQQ 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=claudeqq"});let N=$T(r),q=AT(r),W=tT(r),z=n.health||{},Z=n.status||{},H=n.napcatLogin||{},E=z.napcat||Z.napcat||{},D={...H.napcat||{},...E,qrcode:n.napcatQrcode||{},webui:E.webui||H.napcat?.webui},h=H.login||{},V=n.napcatQrcode||{},Y=cT(n.events),p=jT(n.subscriptions),O=FT(n.sent),m=Boolean(D.httpConnected||h.ready),X=String(D.loginState||h.state||(m?"logged_in":"unknown")),v=Boolean(V.available&&V.dataUrl);return a("div",{className:"claudeqq-page","data-testid":"claudeqq-page"},a(pi,{title:"ClaudeQQ 工作台",eyebrow:"D601 QQ Event Gateway",loading:n.loading,actions:a("div",{className:"panel-actions"},a("button",{type:"button",className:"ghost-btn",onClick:U,disabled:n.loading,"data-testid":"claudeqq-refresh-button"},n.loading?"刷新中":"刷新"),a(V_,{title:"ClaudeQQ 用户服务",data:r,onOpen:f,testId:"raw-claudeqq-service"}))},a("div",{className:"findjob-hero"},a("div",null,a("div",{className:"node-version-line"},a(Bt,{status:N.providerStatus==="online"?"online":"warn"},N.providerStatus||"unknown"),a("span",null,r.providerId),a("span",null,W.public?"公网暴露":"仅 UniDesk frontend 代理访问")),a("p",{className:"muted paragraph"},r.description)),a("div",{className:"microservice-ref-card"},a("span",null,"Repo"),a("strong",null,q.url||"--"),a("code",null,q.commitId||"--")),a("div",{className:"microservice-ref-card"},a("span",null,"D601 Docker"),a("strong",null,`${W.nodeBindHost||"--"}:${W.nodePort||"--"}`),a("code",null,`${q.composeFile||"--"} / ${q.composeService||"--"}`))),a(yf,{error:n.error,wide:!0})),a("div",{className:"metric-grid"},a(Si,{label:"Health",value:z.ok||z.status==="ok"?"OK":"--",hint:"D601 /health",tone:z.ok||z.status==="ok"?"ok":"warn"}),a(Si,{label:"NapCat HTTP",value:D.httpConnected||D.http?.connected?"OK":"离线",hint:`${D.httpHost||z.napcat?.httpHost||"--"}:${D.httpPort||z.napcat?.httpPort||"--"}`}),a(Si,{label:"NapCat WS",value:D.wsConnected||D.ws?.connected?"OK":"离线",hint:`${D.wsHost||z.napcat?.wsHost||"--"}:${D.wsPort||z.napcat?.wsPort||"--"}`}),a(Si,{label:"事件缓存",value:W5(n.events?.count??Y.length),hint:"recent QQ events"}),a(Si,{label:"订阅",value:W5(n.subscriptions?.count??p.length),hint:"webhook subscribers"}),a(Si,{label:"已发送",value:W5(n.sent?.count??O.length),hint:"sent message log"})),a("div",{className:"findjob-grid"},a(pi,{title:"NapCat 容器登录",eyebrow:"QR Login",className:"claudeqq-login-panel",loading:n.qrLoading,actions:a("div",{className:"panel-actions inline-actions"},a("button",{type:"button",className:"ghost-btn",onClick:()=>Q(!0),disabled:n.qrLoading,"data-testid":"claudeqq-napcat-refresh"},n.qrLoading?"刷新中":"手动刷新二维码"),a(V_,{title:"NapCat Login",data:n.napcatLogin,onOpen:f,testId:"raw-claudeqq-napcat-login"}))},a("div",{className:"claudeqq-login-card","data-testid":"claudeqq-napcat-login"},a("div",{className:"claudeqq-qr-frame"},v?a("img",{src:V.dataUrl,alt:"NapCat QQ 登录二维码","data-testid":"claudeqq-napcat-qrcode"}):a(D_,{title:"等待二维码",text:"NapCat 容器启动后会把登录二维码写入 cache/qrcode.png"})),a("div",{className:"claudeqq-login-copy"},a("div",{className:"node-version-line"},a(Bt,{status:m?"online":v?"warn":"unknown"},m?"已登录":v?"待扫码":"等待二维码"),a("span",null,X),a("span",null,"D601 containerized")),a("p",{className:"muted paragraph"},m?"NapCat 已登录,ClaudeQQ 可通过容器内 HTTP/WS 链路收发 QQ 消息。":"用手机 QQ 扫描二维码授权登录。二维码只在首次加载或手动刷新时更新,D601 的 NapCat 端口仍只绑定 127.0.0.1。"),a("div",{className:"microservice-ref-card"},a("span",null,"NapCat WebUI"),a("strong",null,D.webui?.url||"http://napcat:6099/webui"),a("code",null,"local-only / proxied QR login")),a("div",{className:"microservice-ref-card"},a("span",null,"QR Source"),a("strong",null,V.modifiedAt?Nu(V.modifiedAt):n.qrcodeRefreshedAt?Nu(n.qrcodeRefreshedAt):"--"),a("code",null,V.file||"/napcat/cache/qrcode.png"))))),a(pi,{title:"消息推送",eyebrow:"Push API"},a("div",{className:"microservice-ref-card"},a("span",null,N1.label),a("strong",null,String(N1.userId)),a("code",null,"private userId / 默认推送测试目标")),a("form",{className:"stack-form",onSubmit:L,"data-testid":"claudeqq-push-form"},a("label",null,"目标类型",a("select",{value:y.targetType,onChange:(T)=>_((S)=>({...S,targetType:T.target.value}))},a("option",{value:"private"},"私聊 userId"),a("option",{value:"group"},"群 groupId"))),a("label",null,"QQ ID",a("input",{value:y.targetId,onChange:(T)=>_((S)=>({...S,targetId:T.target.value})),placeholder:String(N1.userId)})),a("label",null,"消息内容",a("textarea",{value:y.message,onChange:(T)=>_((S)=>({...S,message:T.target.value})),rows:4,placeholder:"通过 ClaudeQQ 推送一条 QQ 消息"})),a("button",{type:"submit",className:"primary-btn"},"发送 QQ 消息")),a("p",{className:"muted paragraph"},`主 server 和其他用户服务可通过 UniDesk 同源代理调用 /api/push/text;当前人工推送测试默认使用 ${N1.label} ${N1.userId},不需要暴露 D601 后端端口。`)),a(pi,{title:"QQ 事件订阅",eyebrow:"Webhook Subscription",loading:n.loading},a("form",{className:"stack-form",onSubmit:w,"data-testid":"claudeqq-subscription-form"},a("label",null,"订阅名称",a("input",{value:$.name,onChange:(T)=>A((S)=>({...S,name:T.target.value}))})),a("label",null,"回调 URL",a("input",{value:$.targetUrl,onChange:(T)=>A((S)=>({...S,targetUrl:T.target.value})),placeholder:"http://host.docker.internal:18080/..."})),a("label",null,"事件类型",a("input",{value:$.eventTypes,onChange:(T)=>A((S)=>({...S,eventTypes:T.target.value})),placeholder:"message,notice"})),a("label",null,"签名密钥",a("input",{value:$.secret,onChange:(T)=>A((S)=>({...S,secret:T.target.value})),placeholder:"可选,生成 x-claudeqq-signature"})),a("button",{type:"submit",className:"primary-btn"},"创建订阅")),p.length===0?a(D_,{title:"暂无订阅",text:"可以为 main server 或其他用户服务注册 HTTP webhook"}):a("div",{className:"table-wrap","data-testid":"claudeqq-subscription-table"},a("table",null,a("thead",null,a("tr",null,a("th",null,"名称"),a("th",null,"状态"),a("th",null,"事件"),a("th",null,"回调"),a("th",null,"最近投递"),a("th",null,"操作"))),a("tbody",null,p.map((T)=>a("tr",{key:T.id},a("td",null,a("strong",null,T.name||T.id),a("code",null,T.id||"--")),a("td",null,a(Bt,{status:T.enabled?"online":"warn"},T.enabled?"enabled":"disabled")),a("td",null,Array.isArray(T.eventTypes)?T.eventTypes.join(", "):"message"),a("td",null,T.targetUrl||"--"),a("td",null,T.lastDelivery?`${T.lastDelivery.ok?"OK":"FAIL"} ${Nu(T.lastDelivery.at)}`:"--"),a("td",null,a("button",{type:"button",className:"ghost-btn",onClick:()=>J(T.id)},"删除"))))))),a("div",{className:"panel-actions inline-actions"},a(V_,{title:"ClaudeQQ Subscriptions",data:n.subscriptions,onOpen:f,testId:"raw-claudeqq-subscriptions"}))),a(pi,{title:"最近 QQ 事件",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Event Stream",loading:n.loading},Y.length===0?a(D_,{title:"暂无事件",text:"等待 NapCat WebSocket 上报 QQ 消息事件,或通过订阅 API 消费后续事件"}):a("div",{className:"table-wrap","data-testid":"claudeqq-event-list"},a("table",null,a("thead",null,a("tr",null,a("th",null,"时间"),a("th",null,"类型"),a("th",null,"会话"),a("th",null,"消息"),a("th",null,"ID"))),a("tbody",null,Y.map((T)=>a("tr",{key:T.id},a("td",null,Nu(T.receivedAt||T.timestamp)),a("td",null,a(Bt,{status:T.postType||T.eventType},T.postType||T.eventType||"--")),a("td",null,AU(T)),a("td",null,tU(T)),a("td",null,a("code",null,T.messageId||T.id||"--"))))))),a("div",{className:"panel-actions inline-actions"},a(V_,{title:"ClaudeQQ Events",data:n.events,onOpen:f,testId:"raw-claudeqq-events"}))),a(pi,{title:"已发送消息",eyebrow:`${O.length} Sent`,loading:n.loading},O.length===0?a(D_,{title:"暂无发送记录",text:"发送日志来自 ClaudeQQ bot_workspace/messages/sent_messages.jsonl"}):a("div",{className:"table-wrap"},a("table",null,a("thead",null,a("tr",null,a("th",null,"时间"),a("th",null,"目标"),a("th",null,"消息"),a("th",null,"结果"))),a("tbody",null,O.map((T,S)=>a("tr",{key:T.id||S},a("td",null,Nu(T.timestamp||T.sentAt||T.createdAt)),a("td",null,AU(T)),a("td",null,tU(T)),a("td",null,T.status||T.messageId||T.message_id||"--")))))),a("div",{className:"panel-actions inline-actions"},a(V_,{title:"ClaudeQQ Sent Messages",data:n.sent,onOpen:f,testId:"raw-claudeqq-sent"})))))}var R_=Pu(Qf(),1);var JU=Pu(Qf(),1),Uf=JU.default.createElement;function UU({markdown:u,className:f,testId:l}){let r=String(u??"").trimEnd(),n=["markdown-body",f].filter(Boolean).join(" ");return Uf("div",{className:n,"data-testid":l},QU(r,"md"))}function QU(u,f){let l=JT(u).split(` +`),r=[],n=0;while(n\s?/u.test(i)){let j=[];while(n\s?(.*)$/u);if(U!==null){j.push(U[1]),n+=1;continue}if(F.trim().length===0){j.push(""),n+=1;continue}break}r.push(Uf("blockquote",{key:`${f}-quote-${n}`},QU(j.join(` +`),`${f}-quote-${n}`)));continue}if(NU(l,n)){let j=n,F=X_(l[n]??""),U=X_(l[n+1]??"");n+=2;let Q=[];while(n0)Q.push(X_(l[n]??"")),n+=1;r.push(WT(F,U,Q,`${f}-table-${j}`));continue}let $=Xt(i);if($!==null){let j=n,F=$.ordered,U=$.start,Q=[];while(nqT(w,`${f}-list-${j}-${J}`))));continue}let A=n,c=[];while(n0&&!QT(l,n))c.push(l[n].trim()),n+=1;if(c.length===0)c.push(i.trim()),n+=1;r.push(Uf("p",{key:`${f}-p-${A}`},i0(c.join(` +`),`${f}-p-${A}`)))}return r}function JT(u){return String(u||"").replace(/\r\n/gu,` `).replace(/\r/gu,` -`).trimEnd()}function UU(u){let f=u.match(/^\s*(```+|~~~+)\s*([A-Za-z0-9_-]+)?\s*$/u);if(f===null)return null;let l=f[1];return{marker:l.startsWith("`")?"`":"~",length:l.length,language:f[2]||""}}function FT(u,f){let l=u.trim();return l.length>=f.length&&l.split("").every((r)=>r===f.marker)}function q5(u){return/^(?: {4}|\t)/u.test(u)}function AU(u,f,l){let r=f.trim().length>0?`language-${WT(f)}`:void 0;return Uf("pre",{key:l,className:"markdown-code-block"},Uf("code",{className:r},u))}function JT(u,f){let l=u[f]??"";if(l.trim().length===0)return!0;return UU(l)!==null||q5(l)||/^(#{1,6})\s+.+$/u.test(l)||/^\s*(?:---+|\*\*\*+|___+)\s*$/u.test(l)||/^\s*>\s?/u.test(l)||QU(u,f)||Dt(l)!==null}function Dt(u){let f=u.match(/^\s{0,3}[-*+]\s+(.+)$/u);if(f!==null)return{ordered:!1,text:f[1]};let l=u.match(/^\s{0,3}(\d+)[.)]\s+(.+)$/u);if(l!==null)return{ordered:!0,start:Number(l[1]),text:l[2]};return null}function UT(u,f){let l=u.match(/^\[([ xX])\]\s+(.+)$/u);if(l!==null){let r=l[1].toLowerCase()==="x";return Uf("li",{key:f,className:"task-list-item"},Uf("input",{type:"checkbox",checked:r,readOnly:!0,tabIndex:-1}),Uf("span",null,n0(l[2],`${f}-task`)))}return Uf("li",{key:f},n0(u,f))}function QU(u,f){let l=u[f]??"",r=u[f+1]??"";if(!l.includes("|")||!r.includes("|"))return!1;let n=B_(l),i=B_(r);return n.length>1&&i.length===n.length&&i.every((y)=>/^:?-{3,}:?$/u.test(y.trim()))}function B_(u){let f=u.trim();if(f.startsWith("|"))f=f.slice(1);if(f.endsWith("|"))f=f.slice(0,-1);return f.split("|").map((l)=>l.trim())}function QT(u){let f=u.trim();if(f.startsWith(":")&&f.endsWith(":"))return"center";if(f.endsWith(":"))return"right";if(f.startsWith(":"))return"left";return}function qT(u,f,l,r){let n=f.map(QT);return Uf("div",{key:r,className:"markdown-table-wrap"},Uf("table",null,Uf("thead",null,Uf("tr",null,u.map((i,y)=>Uf("th",{key:`${r}-h-${y}`,style:n[y]?{textAlign:n[y]}:void 0},n0(i,`${r}-h-${y}`))))),Uf("tbody",null,l.map((i,y)=>Uf("tr",{key:`${r}-r-${y}`},u.map((_,$)=>Uf("td",{key:`${r}-r-${y}-${$}`,style:n[$]?{textAlign:n[$]}:void 0},n0(i[$]||"",`${r}-r-${y}-${$}`))))))))}function n0(u,f,l={}){let r=[],n=/`([^`\n]+)`|\[([^\]\n]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)|(https?:\/\/[^\s<>)]+)|\*\*([^*\n]+)\*\*|__([^_\n]+)__|~~([^~\n]+)~~|\*([^*\n]+)\*|_([^_\n]+)_/gu,i=l.linkify!==!1,y=0,_=0;for(let $ of u.matchAll(n)){let A=$[0],c=$.index??0;Vt(r,u.slice(y,c),`${f}-text-${_}`),y=c+A.length;let j=`${f}-inline-${_}`;if(_+=1,$[1]!==void 0){r.push(Uf("code",{key:j},$[1]));continue}if($[2]!==void 0&&$[3]!==void 0){if(!i){Vt(r,A,`${j}-literal`);continue}r.push(cU($[2],$[3],j));continue}if($[4]!==void 0){if(!i){Vt(r,A,`${j}-literal`);continue}r.push(cU($[4],$[4],j));continue}let F=$[5]??$[6];if(F!==void 0){r.push(Uf("strong",{key:j},n0(F,`${j}-strong`)));continue}if($[7]!==void 0){r.push(Uf("del",{key:j},n0($[7],`${j}-del`)));continue}let U=$[8]??$[9];if(U!==void 0)r.push(Uf("em",{key:j},n0(U,`${j}-em`)))}return Vt(r,u.slice(y),`${f}-text-tail`),r}function Vt(u,f,l){if(f.length===0)return;f.split(` -`).forEach((n,i)=>{if(i>0)u.push(Uf("br",{key:`${l}-br-${i}`}));if(n.length>0)u.push(n)})}function cU(u,f,l){let r=NT(f);if(r===null)return Uf("span",{key:l},u);let n=/^(?:https?:|mailto:)/iu.test(r);return Uf("a",{key:l,href:r,target:n?"_blank":void 0,rel:n?"noreferrer":void 0},n0(u,`${l}-label`,{linkify:!1}))}function NT(u){let f=String(u||"").trim();if(/^(?:https?:|mailto:)/iu.test(f))return f;if(f.startsWith("/")&&!f.startsWith("//"))return f;if(f.startsWith("#"))return f;return null}function WT(u){return String(u||"").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-").replace(/^-+|-+$/gu,"")||"text"}var G5=Pu(qf(),1);var Su=G5.default.createElement,{useEffect:LT,useRef:qU}=G5.default;function wT(u,f){return XU(u.toTrace(f))}function KT(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.floor(f/1000),r=Math.floor(l/3600),n=Math.floor(l%3600/60),i=l%60;if(r>0)return`${r}h ${String(n).padStart(2,"0")}m`;if(n>0)return`${n}m ${String(i).padStart(2,"0")}s`;return`${i}s`}function Rr(u){let f=Number(u);return Number.isFinite(f)&&f>=0?f:null}function mi(u,f=180){let l=String(u||"").replace(/\s+/gu," ").trim();return l.length>f?`${l.slice(0,f-1)}…`:l}function GT(u){if(!u)return 0;return u.split(/\r?\n/u).length}function L5(u){return{ran:"Ran",explored:"Explored",edited:"Edited",toolGroup:"Tool calls",plan:"Plan",message:"Message",system:"System",error:"Error"}[u]||"Message"}function w5(u){let f=Number(u||0);return Number.isFinite(f)&&f>0?`… +${Math.floor(f)} lines`:""}function zT(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,Number(l?.seq??0)),0)}function NU(u){return["explored","edited","ran"].includes(String(u?.kind||""))}function EU(u){let f={read:0,edit:0,run:0};for(let l of u){let r=String(l?.kind||"");if(r==="explored")f.read+=1;else if(r==="edited")f.edit+=1;else if(r==="ran")f.run+=1}return f}function ZU(u){let f=EU(u);return`${f.read} read, ${f.edit} edit, ${f.run} run`}function OU(u){return u.replace(/^['"`([{<]+/u,"").replace(/['"`)\]}>.,;:]+$/u,"").replace(/:\d+(?::\d+)?$/u,"").trim()}function WU(u){let l=String(u||"").match(/(?:~|\.{1,2}|\/)?(?:[A-Za-z0-9_.@+-]+\/)+[A-Za-z0-9_.@+-]+|[A-Za-z0-9_.@+-]+\.(?:c|cc|cpp|h|hpp|js|jsx|ts|tsx|json|md|py|sh|toml|ya?ml|txt|log|lock)/gu)||[],r=[];for(let n of l){let i=OU(n);if(i.length<2||i.includes("..."))continue;if(/^(http|https|status|method)$/iu.test(i))continue;if(!r.includes(i))r.push(i)}return r}function N5(u,f=4){if(u.length===0)return"--";let l=u.slice(0,f).join(", ");return u.length>f?`${l} +${u.length-f}`:l}function LU(u){let f="";for(let l of u){if(l.length===0)continue;if(f.length>0&&!f.endsWith(` +`).trimEnd()}function qU(u){let f=u.match(/^\s*(```+|~~~+)\s*([A-Za-z0-9_-]+)?\s*$/u);if(f===null)return null;let l=f[1];return{marker:l.startsWith("`")?"`":"~",length:l.length,language:f[2]||""}}function UT(u,f){let l=u.trim();return l.length>=f.length&&l.split("").every((r)=>r===f.marker)}function L5(u){return/^(?: {4}|\t)/u.test(u)}function jU(u,f,l){let r=f.trim().length>0?`language-${wT(f)}`:void 0;return Uf("pre",{key:l,className:"markdown-code-block"},Uf("code",{className:r},u))}function QT(u,f){let l=u[f]??"";if(l.trim().length===0)return!0;return qU(l)!==null||L5(l)||/^(#{1,6})\s+.+$/u.test(l)||/^\s*(?:---+|\*\*\*+|___+)\s*$/u.test(l)||/^\s*>\s?/u.test(l)||NU(u,f)||Xt(l)!==null}function Xt(u){let f=u.match(/^\s{0,3}[-*+]\s+(.+)$/u);if(f!==null)return{ordered:!1,text:f[1]};let l=u.match(/^\s{0,3}(\d+)[.)]\s+(.+)$/u);if(l!==null)return{ordered:!0,start:Number(l[1]),text:l[2]};return null}function qT(u,f){let l=u.match(/^\[([ xX])\]\s+(.+)$/u);if(l!==null){let r=l[1].toLowerCase()==="x";return Uf("li",{key:f,className:"task-list-item"},Uf("input",{type:"checkbox",checked:r,readOnly:!0,tabIndex:-1}),Uf("span",null,i0(l[2],`${f}-task`)))}return Uf("li",{key:f},i0(u,f))}function NU(u,f){let l=u[f]??"",r=u[f+1]??"";if(!l.includes("|")||!r.includes("|"))return!1;let n=X_(l),i=X_(r);return n.length>1&&i.length===n.length&&i.every((y)=>/^:?-{3,}:?$/u.test(y.trim()))}function X_(u){let f=u.trim();if(f.startsWith("|"))f=f.slice(1);if(f.endsWith("|"))f=f.slice(0,-1);return f.split("|").map((l)=>l.trim())}function NT(u){let f=u.trim();if(f.startsWith(":")&&f.endsWith(":"))return"center";if(f.endsWith(":"))return"right";if(f.startsWith(":"))return"left";return}function WT(u,f,l,r){let n=f.map(NT);return Uf("div",{key:r,className:"markdown-table-wrap"},Uf("table",null,Uf("thead",null,Uf("tr",null,u.map((i,y)=>Uf("th",{key:`${r}-h-${y}`,style:n[y]?{textAlign:n[y]}:void 0},i0(i,`${r}-h-${y}`))))),Uf("tbody",null,l.map((i,y)=>Uf("tr",{key:`${r}-r-${y}`},u.map((_,$)=>Uf("td",{key:`${r}-r-${y}-${$}`,style:n[$]?{textAlign:n[$]}:void 0},i0(i[$]||"",`${r}-r-${y}-${$}`))))))))}function i0(u,f,l={}){let r=[],n=/`([^`\n]+)`|\[([^\]\n]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)|(https?:\/\/[^\s<>)]+)|\*\*([^*\n]+)\*\*|__([^_\n]+)__|~~([^~\n]+)~~|\*([^*\n]+)\*|_([^_\n]+)_/gu,i=l.linkify!==!1,y=0,_=0;for(let $ of u.matchAll(n)){let A=$[0],c=$.index??0;Dt(r,u.slice(y,c),`${f}-text-${_}`),y=c+A.length;let j=`${f}-inline-${_}`;if(_+=1,$[1]!==void 0){r.push(Uf("code",{key:j},$[1]));continue}if($[2]!==void 0&&$[3]!==void 0){if(!i){Dt(r,A,`${j}-literal`);continue}r.push(FU($[2],$[3],j));continue}if($[4]!==void 0){if(!i){Dt(r,A,`${j}-literal`);continue}r.push(FU($[4],$[4],j));continue}let F=$[5]??$[6];if(F!==void 0){r.push(Uf("strong",{key:j},i0(F,`${j}-strong`)));continue}if($[7]!==void 0){r.push(Uf("del",{key:j},i0($[7],`${j}-del`)));continue}let U=$[8]??$[9];if(U!==void 0)r.push(Uf("em",{key:j},i0(U,`${j}-em`)))}return Dt(r,u.slice(y),`${f}-text-tail`),r}function Dt(u,f,l){if(f.length===0)return;f.split(` +`).forEach((n,i)=>{if(i>0)u.push(Uf("br",{key:`${l}-br-${i}`}));if(n.length>0)u.push(n)})}function FU(u,f,l){let r=LT(f);if(r===null)return Uf("span",{key:l},u);let n=/^(?:https?:|mailto:)/iu.test(r);return Uf("a",{key:l,href:r,target:n?"_blank":void 0,rel:n?"noreferrer":void 0},i0(u,`${l}-label`,{linkify:!1}))}function LT(u){let f=String(u||"").trim();if(/^(?:https?:|mailto:)/iu.test(f))return f;if(f.startsWith("/")&&!f.startsWith("//"))return f;if(f.startsWith("#"))return f;return null}function wT(u){return String(u||"").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-").replace(/^-+|-+$/gu,"")||"text"}var E5=Pu(Qf(),1);var Xu=E5.default.createElement,{useEffect:KT,useRef:WU}=E5.default;function GT(u,f){return SU(u.toTrace(f))}function zT(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.floor(f/1000),r=Math.floor(l/3600),n=Math.floor(l%3600/60),i=l%60;if(r>0)return`${r}h ${String(n).padStart(2,"0")}m`;if(n>0)return`${n}m ${String(i).padStart(2,"0")}s`;return`${i}s`}function Rr(u){let f=Number(u);return Number.isFinite(f)&&f>=0?f:null}function Pi(u,f=180){let l=String(u||"").replace(/\s+/gu," ").trim();return l.length>f?`${l.slice(0,f-1)}…`:l}function TT(u){if(!u)return 0;return u.split(/\r?\n/u).length}function G5(u){return{ran:"Ran",explored:"Explored",edited:"Edited",toolGroup:"Tool calls",plan:"Plan",message:"Message",system:"System",error:"Error"}[u]||"Message"}function z5(u){let f=Number(u||0);return Number.isFinite(f)&&f>0?`… +${Math.floor(f)} lines`:""}function ET(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,Number(l?.seq??0)),0)}function LU(u){return["explored","edited","ran"].includes(String(u?.kind||""))}function OU(u){let f={read:0,edit:0,run:0};for(let l of u){let r=String(l?.kind||"");if(r==="explored")f.read+=1;else if(r==="edited")f.edit+=1;else if(r==="ran")f.run+=1}return f}function HU(u){let f=OU(u);return`${f.read} read, ${f.edit} edit, ${f.run} run`}function BU(u){return u.replace(/^['"`([{<]+/u,"").replace(/['"`)\]}>.,;:]+$/u,"").replace(/:\d+(?::\d+)?$/u,"").trim()}function wU(u){let l=String(u||"").match(/(?:~|\.{1,2}|\/)?(?:[A-Za-z0-9_.@+-]+\/)+[A-Za-z0-9_.@+-]+|[A-Za-z0-9_.@+-]+\.(?:c|cc|cpp|h|hpp|js|jsx|ts|tsx|json|md|py|sh|toml|ya?ml|txt|log|lock)/gu)||[],r=[];for(let n of l){let i=BU(n);if(i.length<2||i.includes("..."))continue;if(/^(http|https|status|method)$/iu.test(i))continue;if(!r.includes(i))r.push(i)}return r}function w5(u,f=4){if(u.length===0)return"--";let l=u.slice(0,f).join(", ");return u.length>f?`${l} +${u.length-f}`:l}function KU(u){let f="";for(let l of u){if(l.length===0)continue;if(f.length>0&&!f.endsWith(` `)&&!l.startsWith(` `))f+=` -`;f+=l}return f}function HU(u){let f=String(u||"").replace(/\r\n/gu,` +`;f+=l}return f}function VU(u){let f=String(u||"").replace(/\r\n/gu,` `).replace(/\r/gu,` `).trimEnd();return f.length>0?f.split(` -`):[]}function K5(u){let f=String(u.status||"").trim();if(f.length>0)return f;let l=String(u.bodyPreview||"");return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(l)?.[1]||"item/fileChange"}function TT(u){let f=String(u.bodyPreview||"");return/file changes status=([A-Za-z0-9_-]+)/u.exec(f)?.[1]}function ET(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function BU(u){if(String(u.kind||"")!=="edited")return!1;let f=String(u.status||""),l=String(u.title||""),r=String(u.bodyPreview||""),n=String(u.commandPreview||"");if(l==="Edited files")return!0;if(/^item\/fileChange\//u.test(f))return!0;if((f==="item/started"||f==="item/completed")&&/file changes status=/u.test(r))return!0;if(/^Success\. Updated the following files:/mu.test(r))return!0;if(/^diff --git /mu.test(r))return!0;return/^([AMDRCU?]{1,2})\s+\S+/mu.test(r)||n.length>0&&Yt(r).length>0}function pi(u){return OU(String(u||"").replace(/^[ab]\//u,"").trim())}function z5(u){let f=/^([AMDRCU?]{1,2})\s+(.+)$/u.exec(u);if(!f)return null;let l=pi(f[2]||"");return l.length>0?{status:f[1]||"M",path:l}:null}function T5(u){let f=/^\*\*\*\s+(Add|Update|Delete)\s+File:\s+(.+)$/u.exec(u);if(f){let r=f[1]==="Add"?"A":f[1]==="Delete"?"D":"M",n=pi(f[2]||"");return n.length>0?{status:r,path:n}:null}let l=/^\*\*\*\s+Move to:\s+(.+)$/u.exec(u);if(l){let r=pi(l[1]||"");return r.length>0?{status:"R",path:r}:null}return null}function Yt(u){let f=[],l=(n,i)=>{let y=pi(i);if(y.length===0||y==="/dev/null")return;let _=f.find(($)=>$.path===y);if(_){if(_.status==="M"&&n!=="M")_.status=n;return}f.push({status:n,path:y})},r="";for(let n of HU(u)){let i=z5(n)||T5(n);if(i!==null){l(i.status,i.path),r=i.path;continue}let y=/^diff --git a\/(.+?) b\/(.+)$/u.exec(n);if(y){let j=y[2]||y[1]||"";l("M",j),r=pi(j);continue}let _=/^\+\+\+ b\/(.+)$/u.exec(n);if(_&&_[1]!=="/dev/null"){l("M",_[1]||""),r=pi(_[1]||"");continue}if(/^new file mode /u.exec(n)&&r)l("A",r);if(/^deleted file mode /u.exec(n)&&r)l("D",r);let c=/^rename to (.+)$/u.exec(n);if(c)l("R",c[1]||"")}return f}function ZT(u){if(z5(u)!==null||T5(u)!==null)return"file";if(/^(diff --git |index |--- |\+\+\+ |\*\*\* Begin Patch|\*\*\* End Patch)/u.test(u))return"meta";if(/^@@ /u.test(u))return"hunk";if(/^\+/u.test(u))return"add";if(/^-/u.test(u))return"del";if(/^(Success\.|No changes|Updated\b|Created\b|Deleted\b|Added\s+\d+\s+lines?|Wrote\s+\d+\s+lines?|Read\s+\d+\s+files?|\.\.\.\[patch content truncated)/iu.test(u))return"note";return"context"}function E5(u){return HU(u).map((f)=>{let l=z5(f)||T5(f);if(l!==null)return{text:f,kind:"file",path:l.path,status:l.status};return{text:f,kind:ZT(f)}})}function OT(u){return u.reduce((f,l)=>{if(l.kind==="add")f.added+=1;else if(l.kind==="del")f.removed+=1;return f},{added:0,removed:0})}function wU(u,f){return`${f} ${u} line${u===1?"":"s"}`}function HT(u,f){let l=[];if(u>0)l.push(wU(u,"Added"));if(f>0)l.push(wU(f,"removed"));return l.join(", ")}function BT(u){for(let l=u.length-1;l>=0;l-=1){let r=String(u[l]?.status||"").trim();if(r.length>0)return r}let f=String(u[u.length-1]?.method||"").trim();if(f==="item/fileChange/outputDelta")return"updated";if(f==="item/started")return"started";if(f==="item/completed")return"completed";return f.replace(/^item\//u,"")||"changed"}function VT(u){return`${u} file${u===1?"":"s"}`}function VU(u){let f=u.length>0?u:[],l=LU(f.map((F)=>String(F.bodyPreview||""))),n=LU(f.map((F)=>String(F.bodyPreview||"")).filter((F)=>F.trim().length>0&&!ET(F)))||l,i=Yt(n||l),y=f.map((F)=>({method:K5(F),status:TT(F),at:F.at})),_=E5(n||l),$=OT(_),A=HT($.added,$.removed),c=i.length>0?VT(i.length):"",j=A.length>0?`${A}${c?` in ${c}`:""}`:i.length>0?c:mi(n||l||"File changes",72);return{status:BT(y),summary:j,files:i,stages:y,lines:_,addedLines:$.added,removedLines:$.removed,rawText:l}}function DT(u){let f=u[0],l=u[u.length-1]||f,r=VU(u);return{...f,seq:Number.isFinite(Number(l?.seq))?Number(l?.seq):Number(f?.seq??0),at:l?.at||f?.at,title:r.files.length>0?`Edited ${r.summary}`:"Edited files",status:r.status,commandPreview:"",commandOmittedLines:void 0,bodyPreview:r.rawText,bodyOmittedLines:u.reduce((n,i)=>n+Number(i.bodyOmittedLines||0),0)||void 0,rawSeqs:u.flatMap((n)=>Array.isArray(n?.rawSeqs)?n.rawSeqs:[n?.seq]).filter((n)=>n!==void 0),editObservation:r}}function XT(u){let f=Array.isArray(u)?u:[],l=[],r=[],n=()=>{if(r.length===0)return;l.push(DT(r)),r=[]};for(let i of f){if(BU(i)){if(K5(i)==="item/started"&&r.length>0)n();if(r.push(i),K5(i)==="item/completed")n();continue}n(),l.push(i)}return n(),l}function DU(u){let f=[],l=[],r=[],n=(A,c)=>{for(let j of c)if(!A.includes(j))A.push(j)};for(let A of u){let c=String(A?.kind||""),j=[A?.commandPreview,A?.bodyPreview,A?.title].map((F)=>String(F||"")).join(` -`);if(c==="explored")n(f,WU(j));else if(c==="edited")n(l,WU(j));else if(c==="ran"){let F=String(A?.commandPreview||A?.title||"").trim();if(F.length>0&&!r.includes(F))r.push(mi(F,90))}}let i=u.map((A)=>Date.parse(String(A?.at||""))).filter((A)=>Number.isFinite(A)),y=i.length>=2?Math.max(0,Math.max(...i)-Math.min(...i)):0,_=u.reduce((A,c)=>A+(Rr(c?.durationMs)??Rr(c?.elapsedMs)??0),0),$=y>0?y:_;return{readFiles:f,editedFiles:l,runCommands:r,durationLabel:KT($)}}function YT(u,f=3){let l=Array.isArray(u)?u:[],r=[],n=[],i=Math.max(0,f),y=new Set;for(let $=l.length-1;$>=0&&i>0;$-=1){let A=l[$];if(!NU(A))continue;y.add(A),i-=1}let _=()=>{if(n.length>=2){let $=EU(n);r.push({seq:Number(n[0]?.seq??0),at:n[0]?.at||n.at(-1)?.at,kind:"toolGroup",title:ZU(n),status:`${n.length} calls`,items:n,counts:$,digest:DU(n),rawSeqs:n.flatMap((A)=>Array.isArray(A?.rawSeqs)?A.rawSeqs:[A?.seq]).filter((A)=>A!==void 0)})}else r.push(...n);n=[]};for(let $ of l){if(NU($)&&!y.has($)){n.push($);continue}_(),r.push($)}return _(),r}function XU(u){return(Array.isArray(u)?u:[]).map((f,l)=>({...f,seq:Number.isFinite(Number(f?.seq))?Number(f.seq):l+1,kind:String(f?.kind||"message"),at:f?.at===void 0?void 0:String(f.at),durationMs:Rr(f?.durationMs)??void 0,title:f?.title===void 0?void 0:String(f.title),status:f?.status===void 0?void 0:String(f.status)}))}function V_(u){let f=Rr(u?.state?.time?.start)??Rr(u?.time?.start),l=Rr(u?.state?.time?.end)??Rr(u?.time?.end);return Rr(u?.durationMs)??Rr(u?.elapsedMs)??Rr(u?.timing?.durationMs)??Rr(u?.metadata?.durationMs)??(f!==null&&l!==null&&l>=f?l-f:null)??void 0}function D_(u,f){return u?.createdAt||u?.updatedAt||u?.completedAt||f||void 0}function W5(u,f){return u?.id||u?.messageId||f}function ST(u,f=1200){if(typeof u==="string")return u;if(u===void 0||u===null)return"";try{return mi(JSON.stringify(u),f)}catch{return mi(String(u),f)}}function YU(u,f,l){if(typeof u?.metadata?.diff==="string"&&u.metadata.diff.length>0)return u.metadata.diff;if(typeof u?.metadata?.filediff?.patch==="string"&&u.metadata.filediff.patch.length>0)return u.metadata.filediff.patch;if(typeof u?.output==="string"&&u.output.length>0)return u.output;if(typeof u?.result==="string"&&u.result.length>0)return u.result;if(typeof f?.output==="string"&&f.output.length>0)return f.output;if(typeof l?.output==="string"&&l.output.length>0)return l.output;if(typeof u?.metadata?.output==="string"&&u.metadata.output.length>0)return u.metadata.output;return""}function Xt(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return"";for(let l of f){let r=u[l];if(typeof r==="string"&&r.length>0)return r;if(r!==void 0&&r!==null&&typeof r!=="object")return String(r)}return""}function KU(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return null;for(let l of f){let r=Number(u[l]);if(Number.isFinite(r))return r}return null}function SU(u,f){let l=f?.input&&typeof f.input==="object"&&!Array.isArray(f.input)?f.input:u?.input&&typeof u.input==="object"&&!Array.isArray(u.input)?u.input:{},r=Xt(l,["command","cmd","script"]);if(r.length>0)return r;if(typeof u?.command==="string"&&u.command.length>0)return u.command;if(typeof f?.command==="string"&&f.command.length>0)return f.command;let n=String(u?.tool||u?.title||"tool"),i=Xt(l,["filePath","filepath","path"])||Xt(u,["filePath","filepath","path"]),y=Xt(l,["pattern","query"]),_=KU(l,["offset"]),$=KU(l,["limit"]),A=[n];if(y.length>0)A.push(y);if(i.length>0)A.push(i);if(_!==null)A.push(`offset=${_}`);if($!==null)A.push(`limit=${$}`);return A.length>1?A.join(" "):n}function pT(u,f){let l=u?.part&&typeof u.part==="object"&&!Array.isArray(u.part)?u.part:{},r=String(u?.type||u?.event||u?.name||l?.type||"").toLowerCase(),n=String(l?.type||"").toLowerCase(),i=u?.at||u?.timestamp||l?.updatedAt||l?.createdAt,y=Number.isFinite(Number(u?.seq))?Number(u.seq):f;if(r==="step_start"||r==="step-start"||n==="step-start")return null;if(r==="step_finish"||r==="step-finish"||n==="step-finish")return null;if(n==="tool"||/tool|bash|command/iu.test(`${r} ${n}`)){let $=l?.state&&typeof l.state==="object"&&!Array.isArray(l.state)?l.state:{},A=SU(l,$),c=YU($,l,u),j=pU(A,String(l?.tool||l?.title||"")),F=j==="edited"?{status:String($?.status||l?.status||u?.status||""),summary:mi(c||A,72),files:Yt(c),stages:[],lines:E5(c),addedLines:0,removedLines:0,rawText:c}:void 0;return{seq:y,at:D_(l,i),kind:j,title:String($?.title||l?.title||$?.metadata?.description||l?.tool||"OpenCode tool"),status:String($?.status||l?.status||u?.status||""),commandPreview:A,bodyPreview:c,durationMs:V_(l),rawSeqs:[l?.id||l?.callID||u?.sessionID||y],editObservation:F}}let _=ST(l?.text??l?.content??l?.delta??u?.text??u?.content??u?.delta,3000).trim();if(_.length>0)return{seq:y,at:D_(l,i),kind:n==="reasoning"?"message":/error|failed/iu.test(`${r} ${n}`)?"error":"message",title:n==="reasoning"?"Reasoning":/error|failed/iu.test(`${r} ${n}`)?"OpenCode error":"Assistant message",status:`opencode/${r||n||"event"}`,bodyPreview:_,durationMs:V_(l),rawSeqs:[l?.id||u?.sessionID||y]};return null}function pU(u,f){let l=`${f} ${u}`.toLowerCase();if(/\b(read|grep|glob|list|ls|find|search|view|cat|sed|rg|head|tail|wc|file)\b/iu.test(l))return"explored";if(/\b(edit|write|patch|apply|update|create|delete|apply_patch|git apply|cat >|tee .*<<|sed -i|python3? .*write_text|mkdir|rm |touch )\b/iu.test(l))return"edited";return"ran"}function mT(u){let f=[],l=1;for(let r of Array.isArray(u)?u:[]){if(r?.kind&&r?.title){let _=String(r?.status||"");if(_==="opencode/step-start"||_==="opencode/step-finish")continue;f.push({...r,seq:Number.isFinite(Number(r?.seq))?Number(r.seq):l++});continue}let n=r?.createdAt||r?.updatedAt||r?.completedAt,i=String(r?.role||"assistant").toLowerCase(),y=Array.isArray(r?.parts)?r.parts:[];if(y.length===0){if(r?.part&&(r?.sessionID||String(r?.type||"").startsWith("step_")||String(r?.type||"").includes("tool"))){let _=pT(r,l);if(_!==null)f.push(_),l=Math.max(l+1,Number(_.seq)+1)}else if(r?.textPreview)f.push({seq:l++,at:n,kind:"message",title:`${i||"assistant"} message`,status:i,bodyPreview:String(r.textPreview),rawSeqs:[r?.messageId||l]});continue}for(let _ of y){let $=String(_?.type||"").toLowerCase();if($==="step-start"||$==="step-finish")continue;if($==="text"||$==="reasoning"){let c=String(_?.textPreview||r?.textPreview||"").trim();if(c.length===0)continue;f.push({seq:l++,at:D_(_,n),kind:"message",title:$==="reasoning"?"Reasoning":i==="user"?"User message":i==="system"?"System message":"Assistant message",status:$==="reasoning"?"reasoning":i,bodyPreview:c,durationMs:V_(_),rawSeqs:[W5(_,l)]});continue}if($==="tool"){let c=_?.state&&typeof _.state==="object"&&!Array.isArray(_.state)?_.state:{},j=SU(_,c),F=YU(c,_,{}),U=pU(j,String(_?.tool||_?.title||"")),Q=U==="edited"?{status:String(c?.status||_?.status||""),summary:mi(F||j,72),files:Yt(F),stages:[],lines:E5(F),addedLines:0,removedLines:0,rawText:F}:void 0;f.push({seq:l++,at:D_(_,n),kind:U,title:String(_?.title||_?.tool||"tool"),status:String(_?.status||""),commandPreview:j,bodyPreview:F,durationMs:V_(_),rawSeqs:[W5(_,l)],editObservation:Q});continue}let A=String(_?.textPreview||_?.title||$||"").trim();if(A)f.push({seq:l++,at:D_(_,n),kind:"system",title:$||"part",bodyPreview:A,status:String(_?.status||""),durationMs:V_(_),rawSeqs:[W5(_,l)]})}}return f}var mU={source:"opencode",toTrace:mT};function PT(u){return String(u||"unknown").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-")||"unknown"}function GU(u){let f=String(u||"M").toUpperCase();if(f.startsWith("A")||f==="??")return"added";if(f.startsWith("D"))return"deleted";if(f.startsWith("R"))return"renamed";return"modified"}function MT(u){if(u==="item/fileChange/outputDelta")return"delta";return u.replace(/^item\//u,"")}function CT(u,f){if(u.kind==="file"){let n=String(u.status||"M");return Su("div",{key:`${f}-${u.text}`,className:`codex-edit-diff-line file ${GU(n)}`},Su("span",{className:`codex-edit-file-status ${GU(n)}`},n),Su("code",null,u.path||u.text.replace(/^([AMDRCU?]{1,2})\s+/u,"")))}let l=u.kind==="add"||u.kind==="del"?u.text.slice(0,1):u.kind==="hunk"?"@@":u.kind==="note"?"ok":"",r=u.kind==="add"||u.kind==="del"?u.text.slice(1):u.text;return Su("div",{key:`${f}-${u.text}`,className:`codex-edit-diff-line ${u.kind}`},Su("span",{className:"codex-edit-diff-sign"},l),Su("code",null,r||" "))}function RT(u,f){let l=u.lines.length>0?u.lines:u.files.map((n)=>({text:`${n.status} ${n.path}`,kind:"file",path:n.path,status:n.status})),r=Number(u.addedLines||0)+Number(u.removedLines||0)>0;return Su("div",{className:"codex-edit-observation","data-testid":"codex-edit-observation"},Su("div",{className:"codex-edit-observation-head"},Su("span",{className:"codex-edit-window-controls","aria-hidden":"true"},Su("i",null),Su("i",null),Su("i",null)),Su("strong",null,r?"git diff":"git diff --stat"),Su("code",null,u.summary||"File changes")),u.stages.length>0?Su("div",{className:"codex-edit-stage-strip"},u.stages.map((n,i)=>Su("span",{key:`${n.method}-${i}`,className:`codex-edit-stage ${PT(n.status||n.method)}`},Su("b",null,MT(n.method)),n.status?Su("em",null,n.status):null))):null,l.length>0?Su("div",{className:"codex-edit-diff",role:"list"},l.map(CT)):null,f?Su("div",{className:"codex-edit-omitted"},`${f} (查看原始JSON获取完整记录)`):null)}function zU(u,f,l){let r=w5(l);return Su("div",{className:`codex-transcript-stream ${u}`,"data-testid":`codex-trace-${u}`},Su("span",{className:"codex-transcript-stream-label"},u),Su("pre",{className:"codex-transcript-body"},f,r?` -${r} (查看原始JSON获取完整记录)`:""))}function PU(u,f=!1){let l=String(u.kind||"message"),r=["ran","explored","edited"].includes(l),n=w5(u.commandOmittedLines),i=w5(u.bodyOmittedLines),y=String(u.commandPreview||(r?u.title||"":"")),_=String(u.stdoutPreview||""),$=String(u.stderrPreview||""),A=_.length>0||$.length>0,c=Boolean(u.foldedReferencePrompt)&&String(u.fullPrompt||"").length>0,j=l==="edited"&&(u.editObservation!==void 0||BU(u))?u.editObservation||VU([u]):null;return Su("article",{key:`${u.seq}-${l}`,className:`codex-transcript-item ${l} ${f?"nested":""}`},Su("div",{className:"codex-transcript-main"},Su("div",{className:"codex-transcript-title"},Su("span",{className:"codex-output-channel"},L5(l)),r&&j===null?null:Su("strong",null,j!==null?"File changes":String(u.title||L5(l))),u.status?Su("code",null,String(j?.status||u.status)):null,Su("time",null,Nu(u.at))),y&&j===null?Su("pre",{className:"codex-transcript-command"},y,n?` -${n}`:""):null,j!==null?RT(j,i):A?Su("div",{className:"codex-transcript-streams"},_.length>0?zU("stdout",_,u.stdoutOmittedLines):null,$.length>0?zU("stderr",$,u.stderrOmittedLines):null):u.bodyPreview?Su("pre",{className:"codex-transcript-body"},String(u.bodyPreview),i?` -${i} (查看原始JSON获取完整记录)`:""):null,c?Su("details",{className:"codex-initial-prompt-full","data-testid":"codex-initial-prompt-full"},Su("summary",null,Su("span",null,"引用注入已折叠,点击查看最终传入 Codex 的完整 prompt"),Su("code",null,`${u.fullPromptLines||GT(String(u.fullPrompt||""))} lines / ${u.fullPromptChars||String(u.fullPrompt||"").length} chars`)),Su("pre",{className:"codex-transcript-body codex-transcript-full-prompt","data-testid":"codex-initial-prompt-full-text"},String(u.fullPrompt||""))):null))}function xT(u){let f=Array.isArray(u.items)?u.items:[],l=u.digest&&typeof u.digest==="object"?u.digest:DU(f);return Su("article",{key:`${u.seq}-toolGroup`,className:"codex-transcript-item toolGroup"},Su("div",{className:"codex-transcript-main"},Su("details",{className:"codex-tool-group","data-testid":"codex-tool-group"},Su("summary",null,Su("div",{className:"codex-tool-group-head"},Su("span",{className:"codex-output-channel"},L5("toolGroup")),Su("strong",null,String(u.title||ZU(f))),Su("code",null,String(u.status||`${f.length} calls`)),Su("time",null,Nu(u.at)))),Su("div",{className:"codex-tool-group-digest"},Su("span",null,`read: ${N5(Array.isArray(l.readFiles)?l.readFiles:[])}`),Su("span",null,`edit: ${N5(Array.isArray(l.editedFiles)?l.editedFiles:[])}`),Su("span",null,`run: ${N5(Array.isArray(l.runCommands)?l.runCommands:[],2)}`),Su("span",null,`duration: ${l.durationLabel||"--"}`)),Su("div",{className:"codex-tool-group-items"},f.map((r)=>PU(r,!0))))))}function hT(u){let f=[u.title,u.status,u.bodyPreview,u.commandPreview,u.stderrPreview,u.stdoutPreview].map((l)=>String(l||"")).join(` -`);return/\b(error|failed|failure|interrupt|interrupted|cancell?ed|watchdog|timeout|closed|refused|aborted|exception)\b/iu.test(f)}function MU(u,f){if(f)return u;return u.flatMap((l)=>{if(String(l.kind||"")==="system"&&!hT(l))return[];if(String(l.kind||"")!=="toolGroup"||!Array.isArray(l.items))return[l];let r=MU(l.items,f);return[{...l,items:r}]})}var bT=16;function TU(u){return u.scrollHeight-u.scrollTop-u.clientHeight<=bT}function St({items:u,input:f,port:l,autoScroll:r=!1,loading:n=!1,hasDetail:i=!0,emptyText:y="等待 Trace 输出...",loadingText:_="正在加载完整 Trace...",testId:$="trace-output",className:A="codex-transcript",keepRecentToolCalls:c=3,collapseTools:j=!0,showSystemEvents:F=!1}){let U=qU(null),Q=qU(!0),L=MU(XT(l?wT(l,f):XU(u)),Boolean(F)),w=j?YT(L,c):L,J=zT(L);LT(()=>{let W=U.current;if(!r||!W)return;if(!Q.current&&!TU(W))return;W.scrollTop=W.scrollHeight,Q.current=!0},[r,L.length,J]);let q={className:A,ref:U,onScroll:(W)=>{let z=W.currentTarget;Q.current=TU(z)},"data-testid":$};if(n&&!i)return Su("div",q,Su("div",{className:"codex-output-empty"},_));return Su("div",q,w.length===0?Su("div",{className:"codex-output-empty"},y):w.map((W)=>String(W.kind||"")==="toolGroup"?xT(W):PU(W)))}var CU=Pu(qf(),1),Q1=CU.default.createElement;function pt(...u){return u.filter(Boolean).join(" ")}function RU({title:u,children:f,actions:l,onClose:r,className:n,backdropClassName:i,bodyClassName:y,actionsClassName:_,titleId:$,testId:A,closeTestId:c,closeLabel:j="关闭",disableClose:F=!1,closeOnBackdrop:U=!0}){let Q={className:pt("raw-dialog","unidesk-dialog",n),role:"dialog","aria-modal":"true"};if($)Q["aria-labelledby"]=$;else if(typeof u==="string")Q["aria-label"]=u;if(A)Q["data-testid"]=A;return Q1("div",{className:pt("modal-backdrop","unidesk-dialog-backdrop",i),role:"presentation",onClick:(L)=>{if(U&&!F&&L.target===L.currentTarget)r()}},Q1("section",Q,Q1("div",{className:"raw-dialog-head unidesk-dialog-head"},Q1("strong",$?{id:$}:null,u),Q1("button",{type:"button",className:"ghost-btn",onClick:r,disabled:F,"data-testid":c},j)),Q1("div",{className:pt("unidesk-dialog-body",y)},f),l?Q1("div",{className:pt("unidesk-dialog-actions",_)},l):null))}var K=P_.default.createElement,{useEffect:wn,useMemo:xU,useRef:Xf}=P_.default,bu=P_.default.useState,vT=120,rQ=24,nQ=48,kT=1200;function Z5(){return typeof document>"u"||document.visibilityState!=="hidden"}function cl(u,f="操作失败"){return Hu(u,f)}function hr(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.floor(f/1000),r=Math.floor(l/3600),n=Math.floor(l%3600/60),i=l%60;if(r>0)return`${r}h ${String(n).padStart(2,"0")}m`;if(n>0)return`${n}m ${String(i).padStart(2,"0")}s`;return`${i}s`}function X0(u){if(u===null||u===void 0||u==="")return null;let f=u instanceof Date?u.getTime():new Date(u).getTime();return Number.isFinite(f)?f:null}function iQ(u,f=Date.now()){let l=X0(u);if(l===null)return"--";let r=Math.max(0,Math.floor((f-l)/1000));if(r<1)return"刚刚";let n=Math.floor(r/86400),i=Math.floor(r%86400/3600),y=Math.floor(r%3600/60),_=r%60;if(n>0)return`${n}天${i>0?`${i}小时`:""}前`;if(i>0)return`${i}小时${y>0?`${y}分钟`:""}前`;if(y>0)return`${y}分钟${_}秒前`;return`${_}秒前`}function yQ(...u){let f="",l=-1/0;for(let r of u){let n=String(r||"");if(n.length===0)continue;let i=X0(r);if(i!==null&&i>=l)f=n,l=i;else if(f.length===0)f=n}return f}function IT(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";if(f<1000)return`${Math.round(f)}ms`;return`${(f/1000).toFixed(f<1e4?2:1)}s`}function Y5(u,f=180){let l=String(u||"").replace(/\s+/gu," ").trim();return l.length>f?`${l.slice(0,f-1)}…`:l}async function Rf(u,f={}){return Eu(u,{strictJson:!0,retryInvalidJson:1,invalidJsonPrefix:"Code Queue 返回了无效 JSON",invalidJsonPreview:!0,responsePreviewLength:kT,...f})}function L1({status:u,children:f,title:l}){let r=String(u||"unknown").toLowerCase();return K("span",{className:`status-badge ${r}`,title:l},f||u||"unknown")}function Mi({title:u,eyebrow:f,summary:l,actions:r,children:n,className:i,loading:y}){return K("section",{className:`panel ${i||""}`},K("div",{className:"panel-head"},K("div",null,f?K("p",{className:"panel-eyebrow"},f):null,K(nf,{title:u,loading:y}),l?K("div",{className:"panel-summary"},l):null),r?K("div",{className:"panel-actions"},r):null),K("div",{className:"panel-body"},n))}function _Q({title:u,data:f,onOpen:l,testId:r}){return K("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function w1({title:u,text:f}){return K("div",{className:"empty-state"},K("strong",null,u),K("span",null,f))}function gT(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function sT(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function xf(u,f){return`${u}/code-queue-direct${f}`}function aT(u){return`${u}/microservices/oa-event-flow/proxy/api/events/stream?tags=${encodeURIComponent("service:code-queue")}`}function x5(){return{headers:{"cache-control":"no-cache","x-unidesk-no-cache":"1"}}}function jl(u){return Array.isArray(u?.tasks)?u.tasks:[]}function Ln(u){return u?.pagination&&typeof u.pagination==="object"&&!Array.isArray(u.pagination)?u.pagination:{}}function hU(u){let f=Date.parse(String(u?.updatedAt||u?.createdAt||""));return Number.isFinite(f)?f:0}function bU(u){return X0(u?.queueEnteredAt)??X0(u?.createdAt)??X0(u?.updatedAt)??0}function oT(u,f){let l=bU(u)-bU(f);if(l!==0)return l;let r=(X0(u?.createdAt)??0)-(X0(f?.createdAt)??0);if(r!==0)return r;return String(u?.id||"").localeCompare(String(f?.id||""))}function dT(u,f=""){let l=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length>0&&!l.has(i))l.set(i,n)}return Array.from(l.values()).sort((r,n)=>{let i=eU(r)-eU(n);if(i!==0)return i;let y=String(r?.id||"")===f?0:1,_=String(n?.id||"")===f?0:1;if(y!==_)return y-_;return hU(n)-hU(r)})}function Pi(u,f=""){let l=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length===0)continue;l.set(i,{...l.get(i)||{},...n})}return dT([Array.from(l.values())],f)}function Y_(u){return Array.isArray(u?.activeTaskIds)?u.activeTaskIds.map((f)=>String(f||"")).filter(Boolean):[String(u?.activeTaskId||"")].filter(Boolean)}var Gn="__all__",eT="(max-width: 760px)",uE="(min-width: 761px)";function bl(u){return!u||u===Gn}function fE(){return typeof window<"u"&&window.matchMedia(eT).matches}function lE(u){return bl(u)?"":`&queueId=${encodeURIComponent(u)}`}function S5(u){return String(u||"").trim().replace(/\s+/gu," ").slice(0,200)}function rE(u){let f=S5(u);return f.length===0?"":`&search=${encodeURIComponent(f)}`}function h5(u,f=""){return`${lE(u)}${rE(f)}`}function mt(u,f){return Number(u?.counts?.[f]||0)}function vU(u,f=""){let l=new Map;for(let n of Array.isArray(u?.queues)?u.queues:[]){let i=String(n?.id||"").trim();if(i.length>0)l.set(i,{...n,name:String(n?.name||i).trim()||i})}for(let n of[String(u?.defaultQueueId||"default"),f].map((i)=>i.trim()).filter(Boolean))if(!l.has(n))l.set(n,{id:n,name:n,total:0,counts:{},activeTaskId:null,runnableTaskId:null,processing:!1});return Array.from(l.values()).sort((n,i)=>{let y=String(n?.id||"")===String(u?.defaultQueueId||"default")?0:1,_=String(i?.id||"")===String(u?.defaultQueueId||"default")?0:1;if(y!==_)return y-_;return String(n?.id||"").localeCompare(String(i?.id||""))})}function $Q(u){let f=String(u?.id||"default"),l=String(u?.name||"").trim();return l.length>0?l:f}function p5(u){let f=String(u?.id||"default"),l=$Q(u);return l===f?f:`${l} (${f})`}function S_(u){let f=mt(u,"running")+mt(u,"judging"),l=mt(u,"queued")+mt(u,"retry_wait"),r=Number(u?.total||0),n=[p5(u),`${r} tasks`];if(f>0)n.push(`${f} running`);if(l>0)n.push(`${l} queued`);return n.join(" · ")}function Ri(u,f){if(bl(f))return null;return u.find((l)=>String(l?.id||"")===f)||null}function kU(u,f,l,r){if(bl(l)){let i=Y_(u);return String(u?.activeTaskId||i[0]||r.find((y)=>oU(y))?.id||"")}let n=Ri(f,l);return String(n?.activeTaskId||r.find((i)=>oU(i))?.id||"")}function nE(u,f,l){if(!bl(f)){let r=Ri(u,f);return String(r?.runnableTaskId||l.find((n)=>String(n?.status||"")==="queued"||String(n?.status||"")==="retry_wait")?.id||"")}return String(l.find((r)=>String(r?.status||"")==="queued"||String(r?.status||"")==="retry_wait")?.id||"")}async function iE(u,f=Gn,l=""){return Rf(xf(u,`/api/tasks/overview?limit=${rQ}&transcriptLimit=1&compact=1&selected=0${h5(f,l)}`),x5())}async function yE(u,f,l=0,r=Gn,n=""){return Rf(xf(u,`/api/tasks/overview?limit=${rQ}&transcriptLimit=3&compact=1&afterSeq=${encodeURIComponent(String(Math.max(0,l)))}&preferId=${encodeURIComponent(f)}${h5(r,n)}`),x5())}async function IU(u,f,l,r=nQ,n=""){return Rf(xf(u,`/api/tasks/overview?limit=${encodeURIComponent(String(r))}&transcriptLimit=1&compact=1&selected=0&includeActive=0&stats=0&beforeId=${encodeURIComponent(l)}${h5(f,n)}`),x5())}async function _E(u,f){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-summary`))}async function $E(u,f,l,r=null){let n=r===null||r===void 0||String(r).length===0?"":`&attempt=${encodeURIComponent(String(r))}`;return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/prompt?part=${encodeURIComponent(l)}${n}`))}async function tE(u,f,l=0,r=500,n=null){let i=n===null||n===void 0||String(n).length===0?"":`&attempt=${encodeURIComponent(String(n))}`;return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-steps?afterSeq=${encodeURIComponent(String(l))}&limit=${encodeURIComponent(String(r))}${i}`))}async function AE(u,f,l){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-step?seq=${encodeURIComponent(String(l))}`))}async function cE(u,f){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/read`),{method:"POST",body:{}})}async function jE(u){return Rf(xf(u,"/api/tasks/read-all"),{method:"POST",body:{}})}function FE(u){return Array.isArray(u?.output)?u.output:[]}function JE(u){return Array.isArray(u?.attempts)?u.attempts:[]}function O5(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function UE(u){return u.split(/^\s*---+\s*$/gmu).map((f)=>f.trim()).filter(Boolean)}function gU(u){let f=Number(u);return Number.isFinite(f)?Math.max(1,Math.min(50,Math.floor(f))):1}function q1(u){let f=[];for(let l of u.split(/[\s,,;;]+/u)){let r=l.trim();if(/^codex_\d+_[A-Za-z0-9_-]+$/u.test(r)&&!f.includes(r))f.push(r)}return f}function QE(u,f){let l=q1(f);if(l.length===0)return u;return[`引用 Code Queue 任务 ${l.join(" ")}。后端会在入队时只注入这些任务的 initial prompt 和 final response 全文;中间执行过程不注入,如需补充核查可运行:${l.map((r)=>`bun scripts/cli.ts codex task ${r}`).join(";")}`,"","本次任务:",u].join(` -`)}function qE(u){let r=u.trimStart();if(!r.startsWith("# Code Queue 已解析引用上下文"))return{hasInjection:!1,reference:"",userPrompt:u};let n=u.length-r.length,i=u.lastIndexOf(` +`):[]}function T5(u){let f=String(u.status||"").trim();if(f.length>0)return f;let l=String(u.bodyPreview||"");return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(l)?.[1]||"item/fileChange"}function ZT(u){let f=String(u.bodyPreview||"");return/file changes status=([A-Za-z0-9_-]+)/u.exec(f)?.[1]}function OT(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function DU(u){if(String(u.kind||"")!=="edited")return!1;let f=String(u.status||""),l=String(u.title||""),r=String(u.bodyPreview||""),n=String(u.commandPreview||"");if(l==="Edited files")return!0;if(/^item\/fileChange\//u.test(f))return!0;if((f==="item/started"||f==="item/completed")&&/file changes status=/u.test(r))return!0;if(/^Success\. Updated the following files:/mu.test(r))return!0;if(/^diff --git /mu.test(r))return!0;return/^([AMDRCU?]{1,2})\s+\S+/mu.test(r)||n.length>0&&St(r).length>0}function mi(u){return BU(String(u||"").replace(/^[ab]\//u,"").trim())}function Z5(u){let f=/^([AMDRCU?]{1,2})\s+(.+)$/u.exec(u);if(!f)return null;let l=mi(f[2]||"");return l.length>0?{status:f[1]||"M",path:l}:null}function O5(u){let f=/^\*\*\*\s+(Add|Update|Delete)\s+File:\s+(.+)$/u.exec(u);if(f){let r=f[1]==="Add"?"A":f[1]==="Delete"?"D":"M",n=mi(f[2]||"");return n.length>0?{status:r,path:n}:null}let l=/^\*\*\*\s+Move to:\s+(.+)$/u.exec(u);if(l){let r=mi(l[1]||"");return r.length>0?{status:"R",path:r}:null}return null}function St(u){let f=[],l=(n,i)=>{let y=mi(i);if(y.length===0||y==="/dev/null")return;let _=f.find(($)=>$.path===y);if(_){if(_.status==="M"&&n!=="M")_.status=n;return}f.push({status:n,path:y})},r="";for(let n of VU(u)){let i=Z5(n)||O5(n);if(i!==null){l(i.status,i.path),r=i.path;continue}let y=/^diff --git a\/(.+?) b\/(.+)$/u.exec(n);if(y){let j=y[2]||y[1]||"";l("M",j),r=mi(j);continue}let _=/^\+\+\+ b\/(.+)$/u.exec(n);if(_&&_[1]!=="/dev/null"){l("M",_[1]||""),r=mi(_[1]||"");continue}if(/^new file mode /u.exec(n)&&r)l("A",r);if(/^deleted file mode /u.exec(n)&&r)l("D",r);let c=/^rename to (.+)$/u.exec(n);if(c)l("R",c[1]||"")}return f}function HT(u){if(Z5(u)!==null||O5(u)!==null)return"file";if(/^(diff --git |index |--- |\+\+\+ |\*\*\* Begin Patch|\*\*\* End Patch)/u.test(u))return"meta";if(/^@@ /u.test(u))return"hunk";if(/^\+/u.test(u))return"add";if(/^-/u.test(u))return"del";if(/^(Success\.|No changes|Updated\b|Created\b|Deleted\b|Added\s+\d+\s+lines?|Wrote\s+\d+\s+lines?|Read\s+\d+\s+files?|\.\.\.\[patch content truncated)/iu.test(u))return"note";return"context"}function H5(u){return VU(u).map((f)=>{let l=Z5(f)||O5(f);if(l!==null)return{text:f,kind:"file",path:l.path,status:l.status};return{text:f,kind:HT(f)}})}function BT(u){return u.reduce((f,l)=>{if(l.kind==="add")f.added+=1;else if(l.kind==="del")f.removed+=1;return f},{added:0,removed:0})}function GU(u,f){return`${f} ${u} line${u===1?"":"s"}`}function VT(u,f){let l=[];if(u>0)l.push(GU(u,"Added"));if(f>0)l.push(GU(f,"removed"));return l.join(", ")}function DT(u){for(let l=u.length-1;l>=0;l-=1){let r=String(u[l]?.status||"").trim();if(r.length>0)return r}let f=String(u[u.length-1]?.method||"").trim();if(f==="item/fileChange/outputDelta")return"updated";if(f==="item/started")return"started";if(f==="item/completed")return"completed";return f.replace(/^item\//u,"")||"changed"}function XT(u){return`${u} file${u===1?"":"s"}`}function XU(u){let f=u.length>0?u:[],l=KU(f.map((F)=>String(F.bodyPreview||""))),n=KU(f.map((F)=>String(F.bodyPreview||"")).filter((F)=>F.trim().length>0&&!OT(F)))||l,i=St(n||l),y=f.map((F)=>({method:T5(F),status:ZT(F),at:F.at})),_=H5(n||l),$=BT(_),A=VT($.added,$.removed),c=i.length>0?XT(i.length):"",j=A.length>0?`${A}${c?` in ${c}`:""}`:i.length>0?c:Pi(n||l||"File changes",72);return{status:DT(y),summary:j,files:i,stages:y,lines:_,addedLines:$.added,removedLines:$.removed,rawText:l}}function YT(u){let f=u[0],l=u[u.length-1]||f,r=XU(u);return{...f,seq:Number.isFinite(Number(l?.seq))?Number(l?.seq):Number(f?.seq??0),at:l?.at||f?.at,title:r.files.length>0?`Edited ${r.summary}`:"Edited files",status:r.status,commandPreview:"",commandOmittedLines:void 0,bodyPreview:r.rawText,bodyOmittedLines:u.reduce((n,i)=>n+Number(i.bodyOmittedLines||0),0)||void 0,rawSeqs:u.flatMap((n)=>Array.isArray(n?.rawSeqs)?n.rawSeqs:[n?.seq]).filter((n)=>n!==void 0),editObservation:r}}function ST(u){let f=Array.isArray(u)?u:[],l=[],r=[],n=()=>{if(r.length===0)return;l.push(YT(r)),r=[]};for(let i of f){if(DU(i)){if(T5(i)==="item/started"&&r.length>0)n();if(r.push(i),T5(i)==="item/completed")n();continue}n(),l.push(i)}return n(),l}function YU(u){let f=[],l=[],r=[],n=(A,c)=>{for(let j of c)if(!A.includes(j))A.push(j)};for(let A of u){let c=String(A?.kind||""),j=[A?.commandPreview,A?.bodyPreview,A?.title].map((F)=>String(F||"")).join(` +`);if(c==="explored")n(f,wU(j));else if(c==="edited")n(l,wU(j));else if(c==="ran"){let F=String(A?.commandPreview||A?.title||"").trim();if(F.length>0&&!r.includes(F))r.push(Pi(F,90))}}let i=u.map((A)=>Date.parse(String(A?.at||""))).filter((A)=>Number.isFinite(A)),y=i.length>=2?Math.max(0,Math.max(...i)-Math.min(...i)):0,_=u.reduce((A,c)=>A+(Rr(c?.durationMs)??Rr(c?.elapsedMs)??0),0),$=y>0?y:_;return{readFiles:f,editedFiles:l,runCommands:r,durationLabel:zT($)}}function pT(u,f=3){let l=Array.isArray(u)?u:[],r=[],n=[],i=Math.max(0,f),y=new Set;for(let $=l.length-1;$>=0&&i>0;$-=1){let A=l[$];if(!LU(A))continue;y.add(A),i-=1}let _=()=>{if(n.length>=2){let $=OU(n);r.push({seq:Number(n[0]?.seq??0),at:n[0]?.at||n.at(-1)?.at,kind:"toolGroup",title:HU(n),status:`${n.length} calls`,items:n,counts:$,digest:YU(n),rawSeqs:n.flatMap((A)=>Array.isArray(A?.rawSeqs)?A.rawSeqs:[A?.seq]).filter((A)=>A!==void 0)})}else r.push(...n);n=[]};for(let $ of l){if(LU($)&&!y.has($)){n.push($);continue}_(),r.push($)}return _(),r}function SU(u){return(Array.isArray(u)?u:[]).map((f,l)=>({...f,seq:Number.isFinite(Number(f?.seq))?Number(f.seq):l+1,kind:String(f?.kind||"message"),at:f?.at===void 0?void 0:String(f.at),durationMs:Rr(f?.durationMs)??void 0,title:f?.title===void 0?void 0:String(f.title),status:f?.status===void 0?void 0:String(f.status)}))}function Y_(u){let f=Rr(u?.state?.time?.start)??Rr(u?.time?.start),l=Rr(u?.state?.time?.end)??Rr(u?.time?.end);return Rr(u?.durationMs)??Rr(u?.elapsedMs)??Rr(u?.timing?.durationMs)??Rr(u?.metadata?.durationMs)??(f!==null&&l!==null&&l>=f?l-f:null)??void 0}function S_(u,f){return u?.createdAt||u?.updatedAt||u?.completedAt||f||void 0}function K5(u,f){return u?.id||u?.messageId||f}function mT(u,f=1200){if(typeof u==="string")return u;if(u===void 0||u===null)return"";try{return Pi(JSON.stringify(u),f)}catch{return Pi(String(u),f)}}function pU(u,f,l){if(typeof u?.metadata?.diff==="string"&&u.metadata.diff.length>0)return u.metadata.diff;if(typeof u?.metadata?.filediff?.patch==="string"&&u.metadata.filediff.patch.length>0)return u.metadata.filediff.patch;if(typeof u?.output==="string"&&u.output.length>0)return u.output;if(typeof u?.result==="string"&&u.result.length>0)return u.result;if(typeof f?.output==="string"&&f.output.length>0)return f.output;if(typeof l?.output==="string"&&l.output.length>0)return l.output;if(typeof u?.metadata?.output==="string"&&u.metadata.output.length>0)return u.metadata.output;return""}function Yt(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return"";for(let l of f){let r=u[l];if(typeof r==="string"&&r.length>0)return r;if(r!==void 0&&r!==null&&typeof r!=="object")return String(r)}return""}function zU(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return null;for(let l of f){let r=Number(u[l]);if(Number.isFinite(r))return r}return null}function mU(u,f){let l=f?.input&&typeof f.input==="object"&&!Array.isArray(f.input)?f.input:u?.input&&typeof u.input==="object"&&!Array.isArray(u.input)?u.input:{},r=Yt(l,["command","cmd","script"]);if(r.length>0)return r;if(typeof u?.command==="string"&&u.command.length>0)return u.command;if(typeof f?.command==="string"&&f.command.length>0)return f.command;let n=String(u?.tool||u?.title||"tool"),i=Yt(l,["filePath","filepath","path"])||Yt(u,["filePath","filepath","path"]),y=Yt(l,["pattern","query"]),_=zU(l,["offset"]),$=zU(l,["limit"]),A=[n];if(y.length>0)A.push(y);if(i.length>0)A.push(i);if(_!==null)A.push(`offset=${_}`);if($!==null)A.push(`limit=${$}`);return A.length>1?A.join(" "):n}function PT(u,f){let l=u?.part&&typeof u.part==="object"&&!Array.isArray(u.part)?u.part:{},r=String(u?.type||u?.event||u?.name||l?.type||"").toLowerCase(),n=String(l?.type||"").toLowerCase(),i=u?.at||u?.timestamp||l?.updatedAt||l?.createdAt,y=Number.isFinite(Number(u?.seq))?Number(u.seq):f;if(r==="step_start"||r==="step-start"||n==="step-start")return null;if(r==="step_finish"||r==="step-finish"||n==="step-finish")return null;if(n==="tool"||/tool|bash|command/iu.test(`${r} ${n}`)){let $=l?.state&&typeof l.state==="object"&&!Array.isArray(l.state)?l.state:{},A=mU(l,$),c=pU($,l,u),j=PU(A,String(l?.tool||l?.title||"")),F=j==="edited"?{status:String($?.status||l?.status||u?.status||""),summary:Pi(c||A,72),files:St(c),stages:[],lines:H5(c),addedLines:0,removedLines:0,rawText:c}:void 0;return{seq:y,at:S_(l,i),kind:j,title:String($?.title||l?.title||$?.metadata?.description||l?.tool||"OpenCode tool"),status:String($?.status||l?.status||u?.status||""),commandPreview:A,bodyPreview:c,durationMs:Y_(l),rawSeqs:[l?.id||l?.callID||u?.sessionID||y],editObservation:F}}let _=mT(l?.text??l?.content??l?.delta??u?.text??u?.content??u?.delta,3000).trim();if(_.length>0)return{seq:y,at:S_(l,i),kind:n==="reasoning"?"message":/error|failed/iu.test(`${r} ${n}`)?"error":"message",title:n==="reasoning"?"Reasoning":/error|failed/iu.test(`${r} ${n}`)?"OpenCode error":"Assistant message",status:`opencode/${r||n||"event"}`,bodyPreview:_,durationMs:Y_(l),rawSeqs:[l?.id||u?.sessionID||y]};return null}function PU(u,f){let l=`${f} ${u}`.toLowerCase();if(/\b(read|grep|glob|list|ls|find|search|view|cat|sed|rg|head|tail|wc|file)\b/iu.test(l))return"explored";if(/\b(edit|write|patch|apply|update|create|delete|apply_patch|git apply|cat >|tee .*<<|sed -i|python3? .*write_text|mkdir|rm |touch )\b/iu.test(l))return"edited";return"ran"}function MT(u){let f=[],l=1;for(let r of Array.isArray(u)?u:[]){if(r?.kind&&r?.title){let _=String(r?.status||"");if(_==="opencode/step-start"||_==="opencode/step-finish")continue;f.push({...r,seq:Number.isFinite(Number(r?.seq))?Number(r.seq):l++});continue}let n=r?.createdAt||r?.updatedAt||r?.completedAt,i=String(r?.role||"assistant").toLowerCase(),y=Array.isArray(r?.parts)?r.parts:[];if(y.length===0){if(r?.part&&(r?.sessionID||String(r?.type||"").startsWith("step_")||String(r?.type||"").includes("tool"))){let _=PT(r,l);if(_!==null)f.push(_),l=Math.max(l+1,Number(_.seq)+1)}else if(r?.textPreview)f.push({seq:l++,at:n,kind:"message",title:`${i||"assistant"} message`,status:i,bodyPreview:String(r.textPreview),rawSeqs:[r?.messageId||l]});continue}for(let _ of y){let $=String(_?.type||"").toLowerCase();if($==="step-start"||$==="step-finish")continue;if($==="text"||$==="reasoning"){let c=String(_?.textPreview||r?.textPreview||"").trim();if(c.length===0)continue;f.push({seq:l++,at:S_(_,n),kind:"message",title:$==="reasoning"?"Reasoning":i==="user"?"User message":i==="system"?"System message":"Assistant message",status:$==="reasoning"?"reasoning":i,bodyPreview:c,durationMs:Y_(_),rawSeqs:[K5(_,l)]});continue}if($==="tool"){let c=_?.state&&typeof _.state==="object"&&!Array.isArray(_.state)?_.state:{},j=mU(_,c),F=pU(c,_,{}),U=PU(j,String(_?.tool||_?.title||"")),Q=U==="edited"?{status:String(c?.status||_?.status||""),summary:Pi(F||j,72),files:St(F),stages:[],lines:H5(F),addedLines:0,removedLines:0,rawText:F}:void 0;f.push({seq:l++,at:S_(_,n),kind:U,title:String(_?.title||_?.tool||"tool"),status:String(_?.status||""),commandPreview:j,bodyPreview:F,durationMs:Y_(_),rawSeqs:[K5(_,l)],editObservation:Q});continue}let A=String(_?.textPreview||_?.title||$||"").trim();if(A)f.push({seq:l++,at:S_(_,n),kind:"system",title:$||"part",bodyPreview:A,status:String(_?.status||""),durationMs:Y_(_),rawSeqs:[K5(_,l)]})}}return f}var MU={source:"opencode",toTrace:MT};function CT(u){return String(u||"unknown").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-")||"unknown"}function TU(u){let f=String(u||"M").toUpperCase();if(f.startsWith("A")||f==="??")return"added";if(f.startsWith("D"))return"deleted";if(f.startsWith("R"))return"renamed";return"modified"}function RT(u){if(u==="item/fileChange/outputDelta")return"delta";return u.replace(/^item\//u,"")}function xT(u,f){if(u.kind==="file"){let n=String(u.status||"M");return Xu("div",{key:`${f}-${u.text}`,className:`codex-edit-diff-line file ${TU(n)}`},Xu("span",{className:`codex-edit-file-status ${TU(n)}`},n),Xu("code",null,u.path||u.text.replace(/^([AMDRCU?]{1,2})\s+/u,"")))}let l=u.kind==="add"||u.kind==="del"?u.text.slice(0,1):u.kind==="hunk"?"@@":u.kind==="note"?"ok":"",r=u.kind==="add"||u.kind==="del"?u.text.slice(1):u.text;return Xu("div",{key:`${f}-${u.text}`,className:`codex-edit-diff-line ${u.kind}`},Xu("span",{className:"codex-edit-diff-sign"},l),Xu("code",null,r||" "))}function hT(u,f){let l=u.lines.length>0?u.lines:u.files.map((n)=>({text:`${n.status} ${n.path}`,kind:"file",path:n.path,status:n.status})),r=Number(u.addedLines||0)+Number(u.removedLines||0)>0;return Xu("div",{className:"codex-edit-observation","data-testid":"codex-edit-observation"},Xu("div",{className:"codex-edit-observation-head"},Xu("span",{className:"codex-edit-window-controls","aria-hidden":"true"},Xu("i",null),Xu("i",null),Xu("i",null)),Xu("strong",null,r?"git diff":"git diff --stat"),Xu("code",null,u.summary||"File changes")),u.stages.length>0?Xu("div",{className:"codex-edit-stage-strip"},u.stages.map((n,i)=>Xu("span",{key:`${n.method}-${i}`,className:`codex-edit-stage ${CT(n.status||n.method)}`},Xu("b",null,RT(n.method)),n.status?Xu("em",null,n.status):null))):null,l.length>0?Xu("div",{className:"codex-edit-diff",role:"list"},l.map(xT)):null,f?Xu("div",{className:"codex-edit-omitted"},`${f} (查看原始JSON获取完整记录)`):null)}function EU(u,f,l){let r=z5(l);return Xu("div",{className:`codex-transcript-stream ${u}`,"data-testid":`codex-trace-${u}`},Xu("span",{className:"codex-transcript-stream-label"},u),Xu("pre",{className:"codex-transcript-body"},f,r?` +${r} (查看原始JSON获取完整记录)`:""))}function CU(u,f=!1){let l=String(u.kind||"message"),r=["ran","explored","edited"].includes(l),n=z5(u.commandOmittedLines),i=z5(u.bodyOmittedLines),y=String(u.commandPreview||(r?u.title||"":"")),_=String(u.stdoutPreview||""),$=String(u.stderrPreview||""),A=_.length>0||$.length>0,c=Boolean(u.foldedReferencePrompt)&&String(u.fullPrompt||"").length>0,j=l==="edited"&&(u.editObservation!==void 0||DU(u))?u.editObservation||XU([u]):null;return Xu("article",{key:`${u.seq}-${l}`,className:`codex-transcript-item ${l} ${f?"nested":""}`},Xu("div",{className:"codex-transcript-main"},Xu("div",{className:"codex-transcript-title"},Xu("span",{className:"codex-output-channel"},G5(l)),r&&j===null?null:Xu("strong",null,j!==null?"File changes":String(u.title||G5(l))),u.status?Xu("code",null,String(j?.status||u.status)):null,Xu("time",null,Nu(u.at))),y&&j===null?Xu("pre",{className:"codex-transcript-command"},y,n?` +${n}`:""):null,j!==null?hT(j,i):A?Xu("div",{className:"codex-transcript-streams"},_.length>0?EU("stdout",_,u.stdoutOmittedLines):null,$.length>0?EU("stderr",$,u.stderrOmittedLines):null):u.bodyPreview?Xu("pre",{className:"codex-transcript-body"},String(u.bodyPreview),i?` +${i} (查看原始JSON获取完整记录)`:""):null,c?Xu("details",{className:"codex-initial-prompt-full","data-testid":"codex-initial-prompt-full"},Xu("summary",null,Xu("span",null,"引用注入已折叠,点击查看最终传入 Codex 的完整 prompt"),Xu("code",null,`${u.fullPromptLines||TT(String(u.fullPrompt||""))} lines / ${u.fullPromptChars||String(u.fullPrompt||"").length} chars`)),Xu("pre",{className:"codex-transcript-body codex-transcript-full-prompt","data-testid":"codex-initial-prompt-full-text"},String(u.fullPrompt||""))):null))}function bT(u){let f=Array.isArray(u.items)?u.items:[],l=u.digest&&typeof u.digest==="object"?u.digest:YU(f);return Xu("article",{key:`${u.seq}-toolGroup`,className:"codex-transcript-item toolGroup"},Xu("div",{className:"codex-transcript-main"},Xu("details",{className:"codex-tool-group","data-testid":"codex-tool-group"},Xu("summary",null,Xu("div",{className:"codex-tool-group-head"},Xu("span",{className:"codex-output-channel"},G5("toolGroup")),Xu("strong",null,String(u.title||HU(f))),Xu("code",null,String(u.status||`${f.length} calls`)),Xu("time",null,Nu(u.at)))),Xu("div",{className:"codex-tool-group-digest"},Xu("span",null,`read: ${w5(Array.isArray(l.readFiles)?l.readFiles:[])}`),Xu("span",null,`edit: ${w5(Array.isArray(l.editedFiles)?l.editedFiles:[])}`),Xu("span",null,`run: ${w5(Array.isArray(l.runCommands)?l.runCommands:[],2)}`),Xu("span",null,`duration: ${l.durationLabel||"--"}`)),Xu("div",{className:"codex-tool-group-items"},f.map((r)=>CU(r,!0))))))}function vT(u){let f=[u.title,u.status,u.bodyPreview,u.commandPreview,u.stderrPreview,u.stdoutPreview].map((l)=>String(l||"")).join(` +`);return/\b(error|failed|failure|interrupt|interrupted|cancell?ed|watchdog|timeout|closed|refused|aborted|exception)\b/iu.test(f)}function RU(u,f){if(f)return u;return u.flatMap((l)=>{if(String(l.kind||"")==="system"&&!vT(l))return[];if(String(l.kind||"")!=="toolGroup"||!Array.isArray(l.items))return[l];let r=RU(l.items,f);return[{...l,items:r}]})}var kT=16;function ZU(u){return u.scrollHeight-u.scrollTop-u.clientHeight<=kT}function pt({items:u,input:f,port:l,autoScroll:r=!1,loading:n=!1,hasDetail:i=!0,emptyText:y="等待 Trace 输出...",loadingText:_="正在加载完整 Trace...",testId:$="trace-output",className:A="codex-transcript",keepRecentToolCalls:c=3,collapseTools:j=!0,showSystemEvents:F=!1}){let U=WU(null),Q=WU(!0),L=RU(ST(l?GT(l,f):SU(u)),Boolean(F)),w=j?pT(L,c):L,J=ET(L);KT(()=>{let W=U.current;if(!r||!W)return;if(!Q.current&&!ZU(W))return;W.scrollTop=W.scrollHeight,Q.current=!0},[r,L.length,J]);let q={className:A,ref:U,onScroll:(W)=>{let z=W.currentTarget;Q.current=ZU(z)},"data-testid":$};if(n&&!i)return Xu("div",q,Xu("div",{className:"codex-output-empty"},_));return Xu("div",q,w.length===0?Xu("div",{className:"codex-output-empty"},y):w.map((W)=>String(W.kind||"")==="toolGroup"?bT(W):CU(W)))}var xU=Pu(Qf(),1),W1=xU.default.createElement;function mt(...u){return u.filter(Boolean).join(" ")}function hU({title:u,children:f,actions:l,onClose:r,className:n,backdropClassName:i,bodyClassName:y,actionsClassName:_,titleId:$,testId:A,closeTestId:c,closeLabel:j="关闭",disableClose:F=!1,closeOnBackdrop:U=!0}){let Q={className:mt("raw-dialog","unidesk-dialog",n),role:"dialog","aria-modal":"true"};if($)Q["aria-labelledby"]=$;else if(typeof u==="string")Q["aria-label"]=u;if(A)Q["data-testid"]=A;return W1("div",{className:mt("modal-backdrop","unidesk-dialog-backdrop",i),role:"presentation",onClick:(L)=>{if(U&&!F&&L.target===L.currentTarget)r()}},W1("section",Q,W1("div",{className:"raw-dialog-head unidesk-dialog-head"},W1("strong",$?{id:$}:null,u),W1("button",{type:"button",className:"ghost-btn",onClick:r,disabled:F,"data-testid":c},j)),W1("div",{className:mt("unidesk-dialog-body",y)},f),l?W1("div",{className:mt("unidesk-dialog-actions",_)},l):null))}var K=R_.default.createElement,{useEffect:zn,useMemo:bU,useRef:Xf}=R_.default,vu=R_.default.useState,IT=120,iQ=24,yQ=48,gT=1200;function B5(){return typeof document>"u"||document.visibilityState!=="hidden"}function Al(u,f="操作失败"){return Zu(u,f)}function hr(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.floor(f/1000),r=Math.floor(l/3600),n=Math.floor(l%3600/60),i=l%60;if(r>0)return`${r}h ${String(n).padStart(2,"0")}m`;if(n>0)return`${n}m ${String(i).padStart(2,"0")}s`;return`${i}s`}function Y0(u){if(u===null||u===void 0||u==="")return null;let f=u instanceof Date?u.getTime():new Date(u).getTime();return Number.isFinite(f)?f:null}function _Q(u,f=Date.now()){let l=Y0(u);if(l===null)return"--";let r=Math.max(0,Math.floor((f-l)/1000));if(r<1)return"刚刚";let n=Math.floor(r/86400),i=Math.floor(r%86400/3600),y=Math.floor(r%3600/60),_=r%60;if(n>0)return`${n}天${i>0?`${i}小时`:""}前`;if(i>0)return`${i}小时${y>0?`${y}分钟`:""}前`;if(y>0)return`${y}分钟${_}秒前`;return`${_}秒前`}function $Q(...u){let f="",l=-1/0;for(let r of u){let n=String(r||"");if(n.length===0)continue;let i=Y0(r);if(i!==null&&i>=l)f=n,l=i;else if(f.length===0)f=n}return f}function sT(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";if(f<1000)return`${Math.round(f)}ms`;return`${(f/1000).toFixed(f<1e4?2:1)}s`}function p5(u,f=180){let l=String(u||"").replace(/\s+/gu," ").trim();return l.length>f?`${l.slice(0,f-1)}…`:l}async function Rf(u,f={}){return Eu(u,{strictJson:!0,retryInvalidJson:1,invalidJsonPrefix:"Code Queue 返回了无效 JSON",invalidJsonPreview:!0,responsePreviewLength:gT,...f})}function G1({status:u,children:f,title:l}){let r=String(u||"unknown").toLowerCase();return K("span",{className:`status-badge ${r}`,title:l},f||u||"unknown")}function Ci({title:u,eyebrow:f,summary:l,actions:r,children:n,className:i,loading:y}){return K("section",{className:`panel ${i||""}`},K("div",{className:"panel-head"},K("div",null,f?K("p",{className:"panel-eyebrow"},f):null,K(nf,{title:u,loading:y}),l?K("div",{className:"panel-summary"},l):null),r?K("div",{className:"panel-actions"},r):null),K("div",{className:"panel-body"},n))}function tQ({title:u,data:f,onOpen:l,testId:r}){return K("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function z1({title:u,text:f}){return K("div",{className:"empty-state"},K("strong",null,u),K("span",null,f))}function aT(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function oT(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function xf(u,f){return`${u}/code-queue-direct${f}`}function dT(u){return`${u}/microservices/oa-event-flow/proxy/api/events/stream?tags=${encodeURIComponent("service:code-queue")}`}function b5(){return{headers:{"cache-control":"no-cache","x-unidesk-no-cache":"1"}}}function cl(u){return Array.isArray(u?.tasks)?u.tasks:[]}function Gn(u){return u?.pagination&&typeof u.pagination==="object"&&!Array.isArray(u.pagination)?u.pagination:{}}function vU(u){let f=Date.parse(String(u?.updatedAt||u?.createdAt||""));return Number.isFinite(f)?f:0}function kU(u){return Y0(u?.queueEnteredAt)??Y0(u?.createdAt)??Y0(u?.updatedAt)??0}function eT(u,f){let l=kU(u)-kU(f);if(l!==0)return l;let r=(Y0(u?.createdAt)??0)-(Y0(f?.createdAt)??0);if(r!==0)return r;return String(u?.id||"").localeCompare(String(f?.id||""))}function uE(u,f=""){let l=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length>0&&!l.has(i))l.set(i,n)}return Array.from(l.values()).sort((r,n)=>{let i=fQ(r)-fQ(n);if(i!==0)return i;let y=String(r?.id||"")===f?0:1,_=String(n?.id||"")===f?0:1;if(y!==_)return y-_;return vU(n)-vU(r)})}function Mi(u,f=""){let l=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length===0)continue;l.set(i,{...l.get(i)||{},...n})}return uE([Array.from(l.values())],f)}function m_(u){return Array.isArray(u?.activeTaskIds)?u.activeTaskIds.map((f)=>String(f||"")).filter(Boolean):[String(u?.activeTaskId||"")].filter(Boolean)}var En="__all__",fE="(max-width: 760px)",lE="(min-width: 761px)";function vl(u){return!u||u===En}function rE(){return typeof window<"u"&&window.matchMedia(fE).matches}function nE(u){return vl(u)?"":`&queueId=${encodeURIComponent(u)}`}function m5(u){return String(u||"").trim().replace(/\s+/gu," ").slice(0,200)}function iE(u){let f=m5(u);return f.length===0?"":`&search=${encodeURIComponent(f)}`}function v5(u,f=""){return`${nE(u)}${iE(f)}`}function Pt(u,f){return Number(u?.counts?.[f]||0)}function IU(u,f=""){let l=new Map;for(let n of Array.isArray(u?.queues)?u.queues:[]){let i=String(n?.id||"").trim();if(i.length>0)l.set(i,{...n,name:String(n?.name||i).trim()||i})}for(let n of[String(u?.defaultQueueId||"default"),f].map((i)=>i.trim()).filter(Boolean))if(!l.has(n))l.set(n,{id:n,name:n,total:0,counts:{},activeTaskId:null,runnableTaskId:null,processing:!1});return Array.from(l.values()).sort((n,i)=>{let y=String(n?.id||"")===String(u?.defaultQueueId||"default")?0:1,_=String(i?.id||"")===String(u?.defaultQueueId||"default")?0:1;if(y!==_)return y-_;return String(n?.id||"").localeCompare(String(i?.id||""))})}function AQ(u){let f=String(u?.id||"default"),l=String(u?.name||"").trim();return l.length>0?l:f}function P5(u){let f=String(u?.id||"default"),l=AQ(u);return l===f?f:`${l} (${f})`}function P_(u){let f=Pt(u,"running")+Pt(u,"judging"),l=Pt(u,"queued")+Pt(u,"retry_wait"),r=Number(u?.total||0),n=[P5(u),`${r} tasks`];if(f>0)n.push(`${f} running`);if(l>0)n.push(`${l} queued`);return n.join(" · ")}function xi(u,f){if(vl(f))return null;return u.find((l)=>String(l?.id||"")===f)||null}function gU(u,f,l,r){if(vl(l)){let i=m_(u);return String(u?.activeTaskId||i[0]||r.find((y)=>eU(y))?.id||"")}let n=xi(f,l);return String(n?.activeTaskId||r.find((i)=>eU(i))?.id||"")}function yE(u,f,l){if(!vl(f)){let r=xi(u,f);return String(r?.runnableTaskId||l.find((n)=>String(n?.status||"")==="queued"||String(n?.status||"")==="retry_wait")?.id||"")}return String(l.find((r)=>String(r?.status||"")==="queued"||String(r?.status||"")==="retry_wait")?.id||"")}async function _E(u,f=En,l=""){return Rf(xf(u,`/api/tasks/overview?limit=${iQ}&transcriptLimit=1&compact=1&selected=0${v5(f,l)}`),b5())}async function $E(u,f,l=0,r=En,n=""){return Rf(xf(u,`/api/tasks/overview?limit=${iQ}&transcriptLimit=3&compact=1&afterSeq=${encodeURIComponent(String(Math.max(0,l)))}&preferId=${encodeURIComponent(f)}${v5(r,n)}`),b5())}async function sU(u,f,l,r=yQ,n=""){return Rf(xf(u,`/api/tasks/overview?limit=${encodeURIComponent(String(r))}&transcriptLimit=1&compact=1&selected=0&includeActive=0&stats=0&beforeId=${encodeURIComponent(l)}${v5(f,n)}`),b5())}async function tE(u,f){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-summary`))}async function AE(u,f,l,r=null){let n=r===null||r===void 0||String(r).length===0?"":`&attempt=${encodeURIComponent(String(r))}`;return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/prompt?part=${encodeURIComponent(l)}${n}`))}async function cE(u,f,l=0,r=500,n=null){let i=n===null||n===void 0||String(n).length===0?"":`&attempt=${encodeURIComponent(String(n))}`;return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-steps?afterSeq=${encodeURIComponent(String(l))}&limit=${encodeURIComponent(String(r))}${i}`))}async function jE(u,f,l){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-step?seq=${encodeURIComponent(String(l))}`))}async function FE(u,f){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/read`),{method:"POST",body:{}})}async function JE(u){return Rf(xf(u,"/api/tasks/read-all"),{method:"POST",body:{}})}function UE(u){return Array.isArray(u?.output)?u.output:[]}function QE(u){return Array.isArray(u?.attempts)?u.attempts:[]}function V5(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function qE(u){return u.split(/^\s*---+\s*$/gmu).map((f)=>f.trim()).filter(Boolean)}function aU(u){let f=Number(u);return Number.isFinite(f)?Math.max(1,Math.min(50,Math.floor(f))):1}function L1(u){let f=[];for(let l of u.split(/[\s,,;;]+/u)){let r=l.trim();if(/^codex_\d+_[A-Za-z0-9_-]+$/u.test(r)&&!f.includes(r))f.push(r)}return f}function NE(u,f){let l=L1(f);if(l.length===0)return u;return[`引用 Code Queue 任务 ${l.join(" ")}。后端会在入队时只注入这些任务的 initial prompt 和 final response 全文;中间执行过程不注入,如需补充核查可运行:${l.map((r)=>`bun scripts/cli.ts codex task ${r}`).join(";")}`,"","本次任务:",u].join(` +`)}function WE(u){let r=u.trimStart();if(!r.startsWith("# Code Queue 已解析引用上下文"))return{hasInjection:!1,reference:"",userPrompt:u};let n=u.length-r.length,i=u.lastIndexOf(` # 本次任务 -`);if(i0?u.split(/\r\n|\r|\n/u).length:0}function tQ(u){let f=String(u?.displayPrompt||"");if(f.length>0)return f;let l=String(u?.prompt||"");return NE(qE(l).userPrompt)}function cr(u){return u?._traceSummary&&typeof u._traceSummary==="object"&&!Array.isArray(u._traceSummary)?u._traceSummary:null}function xt(u){return u?._promptDetails&&typeof u._promptDetails==="object"&&!Array.isArray(u._promptDetails)?u._promptDetails:{}}function b5(u){let f=cr(u)?.prompt;return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function AQ(u){let f=cr(u)?.execution;return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function sU(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):0}function D0(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):null}function cQ(u){let f=Lf(u?.traceStats);if(f&&(u?.statsSource==="oa-event-flow"||f.source==="oa-event-flow"))return f;let l=cr(u),r=Lf(l?.traceStats);if(r&&(l?.statsSource==="oa-event-flow"||r.source==="oa-event-flow"))return r;return null}function WE(u,f){let l=Lf(f?.traceStats)||Lf(f?.execution?.traceStats),r=String(f?.statsSource||f?.execution?.statsSource||"");if(l&&(r==="oa-event-flow"||l.source==="oa-event-flow"))return l;return null}function LE(u,f){return D0(cQ(u)?.[f])}function jQ(u){let f=LE(u,"stepCount");if(f!==null)return f;let l=cr(u);if(l!==null)return wE(l);return null}function wE(u){let f=Lf(u?.traceStats);if(!f||u?.statsSource!=="oa-event-flow"&&f.source!=="oa-event-flow")return null;return D0(f.stepCount)}function Pt(u){if(!u||u?._traceSummaryLoaded!==!0)return!1;let f=cr(u),l=String(u?._traceSummaryUpdatedAt||f?.updatedAt||""),r=String(u?.updatedAt||"");if(r.length>0){let n=X0(l),i=X0(r);if(n!==null&&i!==null){if(n+10?l:tQ(u)}function FQ(u){let f=cr(u);return String(f?.finalResponse||u?.finalResponse||"").trimEnd()}function JQ(u){let l=cr(u)?.lastJudge||u?.lastJudge;return l&&typeof l==="object"&&!Array.isArray(l)?l:null}function Lf(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function KE(u){let f=Lf(u?.raw),l=Lf(u?.failureDetails)||Lf(f?.minimaxFailure);if(l===null)return"";let r=l.repairAttempt===void 0?"":`${l.repairAttempt}/${l.maxRepairAttempts??"?"}`;return[["provider",l.provider||"minimax"],["stage",l.stage],["model",l.model],["timedOut",l.timedOut],["durationMs",l.durationMs],["timeoutMs",l.timeoutMs],["promptChars",l.promptChars],["promptLines",l.promptLines],["payloadBytes",l.payloadBytes],["responseStatus",l.responseStatus],["repairAttempt",r],["errorName",l.errorName],["error",l.errorMessage],["responseContentPreview",l.responseContentPreview],["responseTextPreview",l.responseTextPreview]].filter(([,i])=>i!==void 0&&i!==null&&String(i).length>0).map(([i,y])=>`${i}: ${String(y)}`).join(` -`)}function UQ({judge:u,testId:f="codex-judge-failure-details"}){let l=KE(u);if(l.length===0)return null;return K("details",{className:"codex-judge-failure-details","data-testid":f},K("summary",null,"MiniMax failure details"),K("pre",null,l))}function GE(u){let f=cr(u)?.attempts;if(Array.isArray(f)&&f.length>0)return f;let l=AQ(u),r=FQ(u),n=JQ(u);if(Object.keys(l).length===0&&r.length===0&&n===null)return[];return[{index:Number(u?.currentAttempt||1),mode:u?.currentMode||"initial",startedAt:u?.startedAt,finishedAt:u?.finishedAt,terminalStatus:u?.status,execution:l,finalResponse:r,finalResponseChars:r.length,judge:n}]}function zE(u,f){return Lf(f?.execution)||AQ(u)}function TE(u,f,l,r){let n=cr(u),i=Number(n?.currentAttempt||u?.currentAttempt||0),y=Number(l),_=Number.isFinite(y)&&y>0&&y===i,$=yQ(u?.updatedAt,n?.updatedAt);if(_&&!f?.finishedAt&&$.length>0)return $;return String(f?.updatedAt||f?.finishedAt||r.effectiveEndAt||(_?$:"")||$||u?.finishedAt||u?.startedAt||"")}function EE(u,f){let l=String(f?.finalResponse||f?.finalResponsePreview||"");if(Object.prototype.hasOwnProperty.call(f||{},"finalResponse")||Object.prototype.hasOwnProperty.call(f||{},"finalResponsePreview"))return l.trimEnd();return l.length>0?l.trimEnd():FQ(u)}function QQ(u,f){if(Object.prototype.hasOwnProperty.call(f||{},"judge"))return Lf(f?.judge);return JQ(u)}function ZE(u,f,l){if(!hE(u))return!1;if(v5(f,l))return!1;if(f?.finishedAt)return!1;if(["succeeded","failed","canceled"].includes(String(f?.terminalStatus||"")))return!1;let r=cr(u),n=Number(r?.currentAttempt||u?.currentAttempt||0),i=Number(l);if(Number.isFinite(i)&&i>0&&Number.isFinite(n)&&n>0)return i===n;return!0}function qQ(u){return`feedback:${String(u||"latest")}`}function OE(u,f,l){let r=String(f?.feedbackPrompt||"").trimEnd(),n=String(f?.feedbackPromptPreview||r||"").trimEnd(),i=Number(f?.feedbackPromptChars||r.length||n.length||0),y=Number(f?.feedbackPromptLines||W1(r||n));if(r.length>0||n.length>0||i>0)return{text:r,preview:n,chars:i,lines:y,source:f?.feedbackPromptSource||"judge-feedback",forAttempt:f?.feedbackPromptForAttempt||Number(l||0)+1,truncated:Boolean(f?.feedbackPromptTruncated)};let _=QQ(u,f),$=String(_?.continuePrompt||"").trimEnd();if(_?.decision==="retry"&&$.length>0)return{text:"",preview:$,chars:$.length,lines:W1($),source:"judge-continue-prompt",forAttempt:Number(l||0)+1,truncated:!1};return null}function HE(u){let f=b5(u);return Boolean(f.hasReferenceInjection||Number(f.referencePromptChars||0)>0||u?.referenceInjection||u?.referenceInjectionSummary)}function NQ(u,f=null){if(f!==null&&f!==void 0){let r=(Lf(u?._traceStepsByAttempt)||{})[String(f)];return Array.isArray(r)?r:[]}return Array.isArray(u?._traceSteps)?u._traceSteps:[]}function m5(u){let l=[u?.seq,...Array.isArray(u?.rawSeqs)?u.rawSeqs:[]].map((r)=>Number(r)).filter((r)=>Number.isFinite(r));return l.length>0?Math.max(...l):0}function BE(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,m5(l)),0)}function VE(u,f){let l=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(f)?f:[]]){let n=String(r?.seq??`${r?.title||"step"}:${r?.at||""}`);l.set(n,{...l.get(n)||{},...r})}return Array.from(l.values()).sort((r,n)=>m5(r)-m5(n))}function xi(u){return(Array.isArray(u?.summaryLines)?u.summaryLines:[]).map((f)=>String(f||""))}function DE(u){let f=String(u?.kind||"").trim().toLowerCase(),l=String(u?.status||"").trim().toLowerCase();return f==="error"||l==="error"}function ht(u){let f=String(u?.status||"").trim();if(f.length>0)return f;let l=xi(u).join(` -`);return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(l)?.[1]||""}function aU(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function XE(u){let f=xi(u);for(let r=f.length-1;r>=0;r-=1){let n=/file changes status=([A-Za-z0-9_-]+)/u.exec(f[r]||"")?.[1];if(n)return n}let l=ht(u);if(l==="item/fileChange/outputDelta")return"updated";if(l==="item/started")return"started";if(l==="item/completed")return"completed";return l.replace(/^item\//u,"")||String(u?.status||"changed")}function YE(u){if(String(u?.kind||"")!=="edited")return!1;let f=String(u?.title||""),l=String(u?.status||""),r=xi(u).join(` -`);if(f==="Edited files")return!0;if(/^item\/fileChange\//u.test(l))return!0;if((l==="item/started"||l==="item/completed")&&/file changes status=/u.test(r))return!0;if(/^Success\. Updated the following files:/mu.test(r))return!0;if(/^diff --git /mu.test(r))return!0;return/^([AMDRCU?]{1,2})\s+\S+/mu.test(r)}function SE(u){if(u.length<=1)return u[0];let f=u.find((i)=>ht(i)==="item/fileChange/outputDelta")||u.find((i)=>xi(i).some((y)=>!aU(y)))||u.at(-1)||u[0],l=u.flatMap((i)=>Array.isArray(i?.rawSeqs)?i.rawSeqs:[i?.seq]).filter((i)=>i!==void 0),r=u.flatMap(xi).filter((i)=>i.trim().length>0&&!aU(i)),n=u[u.length-1]||f;return{...f,at:f?.at||n?.at,title:String(f?.title||"Edited files"),status:XE(n),summaryLines:r.length>0?r:xi(f),rawSeqs:l}}function pE(u){let f=Array.isArray(u)?u:[],l=[],r=[],n=()=>{if(r.length>0)l.push(SE(r));r=[]};for(let i of f){if(YE(i)){if(ht(i)==="item/started"&&r.length>0)n();if(r.push(i),ht(i)==="item/completed")n();continue}n(),l.push(i)}return n(),l}function mE(u){return{...u}}function P5(u,f=null){if(f!==null&&f!==void 0){let l=Lf(u?._traceStepsLoadedByAttempt)||{};return Boolean(l[String(f)])}return Boolean(u?._traceStepsLoaded)}function M5(u){return u?._traceStepDetails&&typeof u._traceStepDetails==="object"&&!Array.isArray(u._traceStepDetails)?u._traceStepDetails:{}}function PE(u,f){let l=Number(u?.index);return Number.isFinite(l)?l:f+1}function v5(u,f){return Boolean(u?.synthetic)||Number(f)<=0}function bt(u){let f=Number(u);return Number.isFinite(f)?String(f):void 0}function ME(u){let f=u?.timing&&typeof u.timing==="object"?u.timing:{},l=String(u?.status||"");if(["queued"].includes(l))return`等待 ${hr(f.queueWaitMs??f.totalElapsedMs)}`;if(["running","judging","retry_wait"].includes(l))return`耗时 ${hr(f.durationMs??f.totalElapsedMs)}`;return`耗时 ${hr(f.durationMs??f.totalElapsedMs)}`}function p_(u){return String(u?.queueId||"default")}function WQ(u){return Lf(u?.queuedReason)}function LQ(u){let f=String(u?.queuedReasonLabel||"").trim();if(f.length>0)return f.toUpperCase();let l=WQ(u),r=String(l?.label||"").trim();return r.length>0?r.toUpperCase():""}function CE(u){let f=String(u?.status||"unknown");if(f!=="queued")return f;let l=LQ(u);return l.length>0?`QUEUED(${l})`:"QUEUED"}function RE(u){if(String(u?.status||"")!=="queued")return;let f=WQ(u),l=String(f?.message||"").trim(),r=LQ(u);if(l.length>0&&r.length>0)return`${r}: ${l}`;if(l.length>0)return l;return r.length>0?r:void 0}function xE(u){return{system:"SYS",user:"YOU",assistant:"GPT",reasoning:"THINK",command:"CMD",diff:"DIFF",tool:"TOOL",error:"ERR"}[u]||u.toUpperCase()}function oU(u){return["running","judging","retry_wait"].includes(String(u?.status||""))}function hE(u){return String(u?.status||"")==="running"}function xr(u){return["succeeded","failed","canceled"].includes(String(u?.status||""))}function wQ(u){if(u?.promptEditable===!0)return!0;if(u?.promptEditable===!1)return!1;return String(u?.status||"")==="queued"&&!u?.startedAt&&Number(u?.currentAttempt||0)===0&&!u?.codexThreadId&&!u?.nextMode}function V0(u){if(!xr(u))return!1;if(u?.terminalUnread===!0)return!0;if(u?.terminalUnread===!1)return!1;return!u?.readAt}function Cf(u){let f=Number(u||0);return Number.isFinite(f)?f:0}function bE(u){return Cf(u.queued)+Cf(u.retry_wait)}function vE(u){return Cf(u.running)+Cf(u.judging)}function kE(u,f){return Lf(u?.statistics)||Lf(f?.statistics)||{}}function IE(u){return Array.isArray(u?.daily)?u.daily:[]}function gE(u){return Lf(u?.totals)||{}}function k5(u,f){let l=Number(u?.[f]??0);return Number.isFinite(l)&&l>0?l:0}function H5(u,f){return u.reduce((l,r)=>Math.max(l,k5(r,f)),0)}var N1=700,dU=220,Kn=30,Ci=24,m_=184,C5=m_-Ci;function KQ(u,f){if(f<=1)return N1/2;return Kn+u*(N1-Kn*2)/(f-1)}function GQ(u,f){let l=f>0?f:1;return m_-Math.min(1,u/l)*C5}function B5(u,f,l){let r=u.length>0?u:[{[f]:0}],n=r.length>1?r:[r[0],r[0]];return n.map((i,y)=>`${KQ(y,n.length).toFixed(2)},${GQ(k5(i,f),l).toFixed(2)}`).join(" ")}function B0(u){let f=String(u||"");return/^\d{4}-\d{2}-\d{2}$/u.test(f)?f.slice(5):f||"--"}function Mt(u){if(!u)return"";return`${String(u.seriesKey||"")}:${String(u.row?.date||u.index||"")}`}function sE(u,f,l,r){let n=k5(u,r.key);return{...r,row:u,index:f,value:n,valueLabel:r.format(n),x:KQ(f,l),y:GQ(n,r.max),seriesKey:r.key}}function eU(u){if(V0(u))return 0;return{running:1,judging:2,retry_wait:3,queued:4,succeeded:8,failed:8,canceled:8}[String(u?.status||"")]??9}function X_(u){if(!u)return!1;if(u?._traceSummaryLoaded===!0)return!1;return u?.summaryOnly===!0||u?._metaLoaded!==!0}function aE(u){return Boolean(u?._metaLoaded)||u?.summaryOnly===!1}function oE(u,f,l){let r=String(u?.[l]||""),n=String(f?.[l]||"");return r.length>n.length?r:n}function R5(u,f,l){let r=Array.isArray(u?.[l])?u[l]:[],n=Array.isArray(f?.[l])?f[l]:[];if(n.length===0&&r.length>0)return r;return r.length>n.length?r:n}function uQ(u,f){let l=f?.summaryOnly===!0&&aE(u),r={...u,...f};if(!l)return r;for(let n of["prompt","basePrompt","displayPrompt","finalResponse"])r[n]=oE(u,f,n);for(let n of["promptHistory","attempts","output","events"])r[n]=R5(u,f,n);if(u?.referenceInjection?.items&&!f?.referenceInjection?.items)r.referenceInjection=u.referenceInjection;if(u?.referenceInjectionSummary&&!f?.referenceInjectionSummary)r.referenceInjectionSummary=u.referenceInjectionSummary;r.summaryOnly=u?.summaryOnly===!1?!1:f.summaryOnly,r._metaLoaded=u?._metaLoaded,r._detailLoaded=u?._detailLoaded,r._transcriptComplete=u?._transcriptComplete,r._transcriptPreview=Object.prototype.hasOwnProperty.call(f,"_transcriptPreview")?f._transcriptPreview:u?._transcriptPreview;for(let n of["_traceSummary","_traceSummaryLoaded","_traceSteps","_traceStepsLoaded","_traceStepsByAttempt","_traceStepsLoadedByAttempt","_traceStepsNextAfterSeqByAttempt","_traceStepDetails","_promptDetails"])if(!Object.prototype.hasOwnProperty.call(f,n)&&Object.prototype.hasOwnProperty.call(u||{},n))r[n]=u[n];return r}function dE(u){let f=u?.selected,l=f?.task&&typeof f.task==="object"?f.task:null;if(l!==null){let n=Boolean(f?.preview);return{...l,transcript:Array.isArray(f?.transcript)?f.transcript:[],_detailLoaded:Array.isArray(f?.transcript)&&f.transcript.length>0,_transcriptComplete:Boolean(!n&&!f?.hasMore&&xr(l)),_transcriptPreview:n,_summaryLoaded:!0}}let r=jl(u)[0];return r?{...r,_summaryLoaded:!0}:null}function V5(u,f){let l=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(f)?f:[]]){let n=`${Number(r?.seq??0)}:${String(r?.kind||"message")}`,i=l.get(n);if(!i){l.set(n,r);continue}let y={...i,...r};for(let[_,$]of[["bodyPreview","bodyOmittedLines"],["commandPreview","commandOmittedLines"]]){let A=String(i?.[_]||""),c=String(r?.[_]||"");if(A.length>c.length)y[_]=i[_],y[$]=i[$]}l.set(n,y)}return Array.from(l.values()).sort((r,n)=>Number(r?.seq??0)-Number(n?.seq??0))}function Ct(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,Number(l?.seq??0)),0)}function fQ(u,f=8){let l=Array.from(new Set((Array.isArray(u)?u:[]).map((n)=>Number(n?.seq??0)).filter((n)=>Number.isFinite(n)&&n>0))).sort((n,i)=>n-i);if(l.length===0)return 0;let r=l[Math.max(0,l.length-f)]??0;return Math.max(0,r-0.001)}function eE(u,f){let l=Array.isArray(u?.codeModels)?u.codeModels:Array.isArray(u?.codexModels)?u.codexModels:[],r=["gpt-5.5","gpt-5.4-mini","gpt-5.4","minimax-m2.7"];return Array.from(new Set([...l,...r,f].map((n)=>String(n||"").trim()).filter(Boolean)))}function uZ(u,f){let r=(Array.isArray(u?.executionProviders)?u.executionProviders:[]).map((y)=>({id:String(y?.id||"").trim(),label:String(y?.label||y?.id||"").trim(),defaultWorkdir:String(y?.defaultWorkdir||"").trim(),supportsWindowsNativeCodex:y?.supportsWindowsNativeCodex===!0,windowsNativeDefaultWorkdir:String(y?.windowsNativeDefaultWorkdir||"").trim(),kind:String(y?.kind||"").trim()})).filter((y)=>y.id.length>0),n=String(u?.mainProviderId||u?.defaultProviderId||"main-server").trim()||"main-server",i=new Map;for(let y of[...r,{id:n,label:`${n} (master)`,defaultWorkdir:String(u?.defaultWorkdir||"/root/unidesk"),supportsWindowsNativeCodex:!1,windowsNativeDefaultWorkdir:"",kind:"local"},f?{id:f,label:f,defaultWorkdir:I5(u,f),supportsWindowsNativeCodex:f!==n,windowsNativeDefaultWorkdir:String(u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart"),kind:""}:null].filter(Boolean))if(!i.has(y.id))i.set(y.id,y);return Array.from(i.values())}function fZ(u,f){let r=(Array.isArray(u?.executionModes)?u.executionModes:[]).map((y)=>({id:String(y?.id||y?.kind||"").trim(),label:String(y?.label||y?.id||y?.kind||"").trim(),description:String(y?.description||"").trim(),defaultWorkdir:String(y?.defaultWorkdir||"").trim(),requiresProvider:y?.requiresProvider===!0,requiresWindowsCwd:y?.requiresWindowsCwd===!0})).filter((y)=>y.id.length>0),n=[{id:"default",label:"默认容器/本机",description:"主 server 用本机 Codex;远程 Provider 用执行容器 Codex。",defaultWorkdir:"",requiresProvider:!1,requiresWindowsCwd:!1},{id:"windows-native",label:"Windows 原生 Codex",description:"启动执行容器,但容器只做 stdio relay,Codex 运行在 Provider 的 Windows 宿主。",defaultWorkdir:String(u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart"),requiresProvider:!0,requiresWindowsCwd:!0}],i=new Map;for(let y of[...r,...n,f?{id:f,label:f,description:"",defaultWorkdir:"",requiresProvider:f==="windows-native",requiresWindowsCwd:f==="windows-native"}:null].filter(Boolean))if(!i.has(y.id))i.set(y.id,y);return Array.from(i.values())}function D5(u,f,l){if(f!=="windows-native")return I5(u,l);let r=Array.isArray(u?.executionModes)?u.executionModes.find((i)=>String(i?.id||i?.kind||"")==="windows-native"):null,n=Array.isArray(u?.executionProviders)?u.executionProviders.find((i)=>String(i?.id||"")===l):null;return String(n?.windowsNativeDefaultWorkdir||r?.defaultWorkdir||u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart")}function I5(u,f){let l=String(f||"").trim(),r=u?.defaultWorkdirByProvider&&typeof u.defaultWorkdirByProvider==="object"?u.defaultWorkdirByProvider:{};if(typeof r[l]==="string"&&String(r[l]).trim().length>0)return String(r[l]).trim();let n=Array.isArray(u?.executionProviders)?u.executionProviders.find((y)=>String(y?.id||"")===l):null;if(typeof n?.defaultWorkdir==="string"&&n.defaultWorkdir.trim().length>0)return n.defaultWorkdir.trim();let i=String(u?.mainProviderId||u?.defaultProviderId||"main-server");return l===i?String(u?.defaultWorkdir||"/root/unidesk"):String(u?.remoteDefaultWorkdir||"/home/ubuntu")}function lZ(u){return jQ(u)}function rZ({task:u,selected:f,onSelect:l,onCopy:r,onReference:n,onMarkRead:i,copied:y,markingRead:_}){let $=u?.lastJudge||{},A=String(u?.id||""),c=V0(u),j=yQ(u?.updatedAt,cr(u)?.updatedAt),F=`最近更新: ${iQ(j)}`,U=lZ(u),Q=U===null?"--":String(U),L=U===null?"STEP 统计中心同步中":"STEP 来自 OA Event Flow 统计中心";return K("article",{role:"button",tabIndex:0,className:`codex-task-card ${f?"selected":""} ${c?"unread-terminal":""}`,onClick:l,onKeyDown:(w)=>{if(w.key==="Enter"||w.key===" ")w.preventDefault(),l()},"data-unread-terminal":c?"true":"false","data-testid":`codex-task-${u?.id||"unknown"}`},c?K("span",{className:"codex-unread-badge",title:"待读","aria-label":"待读","data-testid":`codex-unread-task-${A||"unknown"}`}):null,K("div",{className:"codex-task-card-head"},K("div",{className:"codex-task-status-line"},K(L1,{status:u?.status,title:RE(u)},CE(u))),K("span",{className:"mono-text"},`${u?.currentAttempt||0}/${u?.maxAttempts||0}`)),K("div",{className:"codex-task-id-row"},K("code",{title:A},A||"unknown"),K("div",{className:"codex-task-id-actions"},K("button",{type:"button",className:"codex-copy-id-btn",onClick:(w)=>{w.stopPropagation(),n(A)},"data-testid":`codex-reference-task-${A||"unknown"}`},"引用"),K("button",{type:"button",className:"codex-copy-id-btn",onClick:(w)=>{w.stopPropagation(),r(A)},"data-testid":`codex-copy-task-id-${A||"unknown"}`},y?"已复制":"复制ID"),c?K("button",{type:"button",className:"codex-copy-id-btn codex-mark-read-btn",disabled:Boolean(_),onClick:(w)=>{w.stopPropagation(),i(A)},"data-testid":`codex-mark-task-read-${A||"unknown"}`},_?"标记中":"标为已读"):null)),K("strong",null,Y5(tQ(u),120)||"空任务"),K("div",{className:"codex-task-meta"},K("span",null,`queue=${p_(u)}`),K("span",null,`provider=${u?.providerId||"main-server"}`),K("span",null,`mode=${u?.executionMode||"default"}`),K("span",null,u?.model||"--"),K("span",null,ME(u))),K("div",{className:"codex-task-meta codex-task-update-meta"},K("span",{className:"codex-task-recent-update codex-task-step-count",title:L,"data-testid":`codex-task-step-count-${A||"unknown"}`},`STEP ${Q}`),K("span",{className:"codex-task-recent-update",title:j?`更新时间: ${Nu(j)}`:F,"data-testid":`codex-task-recent-update-${A||"unknown"}`},F),K("span",null,Nu(j||u?.updatedAt))),wQ(u)?K("div",{className:"codex-judge-line","data-testid":`codex-task-prompt-editable-${A||"unknown"}`},"queued prompt 可编辑"):null,$?.decision?K("div",{className:"codex-judge-line"},`judge=${$.decision} ${Math.round(Number($.confidence||0)*100)}%`):null)}function X5({title:u,tasks:f,selectedId:l,onSelect:r,onCopy:n,onReference:i,onMarkRead:y,copiedTaskId:_,markingReadTaskId:$,emptyText:A}){let c=Array.isArray(f)?f:[];return K("section",{className:"codex-task-section"},K("div",{className:"codex-task-section-head"},K("span",null,u),K("code",null,String(c.length))),c.length===0?K("p",{className:"codex-task-section-empty"},A):K("div",{className:"codex-task-section-list"},c.map((j)=>K(rZ,{key:j.id,task:j,selected:l===j.id,onSelect:()=>r(j.id),onCopy:n,onReference:i,onMarkRead:y,copied:_===j.id,markingRead:$===j.id}))))}function nZ(){return K("span",{className:"codex-stats-icon","aria-hidden":"true"},K("svg",{viewBox:"0 0 36 24",focusable:"false"},K("path",{className:"grid",d:"M3 20.5H33M3 12.5H33M3 4.5H33"}),K("polyline",{className:"line tasks",points:"3,18 9,14 15,15 21,8 27,10 33,4"}),K("polyline",{className:"line retry",points:"3,20 9,17 15,18 21,13 27,14 33,9"})))}function iZ({stats:u,queueName:f,onRaw:l}){let r=IE(u),n=gE(u),i=r.at(-1)||{},y=H5(r,"executedTasks"),_=H5(r,"retryAttempts"),$=H5(r,"avgDurationMs"),A=r.length>0,c=Lf(u?.range)||{},[j,F]=bu(null),[U,Q]=bu(null),L=[];if(y>0)L.push(`tasks ${y}`);if(_>0)L.push(`retry ${_}`);if($>0)L.push(`avg ${hr($)}`);let w=[{key:"executedTasks",className:"tasks",label:"执行任务",max:y,format:(E)=>`${Cf(E)} tasks`},{key:"retryAttempts",className:"retry",label:"重试次数",max:_,format:(E)=>`${Cf(E)} retries`},{key:"avgDurationMs",className:"duration",label:"平均耗时",max:$,format:(E)=>hr(E)}],J=j||U,N=Mt(J),q=String(J?.row?.date||""),W=J?{left:`${Math.max(8,Math.min(92,Number(J.x)/N1*100))}%`,top:`${Math.max(14,Math.min(86,Number(J.y)/dU*100))}%`}:void 0;wn(()=>{F(null),Q(null)},[f,c.startDate,c.endDate,r.length]);let z=(E)=>{F(E)},Z=(E)=>{let D=Mt(E);Q((h)=>Mt(h)===D?null:E),F(E)},H=w.flatMap((E)=>r.map((D,h)=>{let V=sE(D,h,r.length,E),Y=Mt(V),p=N===Y,O=String(D?.date||`day-${h}`),m=`${B0(O)} ${E.label}: ${V.valueLabel}`;return K("g",{key:`${E.key}-${O}`,className:`stat-point-group ${E.className} ${p?"active":""}`,role:"button",tabIndex:0,"aria-label":m,"data-testid":`codex-stats-point-${E.className}-${O}`,onMouseEnter:()=>z(V),onFocus:()=>z(V),onClick:()=>Z(V),onKeyDown:(X)=>{if(X.key==="Enter"||X.key===" ")X.preventDefault(),Z(V)}},K("circle",{className:"stat-hit-point",cx:V.x,cy:V.y,r:13}),K("circle",{className:`stat-point ${E.className} ${p?"active":""}`,cx:V.x,cy:V.y,r:p?5.6:4.2}))}));return K(Mi,{title:"统计曲线",eyebrow:`Daily task stats / ${f}`,className:"codex-stats-panel",summary:K("span",null,`${B0(c.startDate)} -> ${B0(c.endDate)} · ${u?.timezone||"Asia/Shanghai"}`),actions:Lf(u)?K(_Q,{title:"Code Queue Stats",data:u,onOpen:l,testId:"raw-codex-stats"}):null},K("div",{className:"codex-stats-hero","data-testid":"codex-stats-panel"},K(nZ),K("div",null,K("strong",null,`${Cf(n.executedTasks)} tasks / ${Cf(n.retryAttempts)} retries`),K("span",null,`平均完成耗时 ${hr(n.avgDurationMs??void 0)} · 终态 ${Cf(n.completedTasks)} 个`))),A?K("div",{className:"codex-stats-chart","data-testid":"codex-stats-chart",onMouseLeave:()=>F(null)},K("svg",{viewBox:`0 0 ${N1} ${dU}`,preserveAspectRatio:"none",role:"img","aria-label":"Code Queue daily task statistics"},K("line",{className:"axis",x1:Kn,x2:N1-Kn,y1:m_,y2:m_}),K("line",{className:"grid",x1:Kn,x2:N1-Kn,y1:Ci+C5/2,y2:Ci+C5/2}),K("line",{className:"grid",x1:Kn,x2:N1-Kn,y1:Ci,y2:Ci}),K("polyline",{className:"stat-line tasks",points:B5(r,"executedTasks",y)}),K("polyline",{className:"stat-line retry",points:B5(r,"retryAttempts",_)}),K("polyline",{className:"stat-line duration",points:B5(r,"avgDurationMs",$)}),J?K("g",{className:"stat-cursor-layer","data-testid":"codex-stats-active-point"},K("line",{className:"stat-cursor",x1:J.x,x2:J.x,y1:Ci,y2:m_}),K("circle",{className:`stat-point-active ${J.className}`,cx:J.x,cy:J.y,r:8})):null,K("g",{className:"stat-point-layer"},H)),J?K("div",{className:"codex-stats-tooltip active",style:W,"data-testid":"codex-stats-tooltip"},K("b",null,B0(J.row?.date)),K("span",null,`${J.label} · ${J.valueLabel}`),K("code",null,`${Cf(J.row?.executedTasks)} exec / ${Cf(J.row?.retryAttempts)} retry / ${hr(J.row?.avgDurationMs??void 0)}`)):null,K("div",{className:"codex-stats-legend"},K("span",{className:"tasks"},"执行任务"),K("span",{className:"retry"},"重试次数"),K("span",{className:"duration"},"平均耗时")),K("div",{className:"codex-stats-scale"},K("span",null,B0(r[0]?.date)),K("span",null,L.join(" · ")||"暂无峰值"),K("span",null,B0(r.at(-1)?.date))),K("div",{className:`codex-stats-focus ${J?"active":""}`,"data-testid":"codex-stats-focus"},J?K(P_.default.Fragment,null,K("div",null,K("strong",null,B0(J.row?.date)),K("span",null,`${J.label} · ${J.valueLabel}`)),K("div",{className:"codex-stats-focus-metrics"},K("code",null,`${Cf(J.row?.executedTasks)} exec`),K("code",null,`${Cf(J.row?.retryAttempts)} retry`),K("code",null,hr(J.row?.avgDurationMs??void 0)))):K("span",null,"将鼠标悬停到曲线数据点查看明细,点击数据点可固定。"))):K(w1,{title:"暂无统计",text:"任务开始执行后会生成按天汇总的曲线。"}),K("div",{className:"codex-stats-summary-grid"},K("article",null,K("span",null,"今日执行"),K("strong",null,String(Cf(i.executedTasks))),K("code",null,B0(i.date))),K("article",null,K("span",null,"今日重试"),K("strong",null,String(Cf(i.retryAttempts))),K("code",null,`累计 ${Cf(n.retryAttempts)}`)),K("article",null,K("span",null,"平均耗时"),K("strong",null,hr(n.avgDurationMs??void 0)),K("code",null,`${Cf(n.durationSamples)} samples`))),K("div",{className:"codex-stats-daily-list","data-testid":"codex-stats-daily-list"},r.slice(-7).map((E)=>K("div",{key:String(E?.date||""),className:`codex-stats-daily-row ${q===String(E?.date||"")?"active":""}`,"data-testid":`codex-stats-day-${String(E?.date||"unknown")}`},K("span",null,B0(E?.date)),K("b",null,`${Cf(E?.executedTasks)} exec`),K("b",null,`${Cf(E?.retryAttempts)} retry`),K("code",null,hr(E?.avgDurationMs??void 0))))))}function yZ({task:u,queueRows:f,busy:l,onMove:r}){let n=String(u?.id||""),i=p_(u),[y,_]=bu(i);wn(()=>{_(i)},[n,i]);let $=!n||l||["running","judging","retry_wait"].includes(String(u?.status||""));return K("div",{className:"codex-task-move-control","data-testid":"codex-task-queue-move-control"},K("label",null,"任务 queue",K("select",{value:y,disabled:!n||l,onChange:(A)=>_(String(A.target.value||i)),"data-testid":"codex-task-queue-move-select"},f.map((A)=>K("option",{key:String(A?.id||""),value:String(A?.id||"")},S_(A))))),K("button",{type:"button",className:"ghost-btn",disabled:$||y===i,onClick:()=>r(y),title:$?"运行中 / judging / retry_wait 的任务不能移动;请先打断或等当前 turn 结束":"移动已创建任务到另一个 queue","data-testid":"codex-task-queue-move-button"},"移动"))}function lQ(u,f=4){let l=(Array.isArray(u)?u:[]).map((n)=>String(n||"").trim()).filter(Boolean);if(l.length===0)return"--";let r=l.slice(0,f).join(" / ");return l.length>f?`${r} +${l.length-f}`:r}function _Z({task:u,loading:f,onLoadPromptPart:l,testId:r="codex-initial-prompt-full",textTestId:n="codex-initial-prompt-full-text",baseTextTestId:i="codex-initial-prompt-base"}){let y=b5(u),_=xt(u),$=Rt(u).trimEnd(),A=String(_.full?.text||""),c=HE(u),j=Number(y.promptChars||u?.promptChars||A.length),F=Number(y.basePromptLines||W1($)),U=Number(y.promptLines||W1(A));return K("section",{className:"codex-progressive-card codex-progressive-prompt","data-testid":"codex-progressive-prompt"},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Prompt"),K("strong",null,"Submitted prompt / 原始用户 prompt"),K("code",null,`${F||W1($)} lines / ${$.length} chars`)),K("pre",{className:"codex-prompt-full","data-testid":i},$||"空 prompt"),c?K("details",{className:"codex-reference-injection codex-progressive-full-prompt","data-testid":r,onToggle:(Q)=>{if(Q.currentTarget?.open&&!A)l?.("full")}},K("summary",null,K("span",null,"引用注入已折叠,点击按需拉取最终进入 Code agent 的完整 prompt"),K("code",null,A?`${U||W1(A)} lines / ${A.length} chars`:`${Number.isFinite(j)&&j>0?j:"--"} chars`)),K("pre",{className:"codex-prompt-full codex-prompt-final-full","data-testid":n},A||(f?"正在按需拉取完整 prompt...":"展开后将只请求 full prompt,不拉取完整 transcript。"))):null)}function zQ({task:u,attempt:f,attemptIndex:l,loading:r,onLoadSteps:n,onLoadStep:i,testId:y="codex-execution-summary"}){let _=pE(NQ(u,l)),$=mE(zE(u,f)),A=f?WE(u,f):cQ(u),c=M5(u),j=P5(u,l),F=D0(A?.errorCount),U=D0(A?.stepCount??A?.llmStepCount),Q=D0(A?.readCount),L=D0(A?.editCount),w=D0(A?.runCount),J=D0(A?.stepCount??A?.llmStepCount),N=U===null?"--":String(U),q=J===null?"--":String(J),W=Array.isArray($.editedFiles)?$.editedFiles:[],z=Array.isArray($.commands)?$.commands:[],H=v5(f,l)?` · ${String(f?.label||"recovered thread execution")}`:l?` #${l}`:"",E=TE(u,f,l,$),D=`最近更新: ${iQ(E)}`,h=ZE(u,f,l);return K("details",{className:`codex-progressive-card codex-execution-summary ${h?"running":""}`,"data-testid":y,"data-attempt-index":bt(l),"data-running":h?"true":"false",onToggle:(V)=>{if(V.currentTarget?.open&&!j)n?.(l)}},K("summary",null,K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Summary"),K("strong",null,`执行过程摘要${H}`),h?K("span",{className:"codex-summary-running-pill","data-testid":`${y}-running`},"执行中"):null,K("code",{title:E?`最近更新: ${Nu(E)}`:D},`${hr($.durationMs??$.totalElapsedMs)} / ${N} tools / ${D}`)),K("div",{className:"codex-execution-digest"},K("span",{title:"来自 OA Event Flow 统计中心"},`read ${Q===null?"--":Q}`),K("span",{title:"来自 OA Event Flow 统计中心"},`edit ${L===null?"--":L}`),K("span",{title:"来自 OA Event Flow 统计中心"},`run ${w===null?"--":w}`),K("span",{title:"来自 OA Event Flow 统计中心"},`STEP ${q}`),F!==null&&F>0?K("span",{className:"codex-execution-error-pill","data-testid":`${y}-error-count`},`Error ${F}`):null)),K("div",{className:"codex-execution-digest expanded"},K("span",null,`修改文件:${lQ(W,6)}`),K("span",null,`执行命令:${lQ(z,4)}`)),_.length===0?K("div",{className:"codex-output-empty"},r?"正在按需拉取步骤 summary...":"展开后将只请求执行步骤 summary,不拉取单步骤全量。"):K("div",{className:"codex-trace-step-list"},_.map((V)=>{let Y=String(V?.seq??""),p=c[Y],O=Array.isArray(V?.summaryLines)?V.summaryLines.slice(0,4):[],m=O.find((X)=>String(X||"").trim().length>0);return K("details",{key:Y||`${V?.title}-${V?.at}`,className:`codex-trace-step ${String(V?.kind||"message")} ${DE(V)?"error":""}`,"data-testid":`codex-trace-step-${Y||"unknown"}`,onToggle:(X)=>{if(X.currentTarget?.open&&!p)i?.(V?.seq)}},K("summary",null,K("span",{className:"codex-output-channel"},$Z(V?.kind)),K("strong",null,String(V?.title||"Trace step")),V?.status?K("code",null,String(V.status)):null,m?K("span",{className:"codex-trace-step-inline-summary",title:String(m)},String(m)):null,K("time",null,Nu(V?.at))),K("div",{className:"codex-trace-step-summary"},O.length>0?O.map((X,v)=>K("pre",{key:`${Y}-${v}`},String(X||""))):K("span",null,"无 summary")),p?.line?K(St,{items:[p.line],autoScroll:!1,loading:!1,hasDetail:!0,emptyText:"无步骤详情",testId:`codex-trace-step-detail-${Y||"unknown"}`,className:"codex-transcript codex-step-detail-transcript",collapseTools:!1}):K("div",{className:"codex-output-empty"},r?"正在按需拉取这个步骤的全量数据...":"展开后将只请求这个单步骤的全量数据。"))})))}function $Z(u){let f=String(u||"");if(f==="ran")return"Ran";if(f==="explored")return"Explored";if(f==="edited")return"Edited";if(f==="error")return"Error";if(f==="system")return"System";return"Message"}function TQ({task:u,attempt:f,attemptIndex:l,testId:r="codex-final-response"}){let n=EE(u,f);if(n.length===0)return null;let i=Number(f?.finalResponseChars||n.length),y=l?` #${l}`:"";return K("section",{className:"codex-progressive-card codex-final-response","data-testid":r,"data-attempt-index":bt(l)},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Final"),K("strong",null,`最终 response${y}`),K("code",null,`${Number.isFinite(i)?i:n.length} chars`)),K(FU,{markdown:n,className:"codex-transcript-body codex-markdown",testId:`${r}-markdown`}))}function EQ({task:u,attempt:f,attemptIndex:l,testId:r="codex-progressive-judge"}){let n=QQ(u,f);if(!n?.decision)return null;let i=l?` #${l}`:"";return K("section",{className:"codex-progressive-card codex-progressive-judge","data-testid":r,"data-attempt-index":bt(l)},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Judge"),K("strong",null,`完成判定${i}`),K("code",null,`${n.decision} ${Math.round(Number(n.confidence||0)*100)}%`)),K("div",{className:"codex-judge-card","data-testid":`${r}-card`},K(L1,{status:n.decision},n.decision),K("strong",null,`${Math.round(Number(n.confidence||0)*100)}% confidence`),K("p",{"data-testid":`${r}-reason`},n.reason||"--"),K(UQ,{judge:n,testId:`${r}-failure-details`}),n.continuePrompt?K("pre",{"data-testid":`${r}-continue-prompt`},String(n.continuePrompt||"")):null))}function tZ({task:u,attempt:f,attemptIndex:l,loading:r,onLoadPromptPart:n,testId:i="codex-judge-feedback-prompt"}){let y=OE(u,f,l);if(y===null)return null;let _=qQ(l),A=xt(u)[_],c=String(A?.text||"").trimEnd(),j=String(y.preview||y.text||"").trimEnd(),F=c||String(y.text||"").trimEnd(),U=Number(A?.chars||y.chars||F.length||j.length),Q=Number(A?.lines||y.lines||W1(F||j)),L=A?.forAttempt||y.forAttempt||Number(l||0)+1;return K("details",{className:"codex-progressive-card codex-judge-feedback-prompt","data-testid":i,"data-attempt-index":bt(l),onToggle:(w)=>{if(w.currentTarget?.open&&!c)n?.("feedback",l)}},K("summary",null,K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Prompt"),K("strong",null,`judge feedback prompt #${l} -> #${L}`),K("code",null,`${Q||"--"} lines / ${Number.isFinite(U)?U:j.length} chars`)),K("p",{className:"codex-feedback-preview","data-testid":`${i}-preview`},j||"展开后按需拉取 judge feedback prompt。")),K("pre",{className:"codex-prompt-full codex-feedback-full","data-testid":`${i}-text`},F||(r?"正在按需拉取 judge feedback prompt...":"展开后将只请求这一次 judge feedback prompt。")))}function AZ({task:u,attempt:f,position:l,loading:r,onLoadPromptPart:n,onLoadSteps:i,onLoadStep:y}){let _=PE(f,l),$=l===0,A=v5(f,_),c=A?String(f?.label||"Recovered thread execution"):`Attempt ${_}`;return K("section",{className:"codex-attempt-cycle","data-testid":`codex-attempt-cycle-${_}`},K("div",{className:"codex-attempt-cycle-head"},K("span",{className:"codex-output-channel"},c),K("strong",null,String(f?.mode||(_<=1?"initial":"retry"))),f?.terminalStatus?K(L1,{status:f.terminalStatus},f.terminalStatus):null,K("code",null,`${Nu(f?.startedAt)} -> ${Nu(f?.finishedAt)}`)),K(zQ,{task:u,attempt:f,attemptIndex:_,loading:r,onLoadSteps:i,onLoadStep:y,testId:$?"codex-execution-summary":`codex-execution-summary-attempt-${_}`}),A?null:K(TQ,{task:u,attempt:f,attemptIndex:_,testId:$?"codex-final-response":`codex-final-response-attempt-${_}`}),A?null:K(EQ,{task:u,attempt:f,attemptIndex:_,testId:$?"codex-progressive-judge":`codex-progressive-judge-attempt-${_}`}),A?null:K(tZ,{task:u,attempt:f,attemptIndex:_,loading:r,onLoadPromptPart:n,testId:$?"codex-judge-feedback-prompt":`codex-judge-feedback-prompt-attempt-${_}`}))}function cZ({task:u,loading:f,onLoadPromptPart:l,onLoadSteps:r,onLoadStep:n}){if(!u)return K(w1,{title:"未选择任务",text:"从左侧队列选择任务,或提交新 Codex 任务。"});let i=GE(u);return K("div",{className:"codex-transcript codex-progressive-trace","data-testid":"codex-output"},f&&!cr(u)?K("div",{className:"codex-output-empty"},"正在加载 Trace Summary..."):null,K(_Z,{task:u,loading:f,onLoadPromptPart:l}),i.length>0?i.map((y,_)=>K(AZ,{key:`${y?.index||_+1}-${y?.startedAt||_}`,task:u,attempt:y,position:_,loading:f,onLoadPromptPart:l,onLoadSteps:r,onLoadStep:n})):[K(zQ,{key:"execution",task:u,loading:f,onLoadSteps:r,onLoadStep:n}),K(TQ,{key:"final",task:u}),K(EQ,{key:"judge",task:u})])}function jZ({task:u}){let f=FE(u);if(!u||f.length===0)return K(w1,{title:"暂无原始消息",text:"原始 Codex app-server 消息会保留在任务 JSON 中。"});return K("details",{className:"codex-raw-output"},K("summary",null,`原始 messages (${f.length})`),K("div",null,f.map((l)=>K("article",{key:`${l.seq}-${l.channel}`,className:`codex-output-line ${l.channel||"system"}`},K("div",{className:"codex-output-meta"},K("span",{className:"codex-output-channel"},xE(String(l.channel||"system"))),K("span",null,Nu(l.at)),l.method?K("code",null,l.method):null),K("pre",null,String(l.text||""))))))}function FZ({task:u}){let f=JE(u).slice().reverse();if(f.length===0)return K(w1,{title:"尚无 attempt",text:"任务开始运行后,这里会记录 Codex 终态、传输中断和 stderr tail。"});return K("div",{className:"table-wrap codex-attempt-table"},K("table",null,K("thead",null,K("tr",null,K("th",null,"#"),K("th",null,"模式"),K("th",null,"终态"),K("th",null,"传输"),K("th",null,"退出"),K("th",null,"完成时间"))),K("tbody",null,f.map((l)=>K("tr",{key:`${l.index}-${l.startedAt}`},K("td",null,l.index),K("td",null,l.mode),K("td",null,K(L1,{status:l.terminalStatus||"unknown"},l.terminalStatus||"unknown")),K("td",null,l.transportClosedBeforeTerminal?K(L1,{status:"failed"},"closed-before-terminal"):K(L1,{status:"succeeded"},"normal")),K("td",null,`code=${l.appServerExitCode??"--"} signal=${l.appServerSignal??"--"}`),K("td",null,Nu(l.finishedAt)))))))}function ZQ({microservices:u,onRaw:f,apiBaseUrl:l="/api",initialTasksData:r=null,standalone:n=!1}){let i=u.find((B)=>B.id==="code-queue")||null,y=dE(r),_=String(y?.id||""),$=new Map;if(y!==null&&_.length>0)$.set(_,{task:y,maxSeq:Ct(Array.isArray(y.transcript)?y.transcript:[]),complete:Boolean(y._transcriptComplete),completeUpdatedAt:y._transcriptComplete?String(y.updatedAt||""):""});let A=typeof performance>"u"?0:performance.now(),c=Xf(_),j=Xf(0),F=Xf(0),U=Xf(0),Q=Xf(!1),L=Xf(!1),w=Xf(!1),J=Xf(null),N=Xf(new Map),q=Xf(new Map),W=Xf(new Map),z=Xf(new Map),Z=Xf(new Set),H=Xf(null),E=Xf(null),D=Xf(!1),h=Xf(!1),V=Xf(Boolean(r)),Y=Xf(new Map),p=Xf(new Set),O=Xf($),m=Xf(r),[X,v]=bu(null),[T,S]=bu(r),[k,I]=bu(_),[b,o]=bu(y),[s,x]=bu(!1),[fu,$u]=bu(""),[tu,ju]=bu(null),[Gu,qu]=bu(!1),[P,e]=bu(!1),[uu,Wu]=bu(""),[g,Qu]=bu(""),[Tu,Zu]=bu("default"),[Xu,uf]=bu(Gn),[_f,Jf]=bu(!1),[Pf,Sl]=bu(""),[vf,ll]=bu("main-server"),[dl,el]=bu("default"),[cu,ku]=bu("gpt-5.5"),[Tl,pu]=bu("/root/unidesk"),[rl,El]=bu(99),[Jl,nl]=bu(1),[pl,qr]=bu(!1),[rf,C1]=bu(!1),[kn,R1]=bu(""),[lu,Ou]=bu(""),[Yu,Iu]=bu(""),[Qf,il]=bu(!0),[ff,df]=bu(()=>typeof window>"u"?!0:window.matchMedia(uE).matches),[$f,C$]=bu(!1),[V8,Tf]=bu(""),[u7,kf]=bu(""),{addNotification:ur}=Vl(),[Wy,R$]=bu(""),[x1,Ly]=bu(""),[h1,x$]=bu(!1),[ml,sr]=bu(r?{phase:"complete",taskId:_,queueMs:0,detailMs:0,totalMs:A,chunks:y?1:0,transcriptRows:Array.isArray(y?.transcript)?y.transcript.length:0,partial:Boolean(r?.selected?.hasMore||X_(y)),completedAt:new Date}:null),[h$,b$]=bu(r?new Date:null),[wy,Ky]=bu(!1),ar=s1(jl(T)),v$=ar.filter(V0),pf=T?.queue||X?.body?.queue||X?.queue||{},D8=kE(T,pf),k$=Ln(T),Dr=vU(pf,Tu),In=String(Tu||"default").trim()||"default",b0=Dr.filter((B)=>String(B?.id||"")!==In),b1=Ri(Dr,Xu),gn=Number((bl(Xu)?pf?.total:b1?.total)??k$.total??ar.length),Gy=Y_(pf),f7=bl(Xu)?Gy:[String(Ri(Dr,Xu)?.activeTaskId||"")].filter(Boolean),v1=kU(pf,Dr,Xu,ar),l7=bl(Xu)?O5(pf):O5(b1||{}),I$=O5(pf),X8=bE(I$),g$=Math.max(vE(I$),Gy.length),Y8=Cf((bl(Xu)?pf?.unreadTerminal:b1?.unreadTerminal)??v$.length),U0=T?v$.length:Y8,k1=bl(Xu)?"All queues":p5(b1||{id:Xu,name:Xu}),sn=S5(fu),Ul=sn.length>0,s$=Ul?s1(jl(tu)):[],zy=Ln(tu),fr=Ul?s$:ar,r7=fr.filter(V0),Kw=fr.filter((B)=>!xr(B)).sort(oT),Gw=fr.filter((B)=>xr(B)&&!V0(B)),n7=Ul?zy:k$,I1=Ul?Number(zy.total??s$.length):gn,i7=n7.hasMore===!0&&String(n7.nextBeforeId||"").length>0,S8=Ul?P:wy,zw=i?gT(i):{},Tw=i?sT(i):{},p8=xU(()=>UE(uu),[uu]),Q0=xU(()=>{let B=gU(Jl);return p8.flatMap((M)=>Array.from({length:B},()=>QE(M,g)))},[p8,Jl,g]),Ty=Q0.length,y7=Ty>1&&!pl,Ew=rf||$f||Ty===0||y7,_7=eE(pf,cu),a$=uZ(pf,vf),$7=fZ(pf,dl),Zw=D5(pf,dl,vf),m8=b?.id&&b?.activeTurnId&&String(b?.status)==="running",Ow=b?.id&&!["succeeded","failed","canceled"].includes(String(b?.status||"")),Hw=b?.id&&["succeeded","failed","canceled"].includes(String(b?.status||"")),g1=b?.id&&wQ(b);function Nr(B){let M=typeof B==="function"?B(m.current):B;return m.current=M,S(M),M}function Bw(B,M,d=!0){let nu=Array.from(new Set(B.map((Fu)=>String(Fu||"")).filter(Boolean)));for(let Fu of nu)if(Y.current.set(Fu,M),d)p.current.add(Fu);return nu}function t7(B){for(let M of B.map((d)=>String(d||"")).filter(Boolean))Y.current.delete(M),p.current.delete(M)}function o$(B){let M=String(B?.id||""),d=M?Y.current.get(M):void 0;if(!d)return B;if(String(B?.status||"").length>0&&!xr(B))return Y.current.delete(M),p.current.delete(M),B;return{...B,readAt:B?.readAt||d,terminalUnread:!1}}function P8(B){let M=String(B?.id||"");return M.length>0&&p.current.has(M)&&xr(B)}function s1(B,M=!0){let d=[];for(let nu of Array.isArray(B)?B:[]){let Fu=o$(nu);if(M&&P8(Fu))continue;d.push(Fu)}return d}function Vw(B,M=!0){if(!B||!Array.isArray(B?.tasks))return B;let d=s1(jl(B),M),nu=Ln(B);return{...B,tasks:d,pagination:B.pagination?{...nu,returned:d.length}:B.pagination}}function Dw(B){let M=String(B||pf?.mainProviderId||"main-server").trim()||"main-server";ll(M),pu(D5(pf,dl,M))}function Xw(B){let M=String(B||"default").trim()||"default",d=vf;if(M==="windows-native"){if(!a$.find((Fu)=>Fu.id===vf)?.supportsWindowsNativeCodex)d=String(a$.find((Fu)=>Fu.supportsWindowsNativeCodex)?.id||vf||"D601"),ll(d)}el(M),pu(D5(pf,M,d))}function d$(B,M,d=null,nu=null){let Fu=new Set(Bw(B,M));if(Fu.size===0&&nu===null&&d===null)return;Nr((Ku)=>{if(!Ku)return Ku;let Lu=jl(Ku).flatMap((Cu)=>{let xu=String(Cu?.id||"");if(!Fu.has(xu)){let jf=o$(Cu);return P8(jf)?[]:[jf]}let mu=nu&&String(nu?.id||"")===xu?nu:{},Ru={...Cu,...mu,readAt:M,terminalUnread:!1};return P8(Ru)?[]:[Ru]});return{...Ku,queue:d||Ku.queue,tasks:Fu.size>0?Pi([Lu],v1):Lu}});for(let Ku of Fu){let Lu=O.current.get(Ku);if(Lu?.task){let Cu=nu&&String(nu?.id||"")===Ku?nu:{},xu={...Lu.task,...Cu,readAt:M,terminalUnread:!1};if(O.current.set(Ku,{...Lu,task:xu}),c.current===Ku)o(xu)}}}wn(()=>{qr(!1)},[uu,Jl,g]),wn(()=>{let B=S5(fu);F.current+=1;let M=F.current;if(!i||B.length===0){ju(null),qu(!1),e(!1),w.current=!1;return}qu(!0),ju(null);let d=window.setTimeout(()=>{(async()=>{try{let nu=await iE(l,Xu,B);if(M!==F.current)return;ju(Vw(nu))}catch(nu){if(M===F.current)ju(null),Tf(cl(nu,"搜索 Codex tasks 失败"))}finally{if(M===F.current)qu(!1)}})()},240);return()=>window.clearTimeout(d)},[i?.id,l,Xu,fu]),wn(()=>{Ou(b?Rt(b):""),Iu(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},[k]);function q0(B,M,d){let nu=O.current.get(B)||{},Fu=nu.task||{},Ku=Array.isArray(Fu.transcript)?Fu.transcript:[],Lu=uQ(Fu,M),Cu=Object.prototype.hasOwnProperty.call(M,"transcript")?V5(Ku,Array.isArray(M.transcript)?M.transcript:[]):Ku,xu={...Fu,...Lu,transcript:Cu,output:Array.isArray(Lu.output)?R5(Fu,Lu,"output"):Array.isArray(Fu.output)?Fu.output:[],events:Array.isArray(Lu.events)?R5(Fu,Lu,"events"):Array.isArray(Fu.events)?Fu.events:[]},mu=o$(xu),Ru=String(mu?.updatedAt||""),jf=Boolean(M._transcriptComplete)&&xr(mu),yl=Boolean(nu.complete)&&xr(mu)&&String(nu.completeUpdatedAt||"")===Ru,ou=jf||yl,ef={...nu,task:mu,maxSeq:Ct(Cu),complete:ou,completeUpdatedAt:ou?Ru:""};if(O.current.set(B,ef),d===U.current&&c.current===B)o(mu);return ef}async function a1(B,M=!1,d,nu){if(!i||!B)return;let Ku=O.current.get(B)?.task;if(!M&&Pt(Ku))return;let Lu=B,Cu=N.current.get(Lu);if(Cu){if(M||!Pt(Ku))Cu.refreshAfter=!0;return Cu.promise}let xu=U.current,mu=performance.now();if(c.current===B)x(!0);let Ru={promise:Promise.resolve(),refreshAfter:!1},jf=(async()=>{try{let yl=await _E(l,B);if(xu!==U.current||c.current!==B)return;let ou=yl?.summary||{},ef=String(ou.updatedAt||"");q0(B,{id:B,status:ou.status,updatedAt:ef,startedAt:ou.startedAt,finishedAt:ou.finishedAt,currentAttempt:ou.currentAttempt,maxAttempts:ou.maxAttempts,finalResponse:ou.finalResponse,lastJudge:ou.lastJudge,lastError:ou.lastError,attempts:Array.isArray(ou.attempts)?ou.attempts:[],stepCount:ou.stepCount,llmStepCount:ou.llmStepCount,traceStats:ou.traceStats,statsSource:ou.statsSource,timing:ou.timing,_traceSummary:ou,_traceSummaryLoaded:!0,_traceSummaryUpdatedAt:ef,_detailLoaded:!0},xu),sr({phase:"complete",taskId:B,queueMs:nu??0,detailMs:performance.now()-mu,totalMs:d===void 0?performance.now()-mu:performance.now()-d,chunks:1,transcriptRows:Number(ou?.execution?.traceLineCount||ou?.execution?.stepCount||0),partial:!1,completedAt:new Date})}finally{let yl=Boolean(Ru.refreshAfter&&c.current===B&&!Pt(O.current.get(B)?.task));if(N.current.delete(Lu),xu===U.current&&c.current===B)x(!1);if(yl)window.setTimeout(()=>{a1(B,!0).catch((ou)=>Tf(cl(ou,"自动刷新 Trace Summary 失败")))},0)}})();Ru.promise=jf,N.current.set(Lu,Ru),await jf}async function Yw(B,M=null){let d=c.current;if(!i||!d||!B)return;let nu=O.current.get(d)?.task,Fu=xt(nu),Ku=B==="feedback"||B==="judge-feedback"?qQ(M):B;if(Fu[Ku]?.text)return;let Lu=`${d}:${Ku}`,Cu=q.current.get(Lu);if(Cu)return Cu;let xu=U.current;if(c.current===d)x(!0);let mu=(async()=>{try{let Ru=await $E(l,d,B,M);if(xu!==U.current||c.current!==d)return;let jf=O.current.get(d)?.task,yl=xt(jf);q0(d,{...B==="full"?{prompt:String(Ru?.text||""),promptChars:Number(Ru?.chars||0)}:{},_promptDetails:{...yl,[Ku]:Ru}},xu)}finally{if(q.current.delete(Lu),xu===U.current&&c.current===d)x(!1)}})();q.current.set(Lu,mu),await mu}async function M8(B=null,M={}){let d=c.current;if(!i||!d)return;let nu=O.current.get(d)?.task,Fu=B===null||B===void 0||String(B).length===0?"":String(B),Ku=P5(nu,Fu||null),Lu=Boolean(M.force),Cu=Boolean(M.incremental);if(Ku&&!Lu)return;let xu=NQ(nu,Fu||null),mu=Cu&&xu.length>0?BE(xu):0,Ru=`${d}:${Fu||"all"}:${mu}`,jf=W.current.get(Ru);if(jf)return jf;let yl=U.current;if(c.current===d)x(!0);let ou=(async()=>{try{let ef=await tE(l,d,mu,500,Fu||null);if(yl!==U.current||c.current!==d)return;let v0=Array.isArray(ef?.steps)?ef.steps:[],k0=mu>0?VE(xu,v0):v0;if(Fu){let I0=O.current.get(d)?.task,o1=Lf(I0?._traceStepsByAttempt)||{},_l=Lf(I0?._traceStepsLoadedByAttempt)||{},N0=Lf(I0?._traceStepsNextAfterSeqByAttempt)||{};q0(d,{_traceStepsByAttempt:{...o1,[Fu]:k0},_traceStepsLoadedByAttempt:{..._l,[Fu]:!0},_traceStepsNextAfterSeqByAttempt:{...N0,[Fu]:ef?.nextAfterSeq}},yl)}else q0(d,{_traceSteps:k0,_traceStepsLoaded:!0,_traceStepsHasMore:Boolean(ef?.hasMore),_traceStepsNextAfterSeq:ef?.nextAfterSeq},yl)}finally{if(W.current.delete(Ru),yl===U.current&&c.current===d)x(!1)}})();W.current.set(Ru,ou),await ou}async function Sw(B){let M=c.current,d=String(B??"");if(!i||!M||d.length===0)return;let nu=O.current.get(M)?.task;if(M5(nu)[d]?.line)return;let Ku=`${M}:${d}`,Lu=z.current.get(Ku);if(Lu)return Lu;let Cu=U.current;if(c.current===M)x(!0);let xu=(async()=>{try{let mu=await AE(l,M,B);if(Cu!==U.current||c.current!==M)return;let Ru=O.current.get(M)?.task,jf=M5(Ru);q0(M,{_traceStepDetails:{...jf,[d]:mu}},Cu)}finally{if(z.current.delete(Ku),Cu===U.current&&c.current===M)x(!1)}})();z.current.set(Ku,xu),await xu}function pw(B){if(c.current!==B)return;let M=O.current.get(B)?.task;if(!M)return;if(P5(M,null))M8(null,{force:!0,incremental:!0}).catch((nu)=>Tf(cl(nu,"增量刷新 Trace Steps 失败")));let d=Lf(M?._traceStepsLoadedByAttempt)||{};for(let nu of Object.keys(d).filter((Fu)=>d[Fu]))M8(nu,{force:!0,incremental:!0}).catch((Fu)=>Tf(cl(Fu,"增量刷新 Attempt Trace Steps 失败")))}async function Rp(B,M,d){if(!i||!B)return;let nu=performance.now(),Fu=U.current,Ku=O.current.get(B);if(Ku?.task){if(o(Ku.task),x(X_(Ku.task)||!Ku.complete),!X_(Ku.task)&&Ku.complete&&xr(Ku.task)&&String(Ku.completeUpdatedAt||"")===String(Ku.task?.updatedAt||"")){sr({phase:"complete",taskId:B,queueMs:d??0,detailMs:0,totalMs:M===void 0?0:performance.now()-M,chunks:0,transcriptRows:Array.isArray(Ku.task.transcript)?Ku.task.transcript.length:0,completedAt:new Date});return}}else x(!0);let Lu=J.current;if(Lu?.taskId===B&&Lu.token===Fu)return Lu.promise;let Cu=(async()=>{try{let xu=await Rf(xf(l,`/api/tasks/${encodeURIComponent(B)}?meta=1`));if(Fu!==U.current||c.current!==B)return;let mu=O.current.get(B),Ru=Array.isArray(mu?.task?.transcript)?mu.task.transcript:[],jf=xu?.task||{},yl=Boolean(mu?.complete)&&String(mu?.completeUpdatedAt||"")===String(jf?.updatedAt||"");q0(B,{...jf,summaryOnly:!1,_metaLoaded:!0,transcript:Ru,_detailLoaded:Ru.length>0,_transcriptComplete:yl},Fu);let ou=X_(mu?.task)||Boolean(mu?.task?._transcriptPreview),ef=ou?0:Ru.length>0?fQ(Ru):0,v0=!ou&&mu?.complete&&xr(jf)&&String(mu?.completeUpdatedAt||"")===String(jf?.updatedAt||"")?Ct(Ru):ef,k0=!0,I0=0,o1=Ru.length;while(k0){let _l=await Rf(xf(l,`/api/tasks/${encodeURIComponent(B)}/transcript?afterSeq=${encodeURIComponent(String(v0))}&limit=${vT}&fullText=1`));if(Fu!==U.current||c.current!==B)return;let N0=O.current.get(B),e$=Array.isArray(N0?.task?.transcript)?N0.task.transcript:[],If=V5(e$,Array.isArray(_l?.transcript)?_l.transcript:[]);I0+=1,o1=If.length;let u3=Boolean(!_l?.hasMore);if(q0(B,{status:_l?.status||jf.status,updatedAt:_l?.updatedAt||jf.updatedAt,transcript:If,_detailLoaded:u3||If.length>0,_transcriptComplete:u3,_transcriptPreview:ou&&!u3},Fu),k0=Boolean(_l?.hasMore),v0=Number(_l?.nextAfterSeq??Ct(If)),!k0)break;await new Promise((d1)=>window.setTimeout(d1,0))}sr({phase:"complete",taskId:B,queueMs:d??0,detailMs:performance.now()-nu,totalMs:M===void 0?performance.now()-nu:performance.now()-M,chunks:I0,transcriptRows:o1,completedAt:new Date})}finally{if(J.current?.taskId===B&&J.current?.token===Fu)J.current=null;if(Fu===U.current&&c.current===B)x(!1)}})();J.current={taskId:B,token:Fu,promise:Cu},await Cu}async function Pl(B=c.current,M=!0,d=Xu){if(!i)return;if(!M&&h.current)return;let nu=performance.now();if(M)h.current=!0;if(M)sr({phase:"loading",taskId:String(B||c.current||""),startedAt:new Date});let Fu=j.current+1;j.current=Fu;let Ku=String(B||c.current||""),Lu=Ku?O.current.get(Ku):null,Cu=Array.isArray(Lu?.task?.transcript)?Lu.task.transcript:[],xu=fQ(Cu),mu=null;if(mu=await yE(l,Ku,xu,d),Fu!==j.current){if(M)h.current=!1;return}let Ru=performance.now()-nu;v(X||{});let jf=mu?.queue||{},yl=String(jf?.activeTaskId||Y_(jf)[0]||""),ou=mu;Nr((rr)=>{let Ey=jl(mu),an=jl(rr),Zy=an.length>0?Pi([an,Ey],yl):Pi([Ey],yl),f3=s1(Zy),AK=Ln(mu),l3=Ln(rr),cK=an.length>Ey.length&&(l3.hasMore===!1||String(l3.nextBeforeId||"").length>0),jK={...AK,...cK?{hasMore:l3.hasMore,nextBeforeId:l3.nextBeforeId}:{},returned:f3.length};return ou={...mu,tasks:f3,pagination:jK},ou});let ef=jl(ou),v0=vU(jf,Tu),k0=kU(jf,v0,d,ef),I0=nE(v0,d,ef),o1=Ku||c.current,_l=ou?.selected||null,N0=_l?.task||null,e$=Array.isArray(_l?.transcript)?_l.transcript:null,If=o1||k0||I0||ef[0]?.id||"";if(c.current!==If)U.current+=1;c.current=If,I(If);let d1=ef.find((rr)=>rr.id===If);if(d1){let rr=O.current.get(If);if(rr?.task)O.current.set(If,{...rr,task:{...d1,...rr.task,status:d1.status,updatedAt:d1.updatedAt}})}if(N0?.id===If&&e$!==null){let rr=O.current.get(If),Ey=Array.isArray(rr?.task?.transcript)?rr.task.transcript:[],an=V5(Ey,e$),Zy=Boolean(_l?.preview);if(q0(If,{...N0,_summaryLoaded:!0,transcript:an,_detailLoaded:!_l?.hasMore||an.length>0,_transcriptComplete:!Zy&&!_l?.hasMore&&xr(N0),_transcriptPreview:Zy},U.current),x(!1),M)sr({phase:"complete",taskId:If,queueMs:Ru,detailMs:Math.max(0,performance.now()-nu-Ru),totalMs:performance.now()-nu,chunks:1,transcriptRows:an.length,partial:Boolean(Zy||_l?.hasMore||X_(N0)),completedAt:new Date});if(b$(new Date),M)h.current=!1;a1(If,!1,M?nu:void 0,M?Ru:void 0).catch((f3)=>Tf(cl(f3,"加载 Codex Trace Summary 失败")));return}if(M)sr({phase:"session",taskId:If,queueMs:Ru,totalMs:Ru,startedAt:new Date(Date.now()-Ru)});if(If)a1(If,!0,M?nu:void 0,M?Ru:void 0).catch((rr)=>Tf(cl(rr,"加载 Codex Trace Summary 失败")));else if(U.current+=1,o(null),x(!1),M)sr({phase:"complete",taskId:"",queueMs:Ru,detailMs:0,totalMs:performance.now()-nu,chunks:0,transcriptRows:0,completedAt:new Date});if(b$(new Date),M)h.current=!1}async function A7(){if(Ul){if(!i||P||w.current)return;let M=String(zy.nextBeforeId||"");if(!M)return;w.current=!0,e(!0),Tf("");try{let d=await IU(l,Xu,M,nQ,sn),nu=jl(d),Fu=d?.queue||pf||{},Ku=String(Fu?.activeTaskId||Y_(Fu)[0]||v1||"");ju((Lu)=>{let Cu=s1(Pi([jl(Lu),nu],Ku)),xu=Ln(d);return{...Lu||{},queue:Fu,tasks:Cu,pagination:{...xu,returned:Cu.length}}})}catch(d){Tf(cl(d,"加载更多搜索结果失败"))}finally{w.current=!1,e(!1)}return}if(!i||wy||L.current)return;let B=String(Ln(T).nextBeforeId||"");if(!B)return;L.current=!0,Ky(!0),Tf("");try{let M=await IU(l,Xu,B),d=jl(M),nu=M?.queue||pf||{},Fu=String(nu?.activeTaskId||Y_(nu)[0]||v1||"");Nr((Ku)=>{let Lu=s1(Pi([jl(Ku),d],Fu)),Cu=Ln(M);return{...Ku||{},queue:nu,statistics:M?.statistics||Ku?.statistics,tasks:Lu,pagination:{...Cu,returned:Lu.length}}})}catch(M){Tf(cl(M,"加载更早 Codex tasks 失败"))}finally{L.current=!1,Ky(!1)}}function mw(B){let M=B.currentTarget;if(!M||S8||!i7)return;if(M.scrollHeight-M.scrollTop-M.clientHeight<120)A7()}async function lr(B,M){C$(!0),Tf("");try{await B()}catch(d){Tf(cl(d,M))}finally{C$(!1)}}async function C8(B){if(!B)return;try{let M=!1;try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(B),M=!0}catch{M=!1}if(!M){let nu=document.createElement("textarea");nu.value=B,nu.style.position="fixed",nu.style.opacity="0",document.body.appendChild(nu),nu.select(),M=document.execCommand("copy"),document.body.removeChild(nu)}if(!M)throw Error("browser clipboard rejected the copy request");R$(B);let d=`已复制任务 ID:${B}`;kf(d),ur("success",d),window.setTimeout(()=>R$((nu)=>nu===B?"":nu),1600)}catch(M){Tf(`复制任务 ID 失败:${cl(M)}`)}}function R8(B){if(!B)return;Qu(B);let M=`已引用任务 ID:${B};提交时后端会读取并注入该任务上下文`;kf(M),ur("success",M)}async function x8(B){if(!i||!B)return;let M=new Date().toISOString();j.current+=1,d$([B],M,null,{id:B,readAt:M,terminalUnread:!1}),Ly(B);let d=!1;if(await lr(async()=>{let nu=await cE(l,B),Fu=nu?.task||{id:B,readAt:new Date().toISOString(),terminalUnread:!1},Ku=String(Fu?.readAt||new Date().toISOString());d$([B],Ku,nu?.queue||null,Fu),d=!0;let Lu=`已将任务 ${B} 标为已读`;kf(Lu),ur("success",Lu)},"标记 Codex task 已读失败"),!d)t7([B]),Pl(c.current,!1).catch((nu)=>Tf(cl(nu,"刷新 Codex tasks 失败")));Ly((nu)=>nu===B?"":nu)}async function Pw(){if(!i||h1)return;x$(!0);let B=new Date().toISOString(),M=Array.from(new Set([...jl(m.current).filter(V0).map((nu)=>String(nu?.id||"")).filter(Boolean),...Array.from(O.current.entries()).filter(([,nu])=>V0(nu?.task)).map(([nu])=>nu)]));if(j.current+=1,M.length>0)d$(M,B);let d=!1;if(await lr(async()=>{let nu=await jE(l),Fu=String(nu?.readAt||new Date().toISOString()),Ku=jl(m.current).filter(V0).map((Ru)=>String(Ru?.id||"")).filter(Boolean),Lu=Array.from(O.current.entries()).filter(([,Ru])=>V0(Ru?.task)).map(([Ru])=>Ru),Cu=Array.from(new Set([...M,...Ku,...Lu]));d$(Cu,Fu,nu?.queue||null);let xu=Number(nu?.count||Cu.length);d=!0;let mu=`已将 ${xu} 个已结束未读任务标为已读`;kf(mu),ur("success",mu)},"全部标为已读失败"),!d&&M.length>0)t7(M),Pl(c.current,!1).catch((nu)=>Tf(cl(nu,"刷新 Codex tasks 失败")));x$(!1)}function Mw(B){let M=B||Gn;if(uf(M),!bl(M))Zu(M);if(Nr(null),!(bl(M)?c.current:""))c.current="",U.current+=1,I(""),o(null),x(!0)}async function Cw(){let B=typeof window>"u"?"":window.prompt("输入新的 Codex queue ID(字母/数字/._-,最长 64)","new-lane"),M=String(B||"").trim();if(!M)return;await lr(async()=>{let d=await Rf(xf(l,"/api/queues"),{method:"POST",body:{queueId:M}}),nu=String(d?.queue?.id||M);Zu(nu),uf(nu),Nr(null),c.current="",U.current+=1,I(""),o(null);let Fu=`已创建并切换到 queue:${nu}`;kf(Fu),ur("success",Fu),await Pl("",!0,nu)},"创建 Codex queue 失败")}async function Rw(){let B=String(Tu||"default").trim()||"default",M=Ri(Dr,B)||{id:B,name:B},d=typeof window>"u"?null:window.prompt(`输入 queue 显示名称(ID 不变:${B};留空恢复为 ID)`,$Q(M));if(d===null)return;await lr(async()=>{let nu=await Rf(xf(l,`/api/queues/${encodeURIComponent(B)}`),{method:"PATCH",body:{name:String(d)}}),Fu=nu?.queue||{id:B,name:String(d||B)};if(nu?.summary)Nr((Lu)=>Lu?{...Lu,queue:nu.summary}:Lu);let Ku=`已更新 queue 名称:${p5(Fu)}`;kf(Ku),ur("success",Ku),await Pl(c.current,!0,Xu)},"修改 Codex queue 名称失败")}function xw(){if(b0.length===0){kf("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let B=b0.some((M)=>String(M?.id||"")===Pf)?Pf:"";Sl(B),Jf(!0)}async function hw(){let B=In;if(b0.length===0){kf("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let d=String(Pf||""||"").trim();if(!d){kf("请先选择要合并的源 queue。");return}if(d===B){Tf("源 queue 和目标 queue 不能相同。");return}await lr(async()=>{let nu=await Rf(xf(l,`/api/queues/${encodeURIComponent(B)}/merge`),{method:"POST",body:{sourceQueueId:d}});if(nu?.summary)Nr((Lu)=>Lu?{...Lu,queue:nu.summary}:Lu);Zu(B),uf(B),Nr(null);let Fu=Number(nu?.mergedTaskCount||0),Ku=`已将 queue=${d} 合并到 ${B},移动 ${Fu} 个任务;源 queue 已自动删除。`;kf(Ku),ur("success",Ku),Jf(!1),Sl(""),await Pl(c.current,!0,B)},"合并 Codex queue 失败")}async function bw(B){if(B.preventDefault(),Q.current){kf("任务正在提交中,请等待当前请求完成,已阻止重复提交。");return}if(Q0.length>1&&!pl){Tf(`检测到将创建 ${Q0.length} 个任务;请先勾选“确认批量入队”,避免误传多个任务。`);return}Q.current=!0,C1(!0),kf("正在提交 Code Queue 任务,请等待后端确认,输入已临时锁定。"),await lr(async()=>{if(Q0.length===0)throw Error("prompt 不能为空");let M=q1(g),d=Tu.trim()||"default",nu=[...Q0],Fu=(Ru)=>({prompt:Ru,queueId:d,providerId:vf,executionMode:dl,model:cu,cwd:Tl,maxAttempts:Number(rl),...M.length>0?{referenceTaskIds:M}:{}}),Ku=nu.length===1?Fu(nu[0]):{tasks:nu.map(Fu)},Lu=await Rf(xf(l,nu.length===1?"/api/tasks":"/api/tasks/batch"),{method:"POST",body:Ku}),Cu=Lu?.tasks?.[0]?.id||"",xu=Array.isArray(Lu?.tasks)?Lu.tasks.map((Ru)=>String(Ru?.id||"")).filter(Boolean):[],mu=`已创建 ${xu.length||nu.length} 个任务${xu.length>0?`:${xu.join(" / ")}`:""}`;if(kf(mu),ur("success",mu),Wu(""),Qu(""),qr(!1),c.current=Cu,Xu!==d)Nr(null);Zu(d),await Pl(Cu,!0,d)},"Codex 任务入队失败"),Q.current=!1,C1(!1)}async function vw(B){if(B.preventDefault(),!b?.id)return;await lr(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/steer`),{method:"POST",body:{prompt:kn}}),R1(""),await Pl(b.id)},"追加 prompt 失败")}async function kw(B){B.preventDefault();let M=String(b?.id||"");if(!M||!g1)return;await lr(async()=>{let d=q1(Yu),nu=await Rf(xf(l,`/api/tasks/${encodeURIComponent(M)}/edit`),{method:"POST",body:{prompt:lu,referenceTaskIds:d}}),Fu={...nu?.task||b||{},_traceSummary:null,_traceSummaryLoaded:!1,_traceSummaryUpdatedAt:"",_promptDetails:{},_traceSteps:[],_traceStepsLoaded:!1,_traceStepsByAttempt:{},_traceStepsLoadedByAttempt:{},_traceStepsNextAfterSeqByAttempt:{},_traceStepDetails:{}};O.current.set(M,{...O.current.get(M)||{},task:Fu,complete:!1,completeUpdatedAt:""}),c.current=M,o(Fu),I(M),Ou(Rt(Fu)),Iu(Array.isArray(Fu?.referenceTaskIds)?Fu.referenceTaskIds.join(" "):""),Nr((Lu)=>{if(!Lu)return Lu;let Cu=jl(Lu).map((xu)=>String(xu?.id||"")===M?{...xu,...Fu}:xu);return{...Lu,queue:nu?.queue||Lu.queue,tasks:Pi([Cu],v1)}});let Ku=nu?.changed===!1?`任务 ${M} 的 prompt 未变化`:`已更新 queued 任务 ${M} 的用户 prompt`;kf(Ku),ur("success",Ku),await Pl(M,!0,Xu)},"编辑 queued 任务 prompt 失败")}async function Iw(){if(!b?.id)return;await lr(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/interrupt`),{method:"POST",body:{}}),await Pl(b.id)},"打断 Codex session 失败")}async function gw(){if(!b?.id)return;await lr(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/retry`),{method:"POST",body:{}}),await Pl(b.id)},"重新入队失败")}async function sw(B){let M=String(b?.id||""),d=String(B||"").trim();if(!M||!d)return;let nu=p_(b);if(d===nu){kf(`任务 ${M} 已在 queue=${d}`);return}await lr(async()=>{let Ku=(await Rf(xf(l,`/api/tasks/${encodeURIComponent(M)}/move`),{method:"POST",body:{queueId:d}}))?.task||{...b,queueId:d};if(O.current.set(M,{...O.current.get(M)||{},task:Ku}),c.current=M,o(Ku),I(M),Zu(d),!bl(Xu))Nr(null),uf(d);let Lu=`已将任务 ${M} 从 ${nu} 移动到 ${d}`;kf(Lu),ur("success",Lu),await Pl(M,!0,bl(Xu)?Gn:d)},"移动任务 queue 失败")}async function aw(){let B=c.current;if(!B)return;let M=performance.now();await lr(async()=>{sr({phase:"session",taskId:B,queueMs:0,totalMs:0,partial:!0,startedAt:new Date}),await a1(B,!0,M,0)},"刷新 Trace Summary 失败")}function ow(B){c.current=B,U.current+=1,I(B);let M=O.current.get(B);if(M?.task)o(M.task),x(!1);else{x(!0);let d=ar.find((nu)=>nu.id===B);if(d)o(d);else o(null)}Pl(B).catch((d)=>Tf(cl(d,"切换 Codex session 失败")))}function h8(B){if(ow(B),fE())df(!1)}function c7(B,M,d){if(!B||!Array.isArray(B?.tasks)||M.length===0||Object.keys(d).length===0)return B;let nu=!1,Fu=jl(B).map((Ku)=>{if(String(Ku?.id||"")!==M)return Ku;return nu=!0,o$(uQ(Ku,d))});return nu?{...B,tasks:Fu}:B}function dw(B,M){Nr((d)=>c7(d,B,M)),ju((d)=>c7(d,B,M))}function ew(B,M,d){let nu=String(B?.type||"");if(nu==="queue-updated")return!0;if(nu==="trace-stats-updated"||nu==="trace-step-created")return!1;if(M.length===0)return!0;if(!d)return!0;if(B?.queueId&&String(B.queueId)!==p_(d))return!0;if(B?.status&&String(B.status)!==String(d?.status||""))return!0;return String(B?.reason||"")!=="output"}function j7(){if(!i||!Z5())return;if(H.current!==null)window.clearTimeout(H.current);H.current=window.setTimeout(()=>{H.current=null,Pl(c.current,!1).catch((B)=>Tf(cl(B,"Code Queue 事件刷新失败")))},120)}function uK(B,M){if(!i||!Z5()||c.current!==B)return;if(D.current=D.current||M,E.current!==null)return;E.current=window.setTimeout(()=>{E.current=null;let d=D.current;if(D.current=!1,a1(B,!0).catch((nu)=>Tf(cl(nu,"事件刷新 Trace Summary 失败"))),d)pw(B)},250)}function fK(B){let M=Lf(B?.payload)||B,d=Lf(M?.stats),nu=String(B?.type||M?.type||""),Fu=String(M?.subjectKind||d?.subjectKind||""),Ku=String(M?.scopeId||d?.scopeId||""),Lu=String(M?.taskId||(Fu==="task"?M?.subjectId:"")||d?.taskId||B?.taskId||""),Cu=M?.attemptIndex??d?.attemptIndex,xu=Cu===null||Cu===void 0||Cu===""?null:D0(Cu),mu=d||Lf(M?.traceStats),Ru=mu?.stepCount??mu?.llmStepCount,jf=mu?.outputMaxSeq;return{...M,type:nu,eventId:B?.eventId||M?.eventId,sequence:B?.sequence??M?.sequence,taskId:Lu,subjectKind:Fu,scopeId:Ku,attemptIndex:xu,stepCount:Ru,outputMaxSeq:jf,updatedAt:mu?.updatedAt||M?.updatedAt||B?.createdAt,traceStats:mu,statsSource:mu?"oa-event-flow":M?.statsSource}}function lK(B){let M=fK(B),d=String(M?.taskId||""),nu=String(M?.scopeId||M?.traceStats?.scopeId||""),Fu=String(M?.subjectKind||M?.traceStats?.subjectKind||"")==="task-attempt"||Number(M?.attemptIndex)>0||/:attempt:\d+$/u.test(nu),Ku=sU(M?.stepCount),Lu={},Cu=d.length>0?jl(m.current).find((xu)=>String(xu?.id||"")===d):null;if(d.length>0){if(M?.status)Lu.status=String(M.status);if(M?.updatedAt)Lu.updatedAt=String(M.updatedAt);if(M?.queueId)Lu.queueId=String(M.queueId);if(!Fu&&Number.isFinite(Number(M?.stepCount)))Lu.stepCount=Ku,Lu.llmStepCount=Ku;if(!Fu&&Number.isFinite(Number(M?.outputMaxSeq)))Lu.outputMaxSeq=sU(M.outputMaxSeq);if(!Fu&&Lf(M?.traceStats))Lu.traceStats=M.traceStats,Lu.statsSource="oa-event-flow";if(Object.keys(Lu).length>0&&(O.current.has(d)||c.current===d))q0(d,Lu,U.current);if(Object.keys(Lu).length>0)dw(d,Lu);if(c.current===d&&(M?.type==="trace-step-created"||M?.type==="task-updated"||M?.type==="trace-stats-updated")){let xu=jQ(Cu),mu=M?.type==="trace-step-created"||M?.type==="trace-stats-updated"&&!Fu&&Number.isFinite(Number(M?.stepCount))&&(xu===null||Ku>xu);uK(d,mu)}}if(ew(M,d,Cu))j7()}wn(()=>{if(V.current){V.current=!1;return}lr(()=>Pl(c.current),"Code Queue 加载失败")},[i?.id,Xu]),wn(()=>{if(!i||typeof EventSource>"u")return;let B=new EventSource(aT(l),{withCredentials:!0}),M=(nu)=>{try{lK(JSON.parse(String(nu.data||"{}")))}catch(Fu){Tf(cl(Fu,"解析 Code Queue 事件失败"))}},d=()=>{if(Z5())j7()};return B.addEventListener("trace-step-created",M),B.addEventListener("task-updated",M),B.addEventListener("queue-updated",M),B.addEventListener("trace-stats-updated",M),document.addEventListener("visibilitychange",d),()=>{if(B.close(),document.removeEventListener("visibilitychange",d),H.current!==null)window.clearTimeout(H.current),H.current=null;if(E.current!==null)window.clearTimeout(E.current),E.current=null}},[i?.id,l,Xu]),wn(()=>{if(!i||!b||s)return;let B=String(b.id||"");if(!B)return;let M=String(b.updatedAt||"");if(Pt(b))return;let d=`${B}:${M||"unknown"}:${String(b?._traceSummaryUpdatedAt||"")}`;if(Z.current.has(d))return;Z.current.add(d),a1(B,!0).catch((nu)=>Tf(cl(nu,"自动加载 Trace Summary 失败")))},[i?.id,b?.id,b?.updatedAt,b?.traceStats?.statsRevision,b?._traceSummaryUpdatedAt,b?._traceSummaryLoaded,s]);let rK=fr.length===0?K(w1,{title:Ul?Gu?"搜索中":"没有匹配任务":"队列为空",text:Ul?Gu?`正在搜索包含“${sn}”的 task...`:`未找到包含“${sn}”的 task;可换个关键词或切换 queue。`:"提交一个任务后,Codex 会串行执行并保存输出。"}):[r7.length>0?K(X5,{key:"unread",title:"已结束未读",tasks:r7,selectedId:k,emptyText:"暂无已结束未读任务。",onSelect:h8,onCopy:C8,onReference:R8,onMarkRead:x8,copiedTaskId:Wy,markingReadTaskId:x1}):null,K(X5,{key:"active",title:"运行 / 排队",tasks:Kw,selectedId:k,emptyText:"当前没有运行或排队任务。",onSelect:h8,onCopy:C8,onReference:R8,onMarkRead:x8,copiedTaskId:Wy,markingReadTaskId:x1}),K(X5,{key:"history",title:"历史 session",tasks:Gw,selectedId:k,emptyText:"最近没有完成、失败或取消的 session。",onSelect:h8,onCopy:C8,onReference:R8,onMarkRead:x8,copiedTaskId:Wy,markingReadTaskId:x1}),K("div",{key:"pagination",className:"codex-task-pagination","data-testid":"codex-task-pagination"},K("span",null,Ul?`搜索“${sn}” · 已显示 ${fr.length} / ${Number.isFinite(I1)?I1:fr.length}`:`已加载 ${fr.length} / ${Number.isFinite(I1)?I1:fr.length}`),i7?K("button",{type:"button",className:"ghost-btn",disabled:S8,onClick:()=>void A7(),"data-testid":"codex-load-more-tasks-button"},S8?"加载中":Ul?"加载更多结果":"加载更早任务"):K("code",null,Ul?"已到结果末尾":"已到队列末尾"))],F7=(B,M=!1)=>K("label",{className:`code-queue-switcher ${M?"compact":""}`},K("span",null,M?"Queue":"查看 queue"),K("select",{value:Xu,onChange:(d)=>Mw(String(d.target.value||Gn)),"data-testid":B},K("option",{value:Gn},`All queues · ${Number.isFinite(gn)?gn:ar.length} tasks · ${Gy.length} running`),Dr.map((d)=>K("option",{key:String(d?.id||""),value:String(d?.id||"")},S_(d))))),nK=K("div",{className:"codex-task-search","data-testid":"codex-task-search"},K("label",{htmlFor:"codex-task-search-input"},"搜索 task"),K("div",{className:"codex-task-search-row"},K("input",{id:"codex-task-search-input",type:"search",value:fu,placeholder:"关键词 / task ID / prompt",autoComplete:"off",onChange:(B)=>$u(String(B.target.value||"")),"data-testid":"codex-task-search-input"}),fu?K("button",{type:"button",className:"ghost-btn",onClick:()=>$u(""),"data-testid":"codex-task-search-clear"},"清除"):null),K("small",{"data-testid":"codex-task-search-summary"},Ul?Gu?"搜索中...":`匹配 ${fr.length}/${Number.isFinite(I1)?I1:fr.length}`:"支持 task ID、prompt、状态、provider、模型和最近输出关键词")),iK=K("div",{className:"codex-trace-status","data-testid":"codex-trace-status-summary"},K("span",{className:"codex-trace-status-chip queued"},K("b",null,"排队"),String(X8)),K("span",{className:"codex-trace-status-chip running"},K("b",null,"运行"),String(g$)),K("span",{className:`codex-trace-status-chip unread ${U0>0?"warn":""}`},K("b",null,"结束未读"),String(U0)),K("span",{className:"codex-trace-status-chip service"},K("b",null,"服务"),`${zw.providerStatus||"unknown"} · ${i?.providerId||"main-server"} · ${Tw.public?"公网暴露":"仅 UniDesk frontend 代理访问"}`),K("span",{className:"codex-trace-status-chip"},K("b",null,"执行节点"),a$.map((B)=>B.id).join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"执行模式"),$7.map((B)=>B.id).join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"模型"),_7.join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"加载"),ml?.phase==="complete"?IT(ml?.totalMs):String(ml?.phase||"idle")),K("span",{className:"codex-trace-status-chip"},K("b",null,"刷新"),h$?tf(h$):"--")),yK=K(Mi,{title:b?`Trace ${String(b.id).slice(0,22)}`:"Trace 输出",eyebrow:b?`${b.status} / view=${k1} / task queue=${p_(b)} / provider=${b.providerId||"main-server"} / mode=${b.executionMode||"default"} / ${b.model} / agent loop trace`:`Agent loop trace / view=${k1}`,summary:iK,loading:s||wy||Gu||P||ml?.phase==="loading",actions:K("div",{className:"panel-actions"},F7("code-queue-filter-select"),K("button",{type:"button",className:"ghost-btn codex-mark-all-read-btn",disabled:U0===0||$f||h1,onClick:()=>void Pw(),"data-testid":"codex-mark-all-read-button"},h1?"标记中":`全部标已读${U0>0?` (${U0})`:""}`),b?K("button",{type:"button",className:"ghost-btn",disabled:s||$f,onClick:()=>void aw(),"data-testid":"codex-load-full-trace-button"},s?"加载中":cr(b)?"刷新 Summary":"加载 Summary"):null,K("button",{type:"button",className:"codex-session-title-toggle",onClick:()=>df((B)=>!B),"data-testid":"code-queue-sidebar-toggle"},ff?"收起队列":"展开队列"),K("label",{className:"inline-check"},K("input",{type:"checkbox",checked:Qf,onChange:(B)=>il(Boolean(B.target.checked))}),"自动滚动"),K("button",{type:"button",className:"ghost-btn",disabled:!Ow||$f,onClick:()=>void Iw(),"data-testid":"codex-interrupt-button"},"打断"),K("button",{type:"button",className:"ghost-btn",disabled:!Hw||$f,onClick:()=>void gw()},"重试"),b?K(_Q,{title:"Codex Task",data:b,onOpen:f,testId:"raw-codex-task"}):null),className:"codex-output-panel"},K("div",{className:`codex-session-shell ${ff?"":"queue-collapsed"}`},ff?K("aside",{className:"codex-session-sidebar","data-testid":"codex-session-sidebar"},K("div",{className:"codex-session-sidebar-head"},K("div",null,K("span",null,bl(Xu)?"All queues":"Queue lane"),K("strong",null,`${k1} · ${ar.length}/${Number.isFinite(gn)?gn:ar.length} sessions · 未读 ${U0}`)),K("button",{type:"button",className:"ghost-btn",onClick:()=>df(!1)},"收起")),F7("code-queue-filter-sidebar",!0),nK,K("div",{className:"codex-task-list codex-task-list-session",onScroll:mw,"data-testid":"codex-task-list-scroll"},rK)):null,K("div",{className:"codex-session-main"},K("div",{className:"codex-output-stack"},K(cZ,{task:b,loading:s,onLoadPromptPart:Yw,onLoadSteps:M8,onLoadStep:Sw}),K(jZ,{task:b})))));if(!i)return K(w1,{title:"Code Queue 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=code-queue"});let J7=Number(ml?.totalMs),U7=Number(ml?.queueMs),Q7=Number(ml?.detailMs),q7=Number(ml?.transcriptRows),_K=ml?.phase==="complete"?"complete":String(ml?.phase||"idle"),$K=Ri(Dr,In)||{id:In,name:In},tK=_f?K(RU,{title:"合并 queue",titleId:"codex-merge-dialog-title",className:"codex-merge-dialog",backdropClassName:"codex-merge-dialog-backdrop",bodyClassName:"codex-merge-dialog-body",actionsClassName:"codex-merge-dialog-actions",testId:"codex-merge-queue-dialog",closeTestId:"codex-merge-queue-close",disableClose:$f,onClose:()=>Jf(!1),actions:[K("button",{key:"cancel",type:"button",className:"ghost-btn",onClick:()=>Jf(!1),disabled:$f,"data-testid":"codex-merge-queue-cancel"},"取消"),K("button",{key:"confirm",type:"button",className:"primary-btn",onClick:()=>void hw(),disabled:$f||rf||!Pf,"data-testid":"codex-merge-queue-confirm"},$f?"合并中...":"确认合并")]},K("p",{className:"codex-merge-dialog-target"},"目标 queue:",K("code",null,S_($K))),K("label",null,"源 queue",K("select",{value:Pf,disabled:$f||rf,onChange:(B)=>Sl(String(B.target.value||"")),"data-testid":"codex-merge-source-queue-select"},K("option",{value:""},"选择要合并进来的源 queue"),b0.map((B)=>K("option",{key:String(B?.id||""),value:String(B?.id||"")},S_(B))))),K("p",{className:"codex-merge-dialog-note"},"会把源 queue 的任务归属合并到目标 queue,并自动删除源 queue;目标 queue 会按原 queueEnteredAt/createdAt 时间顺序运行。")):null;return K("div",{className:`code-queue-page ${n?"codex-standalone-page":""}`,"data-testid":"code-queue-page","data-load-state":_K,"data-load-total-ms":Number.isFinite(J7)?String(Math.round(J7*10)/10):"","data-load-queue-ms":Number.isFinite(U7)?String(Math.round(U7*10)/10):"","data-load-detail-ms":Number.isFinite(Q7)?String(Math.round(Q7*10)/10):"","data-load-transcript-rows":Number.isFinite(q7)?String(q7):"","data-load-task-id":String(ml?.taskId||k||""),"data-load-partial":ml?.partial?"true":"false"},K(yf,{error:V8,wide:!0}),tK,K("div",{className:"codex-session-stage codex-session-stage-top"},yK),K("div",{className:"code-queue-layout"},K("div",{className:"codex-left-rail"},K(Mi,{title:"提交任务",eyebrow:rf?"Submitting...":Q0.length>1?`${Q0.length} tasks`:"Single or Batch",className:"codex-compose-panel",loading:rf},K("form",{className:`codex-task-form ${rf?"is-submitting":""}`,onSubmit:bw,"data-testid":"code-queue-task-form","aria-busy":rf?"true":"false"},K("label",null,"Prompt / 多任务用单独一行 --- 分隔",K("textarea",{value:uu,rows:8,disabled:rf,onChange:(B)=>Wu(B.target.value),placeholder:"写入 Codex 任务;多个任务之间用 --- 分隔。"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选)",K("input",{value:g,disabled:rf,onChange:(B)=>Qu(B.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-reference-task-id"}),q1(g).length>0?K("code",null,`后端将解析并注入:${q1(g).join(" / ")}`):null),K("div",{className:"codex-form-grid"},K("label",{className:"codex-submit-queue-field"},"Queue",K("div",{className:"codex-submit-queue-row"},K("select",{className:"codex-submit-queue-select",value:Tu,disabled:rf,onChange:(B)=>Zu(String(B.target.value||"default")),"data-testid":"code-queue-id-select"},Dr.map((B)=>K("option",{key:String(B?.id||""),value:String(B?.id||"")},S_(B)))),K("button",{type:"button",className:"ghost-btn codex-rename-queue-btn",onClick:()=>void Rw(),disabled:$f||rf||!Tu,title:"修改当前 queue 的显示名称,ID 不变","data-testid":"codex-rename-queue-button"},"改名"),K("button",{type:"button",className:"ghost-btn codex-merge-queue-btn",onClick:()=>xw(),disabled:$f||rf||b0.length===0,title:"打开独立窗口选择源 queue 并合并到当前 queue;合并后自动删除源 queue","data-testid":"codex-merge-queue-button"},"合并 queue"),K("button",{type:"button",className:"ghost-btn codex-create-queue-btn",onClick:()=>void Cw(),disabled:$f||rf,"data-testid":"codex-create-queue-button"},"创建 queue"))),K("label",null,"模型",K("select",{value:cu,disabled:rf,onChange:(B)=>ku(B.target.value),"data-testid":"codex-model-select"},_7.map((B)=>K("option",{key:B,value:B},B)))),K("label",null,"执行 Provider",K("select",{value:vf,disabled:rf,onChange:(B)=>Dw(String(B.target.value||"main-server")),"data-testid":"codex-provider-select"},a$.map((B)=>K("option",{key:B.id,value:B.id},`${B.label||B.id} · ${B.defaultWorkdir||I5(pf,B.id)}${B.supportsWindowsNativeCodex?" · Windows native":""}`)))),K("label",null,"执行模式",K("select",{value:dl,disabled:rf,onChange:(B)=>Xw(String(B.target.value||"default")),"data-testid":"codex-execution-mode-select"},$7.map((B)=>K("option",{key:B.id,value:B.id},`${B.label||B.id}${B.id==="windows-native"?" · 宿主 Codex":""}`)))),K("label",null,"工作目录",K("input",{value:Tl,disabled:rf,onChange:(B)=>pu(B.target.value),placeholder:Zw||pf?.defaultWorkdir||"/root/unidesk","data-testid":"codex-cwd-input"})),K("label",null,"最大尝试",K("input",{type:"number",min:1,max:99,value:rl,disabled:rf,onChange:(B)=>El(Number(B.target.value)),"data-testid":"codex-max-attempts-input"})),K("label",null,"入队份数",K("input",{type:"number",min:1,max:50,value:Jl,disabled:rf,onChange:(B)=>nl(Number(B.target.value)),"data-testid":"codex-repeat-count-input"}))),Ty>1?K("label",{className:`codex-batch-confirm ${pl?"confirmed":""}`,"data-testid":"codex-batch-confirm-row"},K("input",{type:"checkbox",checked:pl,disabled:rf,onChange:(B)=>qr(Boolean(B.target.checked)),"data-testid":"codex-batch-confirm-checkbox"}),K("span",null,`确认批量入队 ${Ty} 个任务(prompt 分段 ${p8.length} × 入队份数 ${gU(Jl)})`)):null,rf?K("div",{className:"codex-submit-wait","data-testid":"codex-submit-wait"},"正在提交到后端,已锁定输入以防重复提交..."):null,K("div",{className:"codex-form-actions"},K("button",{type:"button",className:"ghost-btn",disabled:$f||rf||uu.length===0&&g.length===0,onClick:()=>{Wu(""),Qu(""),qr(!1);let B="已清空任务输入栏";kf(B),ur("success",B)},"data-testid":"codex-clear-input-button"},"清空输入"),K("button",{type:"submit",className:"primary-btn",disabled:Ew,"data-testid":"codex-enqueue-button"},rf?"提交中,请等待...":y7?`请确认批量入队 ${Ty} 个任务`:Q0.length>1?`批量入队 ${Q0.length} 个任务`:"入队并运行"))))),K("div",{className:"codex-main-stage"},K("div",{className:"codex-detail-grid"},K(Mi,{title:"运行控制",eyebrow:g1?"Queued prompt editable":m8?"Active turn steer":"Steer when running",loading:$f},K("div",{className:"codex-run-control-stack"},K(yZ,{task:b,queueRows:Dr,busy:$f,onMove:sw}),b?.id?K("form",{className:"codex-steer-form codex-edit-prompt-form",onSubmit:kw,"data-testid":"codex-edit-prompt-form"},K("label",null,"编辑 queued 用户 prompt",K("textarea",{value:lu,rows:5,onChange:(B)=>Ou(B.target.value),placeholder:"仅 QUEUED 且尚未开始运行的任务可在这里修改原始用户 prompt。",disabled:!g1||$f,"data-testid":"codex-edit-prompt-textarea"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选,留空会清除引用)",K("input",{value:Yu,disabled:!g1||$f,onChange:(B)=>Iu(B.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-edit-reference-task-id"}),q1(Yu).length>0?K("code",null,`将保留/注入:${q1(Yu).join(" / ")}`):null),K("div",{className:"codex-form-actions"},K("button",{type:"button",className:"ghost-btn",disabled:!b?.id||$f,onClick:()=>{Ou(b?Rt(b):""),Iu(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},"data-testid":"codex-edit-prompt-reset"},"恢复当前值"),K("button",{type:"submit",className:"primary-btn",disabled:!g1||$f||lu.trim().length===0,title:g1?"保存后会重写尚未运行任务的用户 prompt":"只有 QUEUED 且尚未开始的任务可编辑 prompt","data-testid":"codex-edit-prompt-submit"},"保存 queued prompt"))):null,K("form",{className:"codex-steer-form",onSubmit:vw},K("label",null,"追加 prompt",K("textarea",{value:kn,rows:4,onChange:(B)=>R1(B.target.value),placeholder:"给正在运行的 Codex session 推入新的指令或纠偏。",disabled:!m8})),K("button",{type:"submit",className:"primary-btn",disabled:!m8||$f||kn.trim().length===0,"data-testid":"codex-steer-button"},"推入运行中 session")))),K(Mi,{title:"完成判定",eyebrow:b?.lastJudge?b.lastJudge.source:"judge",loading:s},b?.lastJudge?K("div",{className:"codex-judge-card","data-testid":"codex-task-judge-card"},K(L1,{status:b.lastJudge.decision},b.lastJudge.decision),K("strong",null,`${Math.round(Number(b.lastJudge.confidence||0)*100)}% confidence`),K("p",{"data-testid":"codex-task-judge-reason"},Y5(b.lastJudge.reason||"--",180)),K(UQ,{judge:b.lastJudge,testId:"codex-task-judge-failure-details"}),b.lastJudge.continuePrompt?K("code",{"data-testid":"codex-task-judge-continue-prompt"},Y5(b.lastJudge.continuePrompt,160)):null):K(w1,{title:"尚未判定",text:"Codex turn 结束后会由 MiniMax M2.7 或 fallback judge 判定 complete/retry/fail;retry 会在已有 thread 追加继续执行 prompt。"}))),K(iZ,{stats:D8,queueName:k1,onRaw:f}),K(Mi,{title:"Attempts",eyebrow:"terminal vs interruption",loading:s},K(FZ,{task:b})))))}var M_=Pu(qf(),1);var Bu=M_.default.createElement,{useEffect:g5}=M_.default,s5=M_.default.useState,JZ=M_.default.useRef,o5=` +本次任务:`,r=f.indexOf(l);if(r===-1)return u;return f.slice(r+l.length).trimStart()}function K1(u){return u.length>0?u.split(/\r\n|\r|\n/u).length:0}function cQ(u){let f=String(u?.displayPrompt||"");if(f.length>0)return f;let l=String(u?.prompt||"");return LE(WE(l).userPrompt)}function cr(u){return u?._traceSummary&&typeof u._traceSummary==="object"&&!Array.isArray(u._traceSummary)?u._traceSummary:null}function bt(u){return u?._promptDetails&&typeof u._promptDetails==="object"&&!Array.isArray(u._promptDetails)?u._promptDetails:{}}function k5(u){let f=cr(u)?.prompt;return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function jQ(u){let f=cr(u)?.execution;return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function oU(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):0}function X0(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):null}function FQ(u){let f=Wf(u?.traceStats);if(f&&(u?.statsSource==="oa-event-flow"||f.source==="oa-event-flow"))return f;let l=cr(u),r=Wf(l?.traceStats);if(r&&(l?.statsSource==="oa-event-flow"||r.source==="oa-event-flow"))return r;return null}function wE(u,f){let l=Wf(f?.traceStats)||Wf(f?.execution?.traceStats),r=String(f?.statsSource||f?.execution?.statsSource||"");if(l&&(r==="oa-event-flow"||l.source==="oa-event-flow"))return l;return null}function KE(u,f){return X0(FQ(u)?.[f])}function JQ(u){let f=KE(u,"stepCount");if(f!==null)return f;let l=cr(u);if(l!==null)return GE(l);return null}function GE(u){let f=Wf(u?.traceStats);if(!f||u?.statsSource!=="oa-event-flow"&&f.source!=="oa-event-flow")return null;return X0(f.stepCount)}function Mt(u){if(!u||u?._traceSummaryLoaded!==!0)return!1;let f=cr(u),l=String(u?._traceSummaryUpdatedAt||f?.updatedAt||""),r=String(u?.updatedAt||"");if(r.length>0){let n=Y0(l),i=Y0(r);if(n!==null&&i!==null){if(n+10?l:cQ(u)}function UQ(u){let f=cr(u);return String(f?.finalResponse||u?.finalResponse||"").trimEnd()}function QQ(u){let l=cr(u)?.lastJudge||u?.lastJudge;return l&&typeof l==="object"&&!Array.isArray(l)?l:null}function Wf(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function zE(u){let f=Wf(u?.raw),l=Wf(u?.failureDetails)||Wf(f?.minimaxFailure);if(l===null)return"";let r=l.repairAttempt===void 0?"":`${l.repairAttempt}/${l.maxRepairAttempts??"?"}`;return[["provider",l.provider||"minimax"],["stage",l.stage],["model",l.model],["timedOut",l.timedOut],["durationMs",l.durationMs],["timeoutMs",l.timeoutMs],["promptChars",l.promptChars],["promptLines",l.promptLines],["payloadBytes",l.payloadBytes],["responseStatus",l.responseStatus],["repairAttempt",r],["errorName",l.errorName],["error",l.errorMessage],["responseContentPreview",l.responseContentPreview],["responseTextPreview",l.responseTextPreview]].filter(([,i])=>i!==void 0&&i!==null&&String(i).length>0).map(([i,y])=>`${i}: ${String(y)}`).join(` +`)}function qQ({judge:u,testId:f="codex-judge-failure-details"}){let l=zE(u);if(l.length===0)return null;return K("details",{className:"codex-judge-failure-details","data-testid":f},K("summary",null,"MiniMax failure details"),K("pre",null,l))}function TE(u){let f=cr(u)?.attempts;if(Array.isArray(f)&&f.length>0)return f;let l=jQ(u),r=UQ(u),n=QQ(u);if(Object.keys(l).length===0&&r.length===0&&n===null)return[];return[{index:Number(u?.currentAttempt||1),mode:u?.currentMode||"initial",startedAt:u?.startedAt,finishedAt:u?.finishedAt,terminalStatus:u?.status,execution:l,finalResponse:r,finalResponseChars:r.length,judge:n}]}function EE(u,f){return Wf(f?.execution)||jQ(u)}function ZE(u,f,l,r){let n=cr(u),i=Number(n?.currentAttempt||u?.currentAttempt||0),y=Number(l),_=Number.isFinite(y)&&y>0&&y===i,$=$Q(u?.updatedAt,n?.updatedAt);if(_&&!f?.finishedAt&&$.length>0)return $;return String(f?.updatedAt||f?.finishedAt||r.effectiveEndAt||(_?$:"")||$||u?.finishedAt||u?.startedAt||"")}function OE(u,f){let l=String(f?.finalResponse||f?.finalResponsePreview||"");if(Object.prototype.hasOwnProperty.call(f||{},"finalResponse")||Object.prototype.hasOwnProperty.call(f||{},"finalResponsePreview"))return l.trimEnd();return l.length>0?l.trimEnd():UQ(u)}function NQ(u,f){if(Object.prototype.hasOwnProperty.call(f||{},"judge"))return Wf(f?.judge);return QQ(u)}function HE(u,f,l){if(!vE(u))return!1;if(I5(f,l))return!1;if(f?.finishedAt)return!1;if(["succeeded","failed","canceled"].includes(String(f?.terminalStatus||"")))return!1;let r=cr(u),n=Number(r?.currentAttempt||u?.currentAttempt||0),i=Number(l);if(Number.isFinite(i)&&i>0&&Number.isFinite(n)&&n>0)return i===n;return!0}function WQ(u){return`feedback:${String(u||"latest")}`}function BE(u,f,l){let r=String(f?.feedbackPrompt||"").trimEnd(),n=String(f?.feedbackPromptPreview||r||"").trimEnd(),i=Number(f?.feedbackPromptChars||r.length||n.length||0),y=Number(f?.feedbackPromptLines||K1(r||n));if(r.length>0||n.length>0||i>0)return{text:r,preview:n,chars:i,lines:y,source:f?.feedbackPromptSource||"judge-feedback",forAttempt:f?.feedbackPromptForAttempt||Number(l||0)+1,truncated:Boolean(f?.feedbackPromptTruncated)};let _=NQ(u,f),$=String(_?.continuePrompt||"").trimEnd();if(_?.decision==="retry"&&$.length>0)return{text:"",preview:$,chars:$.length,lines:K1($),source:"judge-continue-prompt",forAttempt:Number(l||0)+1,truncated:!1};return null}function VE(u){let f=k5(u);return Boolean(f.hasReferenceInjection||Number(f.referencePromptChars||0)>0||u?.referenceInjection||u?.referenceInjectionSummary)}function LQ(u,f=null){if(f!==null&&f!==void 0){let r=(Wf(u?._traceStepsByAttempt)||{})[String(f)];return Array.isArray(r)?r:[]}return Array.isArray(u?._traceSteps)?u._traceSteps:[]}function M5(u){let l=[u?.seq,...Array.isArray(u?.rawSeqs)?u.rawSeqs:[]].map((r)=>Number(r)).filter((r)=>Number.isFinite(r));return l.length>0?Math.max(...l):0}function DE(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,M5(l)),0)}function XE(u,f){let l=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(f)?f:[]]){let n=String(r?.seq??`${r?.title||"step"}:${r?.at||""}`);l.set(n,{...l.get(n)||{},...r})}return Array.from(l.values()).sort((r,n)=>M5(r)-M5(n))}function hi(u){return(Array.isArray(u?.summaryLines)?u.summaryLines:[]).map((f)=>String(f||""))}function YE(u){let f=String(u?.kind||"").trim().toLowerCase(),l=String(u?.status||"").trim().toLowerCase();return f==="error"||l==="error"}function vt(u){let f=String(u?.status||"").trim();if(f.length>0)return f;let l=hi(u).join(` +`);return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(l)?.[1]||""}function dU(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function SE(u){let f=hi(u);for(let r=f.length-1;r>=0;r-=1){let n=/file changes status=([A-Za-z0-9_-]+)/u.exec(f[r]||"")?.[1];if(n)return n}let l=vt(u);if(l==="item/fileChange/outputDelta")return"updated";if(l==="item/started")return"started";if(l==="item/completed")return"completed";return l.replace(/^item\//u,"")||String(u?.status||"changed")}function pE(u){if(String(u?.kind||"")!=="edited")return!1;let f=String(u?.title||""),l=String(u?.status||""),r=hi(u).join(` +`);if(f==="Edited files")return!0;if(/^item\/fileChange\//u.test(l))return!0;if((l==="item/started"||l==="item/completed")&&/file changes status=/u.test(r))return!0;if(/^Success\. Updated the following files:/mu.test(r))return!0;if(/^diff --git /mu.test(r))return!0;return/^([AMDRCU?]{1,2})\s+\S+/mu.test(r)}function mE(u){if(u.length<=1)return u[0];let f=u.find((i)=>vt(i)==="item/fileChange/outputDelta")||u.find((i)=>hi(i).some((y)=>!dU(y)))||u.at(-1)||u[0],l=u.flatMap((i)=>Array.isArray(i?.rawSeqs)?i.rawSeqs:[i?.seq]).filter((i)=>i!==void 0),r=u.flatMap(hi).filter((i)=>i.trim().length>0&&!dU(i)),n=u[u.length-1]||f;return{...f,at:f?.at||n?.at,title:String(f?.title||"Edited files"),status:SE(n),summaryLines:r.length>0?r:hi(f),rawSeqs:l}}function PE(u){let f=Array.isArray(u)?u:[],l=[],r=[],n=()=>{if(r.length>0)l.push(mE(r));r=[]};for(let i of f){if(pE(i)){if(vt(i)==="item/started"&&r.length>0)n();if(r.push(i),vt(i)==="item/completed")n();continue}n(),l.push(i)}return n(),l}function ME(u){return{...u}}function C5(u,f=null){if(f!==null&&f!==void 0){let l=Wf(u?._traceStepsLoadedByAttempt)||{};return Boolean(l[String(f)])}return Boolean(u?._traceStepsLoaded)}function R5(u){return u?._traceStepDetails&&typeof u._traceStepDetails==="object"&&!Array.isArray(u._traceStepDetails)?u._traceStepDetails:{}}function CE(u,f){let l=Number(u?.index);return Number.isFinite(l)?l:f+1}function I5(u,f){return Boolean(u?.synthetic)||Number(f)<=0}function kt(u){let f=Number(u);return Number.isFinite(f)?String(f):void 0}function RE(u){let f=u?.timing&&typeof u.timing==="object"?u.timing:{},l=String(u?.status||"");if(["queued"].includes(l))return`等待 ${hr(f.queueWaitMs??f.totalElapsedMs)}`;if(["running","judging","retry_wait"].includes(l))return`耗时 ${hr(f.durationMs??f.totalElapsedMs)}`;return`耗时 ${hr(f.durationMs??f.totalElapsedMs)}`}function M_(u){return String(u?.queueId||"default")}function wQ(u){return Wf(u?.queuedReason)}function KQ(u){let f=String(u?.queuedReasonLabel||"").trim();if(f.length>0)return f.toUpperCase();let l=wQ(u),r=String(l?.label||"").trim();return r.length>0?r.toUpperCase():""}function xE(u){let f=String(u?.status||"unknown");if(f!=="queued")return f;let l=KQ(u);return l.length>0?`QUEUED(${l})`:"QUEUED"}function hE(u){if(String(u?.status||"")!=="queued")return;let f=wQ(u),l=String(f?.message||"").trim(),r=KQ(u);if(l.length>0&&r.length>0)return`${r}: ${l}`;if(l.length>0)return l;return r.length>0?r:void 0}function bE(u){return{system:"SYS",user:"YOU",assistant:"GPT",reasoning:"THINK",command:"CMD",diff:"DIFF",tool:"TOOL",error:"ERR"}[u]||u.toUpperCase()}function eU(u){return["running","judging","retry_wait"].includes(String(u?.status||""))}function vE(u){return String(u?.status||"")==="running"}function xr(u){return["succeeded","failed","canceled"].includes(String(u?.status||""))}function GQ(u){if(u?.promptEditable===!0)return!0;if(u?.promptEditable===!1)return!1;return String(u?.status||"")==="queued"&&!u?.startedAt&&Number(u?.currentAttempt||0)===0&&!u?.codexThreadId&&!u?.nextMode}function D0(u){if(!xr(u))return!1;if(u?.terminalUnread===!0)return!0;if(u?.terminalUnread===!1)return!1;return!u?.readAt}function Cf(u){let f=Number(u||0);return Number.isFinite(f)?f:0}function kE(u){return Cf(u.queued)+Cf(u.retry_wait)}function IE(u){return Cf(u.running)+Cf(u.judging)}function gE(u,f){return Wf(u?.statistics)||Wf(f?.statistics)||{}}function sE(u){return Array.isArray(u?.daily)?u.daily:[]}function aE(u){return Wf(u?.totals)||{}}function g5(u,f){let l=Number(u?.[f]??0);return Number.isFinite(l)&&l>0?l:0}function D5(u,f){return u.reduce((l,r)=>Math.max(l,g5(r,f)),0)}var w1=700,uQ=220,Tn=30,Ri=24,C_=184,x5=C_-Ri;function zQ(u,f){if(f<=1)return w1/2;return Tn+u*(w1-Tn*2)/(f-1)}function TQ(u,f){let l=f>0?f:1;return C_-Math.min(1,u/l)*x5}function X5(u,f,l){let r=u.length>0?u:[{[f]:0}],n=r.length>1?r:[r[0],r[0]];return n.map((i,y)=>`${zQ(y,n.length).toFixed(2)},${TQ(g5(i,f),l).toFixed(2)}`).join(" ")}function V0(u){let f=String(u||"");return/^\d{4}-\d{2}-\d{2}$/u.test(f)?f.slice(5):f||"--"}function Ct(u){if(!u)return"";return`${String(u.seriesKey||"")}:${String(u.row?.date||u.index||"")}`}function oE(u,f,l,r){let n=g5(u,r.key);return{...r,row:u,index:f,value:n,valueLabel:r.format(n),x:zQ(f,l),y:TQ(n,r.max),seriesKey:r.key}}function fQ(u){if(D0(u))return 0;return{running:1,judging:2,retry_wait:3,queued:4,succeeded:8,failed:8,canceled:8}[String(u?.status||"")]??9}function p_(u){if(!u)return!1;if(u?._traceSummaryLoaded===!0)return!1;return u?.summaryOnly===!0||u?._metaLoaded!==!0}function dE(u){return Boolean(u?._metaLoaded)||u?.summaryOnly===!1}function eE(u,f,l){let r=String(u?.[l]||""),n=String(f?.[l]||"");return r.length>n.length?r:n}function h5(u,f,l){let r=Array.isArray(u?.[l])?u[l]:[],n=Array.isArray(f?.[l])?f[l]:[];if(n.length===0&&r.length>0)return r;return r.length>n.length?r:n}function lQ(u,f){let l=f?.summaryOnly===!0&&dE(u),r={...u,...f};if(!l)return r;for(let n of["prompt","basePrompt","displayPrompt","finalResponse"])r[n]=eE(u,f,n);for(let n of["promptHistory","attempts","output","events"])r[n]=h5(u,f,n);if(u?.referenceInjection?.items&&!f?.referenceInjection?.items)r.referenceInjection=u.referenceInjection;if(u?.referenceInjectionSummary&&!f?.referenceInjectionSummary)r.referenceInjectionSummary=u.referenceInjectionSummary;r.summaryOnly=u?.summaryOnly===!1?!1:f.summaryOnly,r._metaLoaded=u?._metaLoaded,r._detailLoaded=u?._detailLoaded,r._transcriptComplete=u?._transcriptComplete,r._transcriptPreview=Object.prototype.hasOwnProperty.call(f,"_transcriptPreview")?f._transcriptPreview:u?._transcriptPreview;for(let n of["_traceSummary","_traceSummaryLoaded","_traceSteps","_traceStepsLoaded","_traceStepsByAttempt","_traceStepsLoadedByAttempt","_traceStepsNextAfterSeqByAttempt","_traceStepDetails","_promptDetails"])if(!Object.prototype.hasOwnProperty.call(f,n)&&Object.prototype.hasOwnProperty.call(u||{},n))r[n]=u[n];return r}function uZ(u){let f=u?.selected,l=f?.task&&typeof f.task==="object"?f.task:null;if(l!==null){let n=Boolean(f?.preview);return{...l,transcript:Array.isArray(f?.transcript)?f.transcript:[],_detailLoaded:Array.isArray(f?.transcript)&&f.transcript.length>0,_transcriptComplete:Boolean(!n&&!f?.hasMore&&xr(l)),_transcriptPreview:n,_summaryLoaded:!0}}let r=cl(u)[0];return r?{...r,_summaryLoaded:!0}:null}function Y5(u,f){let l=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(f)?f:[]]){let n=`${Number(r?.seq??0)}:${String(r?.kind||"message")}`,i=l.get(n);if(!i){l.set(n,r);continue}let y={...i,...r};for(let[_,$]of[["bodyPreview","bodyOmittedLines"],["commandPreview","commandOmittedLines"]]){let A=String(i?.[_]||""),c=String(r?.[_]||"");if(A.length>c.length)y[_]=i[_],y[$]=i[$]}l.set(n,y)}return Array.from(l.values()).sort((r,n)=>Number(r?.seq??0)-Number(n?.seq??0))}function Rt(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,Number(l?.seq??0)),0)}function rQ(u,f=8){let l=Array.from(new Set((Array.isArray(u)?u:[]).map((n)=>Number(n?.seq??0)).filter((n)=>Number.isFinite(n)&&n>0))).sort((n,i)=>n-i);if(l.length===0)return 0;let r=l[Math.max(0,l.length-f)]??0;return Math.max(0,r-0.001)}function fZ(u,f){let l=Array.isArray(u?.codeModels)?u.codeModels:Array.isArray(u?.codexModels)?u.codexModels:[],r=["gpt-5.5","gpt-5.4-mini","gpt-5.4","minimax-m2.7"];return Array.from(new Set([...l,...r,f].map((n)=>String(n||"").trim()).filter(Boolean)))}function lZ(u,f){let r=(Array.isArray(u?.executionProviders)?u.executionProviders:[]).map((y)=>({id:String(y?.id||"").trim(),label:String(y?.label||y?.id||"").trim(),defaultWorkdir:String(y?.defaultWorkdir||"").trim(),supportsWindowsNativeCodex:y?.supportsWindowsNativeCodex===!0,windowsNativeDefaultWorkdir:String(y?.windowsNativeDefaultWorkdir||"").trim(),kind:String(y?.kind||"").trim()})).filter((y)=>y.id.length>0),n=String(u?.mainProviderId||u?.defaultProviderId||"D601").trim()||"D601",i=new Map;for(let y of[...r,{id:n,label:`${n} (local)`,defaultWorkdir:String(u?.defaultWorkdir||"/workspace"),supportsWindowsNativeCodex:!1,windowsNativeDefaultWorkdir:"",kind:"local"},f?{id:f,label:f,defaultWorkdir:s5(u,f),supportsWindowsNativeCodex:f!==n,windowsNativeDefaultWorkdir:String(u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart"),kind:""}:null].filter(Boolean))if(!i.has(y.id))i.set(y.id,y);return Array.from(i.values())}function rZ(u,f){let r=(Array.isArray(u?.executionModes)?u.executionModes:[]).map((y)=>({id:String(y?.id||y?.kind||"").trim(),label:String(y?.label||y?.id||y?.kind||"").trim(),description:String(y?.description||"").trim(),defaultWorkdir:String(y?.defaultWorkdir||"").trim(),requiresProvider:y?.requiresProvider===!0,requiresWindowsCwd:y?.requiresWindowsCwd===!0})).filter((y)=>y.id.length>0),n=[{id:"default",label:"默认容器/本机",description:"Code Queue 所在节点用本机 Codex;远程 Provider 用执行容器 Codex。",defaultWorkdir:"",requiresProvider:!1,requiresWindowsCwd:!1},{id:"windows-native",label:"Windows 原生 Codex",description:"启动执行容器,但容器只做 stdio relay,Codex 运行在 Provider 的 Windows 宿主。",defaultWorkdir:String(u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart"),requiresProvider:!0,requiresWindowsCwd:!0}],i=new Map;for(let y of[...r,...n,f?{id:f,label:f,description:"",defaultWorkdir:"",requiresProvider:f==="windows-native",requiresWindowsCwd:f==="windows-native"}:null].filter(Boolean))if(!i.has(y.id))i.set(y.id,y);return Array.from(i.values())}function xt(u,f,l){if(f!=="windows-native")return s5(u,l);let r=Array.isArray(u?.executionModes)?u.executionModes.find((i)=>String(i?.id||i?.kind||"")==="windows-native"):null,n=Array.isArray(u?.executionProviders)?u.executionProviders.find((i)=>String(i?.id||"")===l):null;return String(n?.windowsNativeDefaultWorkdir||r?.defaultWorkdir||u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart")}function s5(u,f){let l=String(f||"").trim(),r=u?.defaultWorkdirByProvider&&typeof u.defaultWorkdirByProvider==="object"?u.defaultWorkdirByProvider:{};if(typeof r[l]==="string"&&String(r[l]).trim().length>0)return String(r[l]).trim();let n=Array.isArray(u?.executionProviders)?u.executionProviders.find((y)=>String(y?.id||"")===l):null;if(typeof n?.defaultWorkdir==="string"&&n.defaultWorkdir.trim().length>0)return n.defaultWorkdir.trim();let i=String(u?.mainProviderId||u?.defaultProviderId||"D601");return l===i?String(u?.defaultWorkdir||"/workspace"):String(u?.remoteDefaultWorkdir||"/home/ubuntu")}function nZ(u){return JQ(u)}function iZ({task:u,selected:f,onSelect:l,onCopy:r,onReference:n,onMarkRead:i,copied:y,markingRead:_}){let $=u?.lastJudge||{},A=String(u?.id||""),c=D0(u),j=$Q(u?.updatedAt,cr(u)?.updatedAt),F=`最近更新: ${_Q(j)}`,U=nZ(u),Q=U===null?"--":String(U),L=U===null?"STEP 统计中心同步中":"STEP 来自 OA Event Flow 统计中心";return K("article",{role:"button",tabIndex:0,className:`codex-task-card ${f?"selected":""} ${c?"unread-terminal":""}`,onClick:l,onKeyDown:(w)=>{if(w.key==="Enter"||w.key===" ")w.preventDefault(),l()},"data-unread-terminal":c?"true":"false","data-testid":`codex-task-${u?.id||"unknown"}`},c?K("span",{className:"codex-unread-badge",title:"待读","aria-label":"待读","data-testid":`codex-unread-task-${A||"unknown"}`}):null,K("div",{className:"codex-task-card-head"},K("div",{className:"codex-task-status-line"},K(G1,{status:u?.status,title:hE(u)},xE(u))),K("span",{className:"mono-text"},`${u?.currentAttempt||0}/${u?.maxAttempts||0}`)),K("div",{className:"codex-task-id-row"},K("code",{title:A},A||"unknown"),K("div",{className:"codex-task-id-actions"},K("button",{type:"button",className:"codex-copy-id-btn",onClick:(w)=>{w.stopPropagation(),n(A)},"data-testid":`codex-reference-task-${A||"unknown"}`},"引用"),K("button",{type:"button",className:"codex-copy-id-btn",onClick:(w)=>{w.stopPropagation(),r(A)},"data-testid":`codex-copy-task-id-${A||"unknown"}`},y?"已复制":"复制ID"),c?K("button",{type:"button",className:"codex-copy-id-btn codex-mark-read-btn",disabled:Boolean(_),onClick:(w)=>{w.stopPropagation(),i(A)},"data-testid":`codex-mark-task-read-${A||"unknown"}`},_?"标记中":"标为已读"):null)),K("strong",null,p5(cQ(u),120)||"空任务"),K("div",{className:"codex-task-meta"},K("span",null,`queue=${M_(u)}`),K("span",null,`provider=${u?.providerId||"D601"}`),K("span",null,`mode=${u?.executionMode||"default"}`),K("span",null,u?.model||"--"),K("span",null,RE(u))),K("div",{className:"codex-task-meta codex-task-update-meta"},K("span",{className:"codex-task-recent-update codex-task-step-count",title:L,"data-testid":`codex-task-step-count-${A||"unknown"}`},`STEP ${Q}`),K("span",{className:"codex-task-recent-update",title:j?`更新时间: ${Nu(j)}`:F,"data-testid":`codex-task-recent-update-${A||"unknown"}`},F),K("span",null,Nu(j||u?.updatedAt))),GQ(u)?K("div",{className:"codex-judge-line","data-testid":`codex-task-prompt-editable-${A||"unknown"}`},"queued prompt 可编辑"):null,$?.decision?K("div",{className:"codex-judge-line"},`judge=${$.decision} ${Math.round(Number($.confidence||0)*100)}%`):null)}function S5({title:u,tasks:f,selectedId:l,onSelect:r,onCopy:n,onReference:i,onMarkRead:y,copiedTaskId:_,markingReadTaskId:$,emptyText:A}){let c=Array.isArray(f)?f:[];return K("section",{className:"codex-task-section"},K("div",{className:"codex-task-section-head"},K("span",null,u),K("code",null,String(c.length))),c.length===0?K("p",{className:"codex-task-section-empty"},A):K("div",{className:"codex-task-section-list"},c.map((j)=>K(iZ,{key:j.id,task:j,selected:l===j.id,onSelect:()=>r(j.id),onCopy:n,onReference:i,onMarkRead:y,copied:_===j.id,markingRead:$===j.id}))))}function yZ(){return K("span",{className:"codex-stats-icon","aria-hidden":"true"},K("svg",{viewBox:"0 0 36 24",focusable:"false"},K("path",{className:"grid",d:"M3 20.5H33M3 12.5H33M3 4.5H33"}),K("polyline",{className:"line tasks",points:"3,18 9,14 15,15 21,8 27,10 33,4"}),K("polyline",{className:"line retry",points:"3,20 9,17 15,18 21,13 27,14 33,9"})))}function _Z({stats:u,queueName:f,onRaw:l}){let r=sE(u),n=aE(u),i=r.at(-1)||{},y=D5(r,"executedTasks"),_=D5(r,"retryAttempts"),$=D5(r,"avgDurationMs"),A=r.length>0,c=Wf(u?.range)||{},[j,F]=vu(null),[U,Q]=vu(null),L=[];if(y>0)L.push(`tasks ${y}`);if(_>0)L.push(`retry ${_}`);if($>0)L.push(`avg ${hr($)}`);let w=[{key:"executedTasks",className:"tasks",label:"执行任务",max:y,format:(E)=>`${Cf(E)} tasks`},{key:"retryAttempts",className:"retry",label:"重试次数",max:_,format:(E)=>`${Cf(E)} retries`},{key:"avgDurationMs",className:"duration",label:"平均耗时",max:$,format:(E)=>hr(E)}],J=j||U,N=Ct(J),q=String(J?.row?.date||""),W=J?{left:`${Math.max(8,Math.min(92,Number(J.x)/w1*100))}%`,top:`${Math.max(14,Math.min(86,Number(J.y)/uQ*100))}%`}:void 0;zn(()=>{F(null),Q(null)},[f,c.startDate,c.endDate,r.length]);let z=(E)=>{F(E)},Z=(E)=>{let D=Ct(E);Q((h)=>Ct(h)===D?null:E),F(E)},H=w.flatMap((E)=>r.map((D,h)=>{let V=oE(D,h,r.length,E),Y=Ct(V),p=N===Y,O=String(D?.date||`day-${h}`),m=`${V0(O)} ${E.label}: ${V.valueLabel}`;return K("g",{key:`${E.key}-${O}`,className:`stat-point-group ${E.className} ${p?"active":""}`,role:"button",tabIndex:0,"aria-label":m,"data-testid":`codex-stats-point-${E.className}-${O}`,onMouseEnter:()=>z(V),onFocus:()=>z(V),onClick:()=>Z(V),onKeyDown:(X)=>{if(X.key==="Enter"||X.key===" ")X.preventDefault(),Z(V)}},K("circle",{className:"stat-hit-point",cx:V.x,cy:V.y,r:13}),K("circle",{className:`stat-point ${E.className} ${p?"active":""}`,cx:V.x,cy:V.y,r:p?5.6:4.2}))}));return K(Ci,{title:"统计曲线",eyebrow:`Daily task stats / ${f}`,className:"codex-stats-panel",summary:K("span",null,`${V0(c.startDate)} -> ${V0(c.endDate)} · ${u?.timezone||"Asia/Shanghai"}`),actions:Wf(u)?K(tQ,{title:"Code Queue Stats",data:u,onOpen:l,testId:"raw-codex-stats"}):null},K("div",{className:"codex-stats-hero","data-testid":"codex-stats-panel"},K(yZ),K("div",null,K("strong",null,`${Cf(n.executedTasks)} tasks / ${Cf(n.retryAttempts)} retries`),K("span",null,`平均完成耗时 ${hr(n.avgDurationMs??void 0)} · 终态 ${Cf(n.completedTasks)} 个`))),A?K("div",{className:"codex-stats-chart","data-testid":"codex-stats-chart",onMouseLeave:()=>F(null)},K("svg",{viewBox:`0 0 ${w1} ${uQ}`,preserveAspectRatio:"none",role:"img","aria-label":"Code Queue daily task statistics"},K("line",{className:"axis",x1:Tn,x2:w1-Tn,y1:C_,y2:C_}),K("line",{className:"grid",x1:Tn,x2:w1-Tn,y1:Ri+x5/2,y2:Ri+x5/2}),K("line",{className:"grid",x1:Tn,x2:w1-Tn,y1:Ri,y2:Ri}),K("polyline",{className:"stat-line tasks",points:X5(r,"executedTasks",y)}),K("polyline",{className:"stat-line retry",points:X5(r,"retryAttempts",_)}),K("polyline",{className:"stat-line duration",points:X5(r,"avgDurationMs",$)}),J?K("g",{className:"stat-cursor-layer","data-testid":"codex-stats-active-point"},K("line",{className:"stat-cursor",x1:J.x,x2:J.x,y1:Ri,y2:C_}),K("circle",{className:`stat-point-active ${J.className}`,cx:J.x,cy:J.y,r:8})):null,K("g",{className:"stat-point-layer"},H)),J?K("div",{className:"codex-stats-tooltip active",style:W,"data-testid":"codex-stats-tooltip"},K("b",null,V0(J.row?.date)),K("span",null,`${J.label} · ${J.valueLabel}`),K("code",null,`${Cf(J.row?.executedTasks)} exec / ${Cf(J.row?.retryAttempts)} retry / ${hr(J.row?.avgDurationMs??void 0)}`)):null,K("div",{className:"codex-stats-legend"},K("span",{className:"tasks"},"执行任务"),K("span",{className:"retry"},"重试次数"),K("span",{className:"duration"},"平均耗时")),K("div",{className:"codex-stats-scale"},K("span",null,V0(r[0]?.date)),K("span",null,L.join(" · ")||"暂无峰值"),K("span",null,V0(r.at(-1)?.date))),K("div",{className:`codex-stats-focus ${J?"active":""}`,"data-testid":"codex-stats-focus"},J?K(R_.default.Fragment,null,K("div",null,K("strong",null,V0(J.row?.date)),K("span",null,`${J.label} · ${J.valueLabel}`)),K("div",{className:"codex-stats-focus-metrics"},K("code",null,`${Cf(J.row?.executedTasks)} exec`),K("code",null,`${Cf(J.row?.retryAttempts)} retry`),K("code",null,hr(J.row?.avgDurationMs??void 0)))):K("span",null,"将鼠标悬停到曲线数据点查看明细,点击数据点可固定。"))):K(z1,{title:"暂无统计",text:"任务开始执行后会生成按天汇总的曲线。"}),K("div",{className:"codex-stats-summary-grid"},K("article",null,K("span",null,"今日执行"),K("strong",null,String(Cf(i.executedTasks))),K("code",null,V0(i.date))),K("article",null,K("span",null,"今日重试"),K("strong",null,String(Cf(i.retryAttempts))),K("code",null,`累计 ${Cf(n.retryAttempts)}`)),K("article",null,K("span",null,"平均耗时"),K("strong",null,hr(n.avgDurationMs??void 0)),K("code",null,`${Cf(n.durationSamples)} samples`))),K("div",{className:"codex-stats-daily-list","data-testid":"codex-stats-daily-list"},r.slice(-7).map((E)=>K("div",{key:String(E?.date||""),className:`codex-stats-daily-row ${q===String(E?.date||"")?"active":""}`,"data-testid":`codex-stats-day-${String(E?.date||"unknown")}`},K("span",null,V0(E?.date)),K("b",null,`${Cf(E?.executedTasks)} exec`),K("b",null,`${Cf(E?.retryAttempts)} retry`),K("code",null,hr(E?.avgDurationMs??void 0))))))}function $Z({task:u,queueRows:f,busy:l,onMove:r}){let n=String(u?.id||""),i=M_(u),[y,_]=vu(i);zn(()=>{_(i)},[n,i]);let $=!n||l||["running","judging","retry_wait"].includes(String(u?.status||""));return K("div",{className:"codex-task-move-control","data-testid":"codex-task-queue-move-control"},K("label",null,"任务 queue",K("select",{value:y,disabled:!n||l,onChange:(A)=>_(String(A.target.value||i)),"data-testid":"codex-task-queue-move-select"},f.map((A)=>K("option",{key:String(A?.id||""),value:String(A?.id||"")},P_(A))))),K("button",{type:"button",className:"ghost-btn",disabled:$||y===i,onClick:()=>r(y),title:$?"运行中 / judging / retry_wait 的任务不能移动;请先打断或等当前 turn 结束":"移动已创建任务到另一个 queue","data-testid":"codex-task-queue-move-button"},"移动"))}function nQ(u,f=4){let l=(Array.isArray(u)?u:[]).map((n)=>String(n||"").trim()).filter(Boolean);if(l.length===0)return"--";let r=l.slice(0,f).join(" / ");return l.length>f?`${r} +${l.length-f}`:r}function tZ({task:u,loading:f,onLoadPromptPart:l,testId:r="codex-initial-prompt-full",textTestId:n="codex-initial-prompt-full-text",baseTextTestId:i="codex-initial-prompt-base"}){let y=k5(u),_=bt(u),$=ht(u).trimEnd(),A=String(_.full?.text||""),c=VE(u),j=Number(y.promptChars||u?.promptChars||A.length),F=Number(y.basePromptLines||K1($)),U=Number(y.promptLines||K1(A));return K("section",{className:"codex-progressive-card codex-progressive-prompt","data-testid":"codex-progressive-prompt"},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Prompt"),K("strong",null,"Submitted prompt / 原始用户 prompt"),K("code",null,`${F||K1($)} lines / ${$.length} chars`)),K("pre",{className:"codex-prompt-full","data-testid":i},$||"空 prompt"),c?K("details",{className:"codex-reference-injection codex-progressive-full-prompt","data-testid":r,onToggle:(Q)=>{if(Q.currentTarget?.open&&!A)l?.("full")}},K("summary",null,K("span",null,"引用注入已折叠,点击按需拉取最终进入 Code agent 的完整 prompt"),K("code",null,A?`${U||K1(A)} lines / ${A.length} chars`:`${Number.isFinite(j)&&j>0?j:"--"} chars`)),K("pre",{className:"codex-prompt-full codex-prompt-final-full","data-testid":n},A||(f?"正在按需拉取完整 prompt...":"展开后将只请求 full prompt,不拉取完整 transcript。"))):null)}function EQ({task:u,attempt:f,attemptIndex:l,loading:r,onLoadSteps:n,onLoadStep:i,testId:y="codex-execution-summary"}){let _=PE(LQ(u,l)),$=ME(EE(u,f)),A=f?wE(u,f):FQ(u),c=R5(u),j=C5(u,l),F=X0(A?.errorCount),U=X0(A?.stepCount??A?.llmStepCount),Q=X0(A?.readCount),L=X0(A?.editCount),w=X0(A?.runCount),J=X0(A?.stepCount??A?.llmStepCount),N=U===null?"--":String(U),q=J===null?"--":String(J),W=Array.isArray($.editedFiles)?$.editedFiles:[],z=Array.isArray($.commands)?$.commands:[],H=I5(f,l)?` · ${String(f?.label||"recovered thread execution")}`:l?` #${l}`:"",E=ZE(u,f,l,$),D=`最近更新: ${_Q(E)}`,h=HE(u,f,l);return K("details",{className:`codex-progressive-card codex-execution-summary ${h?"running":""}`,"data-testid":y,"data-attempt-index":kt(l),"data-running":h?"true":"false",onToggle:(V)=>{if(V.currentTarget?.open&&!j)n?.(l)}},K("summary",null,K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Summary"),K("strong",null,`执行过程摘要${H}`),h?K("span",{className:"codex-summary-running-pill","data-testid":`${y}-running`},"执行中"):null,K("code",{title:E?`最近更新: ${Nu(E)}`:D},`${hr($.durationMs??$.totalElapsedMs)} / ${N} tools / ${D}`)),K("div",{className:"codex-execution-digest"},K("span",{title:"来自 OA Event Flow 统计中心"},`read ${Q===null?"--":Q}`),K("span",{title:"来自 OA Event Flow 统计中心"},`edit ${L===null?"--":L}`),K("span",{title:"来自 OA Event Flow 统计中心"},`run ${w===null?"--":w}`),K("span",{title:"来自 OA Event Flow 统计中心"},`STEP ${q}`),F!==null&&F>0?K("span",{className:"codex-execution-error-pill","data-testid":`${y}-error-count`},`Error ${F}`):null)),K("div",{className:"codex-execution-digest expanded"},K("span",null,`修改文件:${nQ(W,6)}`),K("span",null,`执行命令:${nQ(z,4)}`)),_.length===0?K("div",{className:"codex-output-empty"},r?"正在按需拉取步骤 summary...":"展开后将只请求执行步骤 summary,不拉取单步骤全量。"):K("div",{className:"codex-trace-step-list"},_.map((V)=>{let Y=String(V?.seq??""),p=c[Y],O=Array.isArray(V?.summaryLines)?V.summaryLines.slice(0,4):[],m=O.find((X)=>String(X||"").trim().length>0);return K("details",{key:Y||`${V?.title}-${V?.at}`,className:`codex-trace-step ${String(V?.kind||"message")} ${YE(V)?"error":""}`,"data-testid":`codex-trace-step-${Y||"unknown"}`,onToggle:(X)=>{if(X.currentTarget?.open&&!p)i?.(V?.seq)}},K("summary",null,K("span",{className:"codex-output-channel"},AZ(V?.kind)),K("strong",null,String(V?.title||"Trace step")),V?.status?K("code",null,String(V.status)):null,m?K("span",{className:"codex-trace-step-inline-summary",title:String(m)},String(m)):null,K("time",null,Nu(V?.at))),K("div",{className:"codex-trace-step-summary"},O.length>0?O.map((X,v)=>K("pre",{key:`${Y}-${v}`},String(X||""))):K("span",null,"无 summary")),p?.line?K(pt,{items:[p.line],autoScroll:!1,loading:!1,hasDetail:!0,emptyText:"无步骤详情",testId:`codex-trace-step-detail-${Y||"unknown"}`,className:"codex-transcript codex-step-detail-transcript",collapseTools:!1}):K("div",{className:"codex-output-empty"},r?"正在按需拉取这个步骤的全量数据...":"展开后将只请求这个单步骤的全量数据。"))})))}function AZ(u){let f=String(u||"");if(f==="ran")return"Ran";if(f==="explored")return"Explored";if(f==="edited")return"Edited";if(f==="error")return"Error";if(f==="system")return"System";return"Message"}function ZQ({task:u,attempt:f,attemptIndex:l,testId:r="codex-final-response"}){let n=OE(u,f);if(n.length===0)return null;let i=Number(f?.finalResponseChars||n.length),y=l?` #${l}`:"";return K("section",{className:"codex-progressive-card codex-final-response","data-testid":r,"data-attempt-index":kt(l)},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Final"),K("strong",null,`最终 response${y}`),K("code",null,`${Number.isFinite(i)?i:n.length} chars`)),K(UU,{markdown:n,className:"codex-transcript-body codex-markdown",testId:`${r}-markdown`}))}function OQ({task:u,attempt:f,attemptIndex:l,testId:r="codex-progressive-judge"}){let n=NQ(u,f);if(!n?.decision)return null;let i=l?` #${l}`:"";return K("section",{className:"codex-progressive-card codex-progressive-judge","data-testid":r,"data-attempt-index":kt(l)},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Judge"),K("strong",null,`完成判定${i}`),K("code",null,`${n.decision} ${Math.round(Number(n.confidence||0)*100)}%`)),K("div",{className:"codex-judge-card","data-testid":`${r}-card`},K(G1,{status:n.decision},n.decision),K("strong",null,`${Math.round(Number(n.confidence||0)*100)}% confidence`),K("p",{"data-testid":`${r}-reason`},n.reason||"--"),K(qQ,{judge:n,testId:`${r}-failure-details`}),n.continuePrompt?K("pre",{"data-testid":`${r}-continue-prompt`},String(n.continuePrompt||"")):null))}function cZ({task:u,attempt:f,attemptIndex:l,loading:r,onLoadPromptPart:n,testId:i="codex-judge-feedback-prompt"}){let y=BE(u,f,l);if(y===null)return null;let _=WQ(l),A=bt(u)[_],c=String(A?.text||"").trimEnd(),j=String(y.preview||y.text||"").trimEnd(),F=c||String(y.text||"").trimEnd(),U=Number(A?.chars||y.chars||F.length||j.length),Q=Number(A?.lines||y.lines||K1(F||j)),L=A?.forAttempt||y.forAttempt||Number(l||0)+1;return K("details",{className:"codex-progressive-card codex-judge-feedback-prompt","data-testid":i,"data-attempt-index":kt(l),onToggle:(w)=>{if(w.currentTarget?.open&&!c)n?.("feedback",l)}},K("summary",null,K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Prompt"),K("strong",null,`judge feedback prompt #${l} -> #${L}`),K("code",null,`${Q||"--"} lines / ${Number.isFinite(U)?U:j.length} chars`)),K("p",{className:"codex-feedback-preview","data-testid":`${i}-preview`},j||"展开后按需拉取 judge feedback prompt。")),K("pre",{className:"codex-prompt-full codex-feedback-full","data-testid":`${i}-text`},F||(r?"正在按需拉取 judge feedback prompt...":"展开后将只请求这一次 judge feedback prompt。")))}function jZ({task:u,attempt:f,position:l,loading:r,onLoadPromptPart:n,onLoadSteps:i,onLoadStep:y}){let _=CE(f,l),$=l===0,A=I5(f,_),c=A?String(f?.label||"Recovered thread execution"):`Attempt ${_}`;return K("section",{className:"codex-attempt-cycle","data-testid":`codex-attempt-cycle-${_}`},K("div",{className:"codex-attempt-cycle-head"},K("span",{className:"codex-output-channel"},c),K("strong",null,String(f?.mode||(_<=1?"initial":"retry"))),f?.terminalStatus?K(G1,{status:f.terminalStatus},f.terminalStatus):null,K("code",null,`${Nu(f?.startedAt)} -> ${Nu(f?.finishedAt)}`)),K(EQ,{task:u,attempt:f,attemptIndex:_,loading:r,onLoadSteps:i,onLoadStep:y,testId:$?"codex-execution-summary":`codex-execution-summary-attempt-${_}`}),A?null:K(ZQ,{task:u,attempt:f,attemptIndex:_,testId:$?"codex-final-response":`codex-final-response-attempt-${_}`}),A?null:K(OQ,{task:u,attempt:f,attemptIndex:_,testId:$?"codex-progressive-judge":`codex-progressive-judge-attempt-${_}`}),A?null:K(cZ,{task:u,attempt:f,attemptIndex:_,loading:r,onLoadPromptPart:n,testId:$?"codex-judge-feedback-prompt":`codex-judge-feedback-prompt-attempt-${_}`}))}function FZ({task:u,loading:f,onLoadPromptPart:l,onLoadSteps:r,onLoadStep:n}){if(!u)return K(z1,{title:"未选择任务",text:"从左侧队列选择任务,或提交新 Codex 任务。"});let i=TE(u);return K("div",{className:"codex-transcript codex-progressive-trace","data-testid":"codex-output"},f&&!cr(u)?K("div",{className:"codex-output-empty"},"正在加载 Trace Summary..."):null,K(tZ,{task:u,loading:f,onLoadPromptPart:l}),i.length>0?i.map((y,_)=>K(jZ,{key:`${y?.index||_+1}-${y?.startedAt||_}`,task:u,attempt:y,position:_,loading:f,onLoadPromptPart:l,onLoadSteps:r,onLoadStep:n})):[K(EQ,{key:"execution",task:u,loading:f,onLoadSteps:r,onLoadStep:n}),K(ZQ,{key:"final",task:u}),K(OQ,{key:"judge",task:u})])}function JZ({task:u}){let f=UE(u);if(!u||f.length===0)return K(z1,{title:"暂无原始消息",text:"原始 Codex app-server 消息会保留在任务 JSON 中。"});return K("details",{className:"codex-raw-output"},K("summary",null,`原始 messages (${f.length})`),K("div",null,f.map((l)=>K("article",{key:`${l.seq}-${l.channel}`,className:`codex-output-line ${l.channel||"system"}`},K("div",{className:"codex-output-meta"},K("span",{className:"codex-output-channel"},bE(String(l.channel||"system"))),K("span",null,Nu(l.at)),l.method?K("code",null,l.method):null),K("pre",null,String(l.text||""))))))}function UZ({task:u}){let f=QE(u).slice().reverse();if(f.length===0)return K(z1,{title:"尚无 attempt",text:"任务开始运行后,这里会记录 Codex 终态、传输中断和 stderr tail。"});return K("div",{className:"table-wrap codex-attempt-table"},K("table",null,K("thead",null,K("tr",null,K("th",null,"#"),K("th",null,"模式"),K("th",null,"终态"),K("th",null,"传输"),K("th",null,"退出"),K("th",null,"完成时间"))),K("tbody",null,f.map((l)=>K("tr",{key:`${l.index}-${l.startedAt}`},K("td",null,l.index),K("td",null,l.mode),K("td",null,K(G1,{status:l.terminalStatus||"unknown"},l.terminalStatus||"unknown")),K("td",null,l.transportClosedBeforeTerminal?K(G1,{status:"failed"},"closed-before-terminal"):K(G1,{status:"succeeded"},"normal")),K("td",null,`code=${l.appServerExitCode??"--"} signal=${l.appServerSignal??"--"}`),K("td",null,Nu(l.finishedAt)))))))}function HQ({microservices:u,onRaw:f,apiBaseUrl:l="/api",initialTasksData:r=null,standalone:n=!1}){let i=u.find((B)=>B.id==="code-queue")||null,y=uZ(r),_=String(y?.id||""),$=new Map;if(y!==null&&_.length>0)$.set(_,{task:y,maxSeq:Rt(Array.isArray(y.transcript)?y.transcript:[]),complete:Boolean(y._transcriptComplete),completeUpdatedAt:y._transcriptComplete?String(y.updatedAt||""):""});let A=typeof performance>"u"?0:performance.now(),c=Xf(_),j=Xf(0),F=Xf(0),U=Xf(0),Q=Xf(!1),L=Xf(!1),w=Xf(!1),J=Xf(null),N=Xf(new Map),q=Xf(new Map),W=Xf(new Map),z=Xf(new Map),Z=Xf(new Set),H=Xf(null),E=Xf(null),D=Xf(!1),h=Xf(!1),V=Xf(Boolean(r)),Y=Xf(new Map),p=Xf(new Set),O=Xf($),m=Xf(r),[X,v]=vu(null),[T,S]=vu(r),[k,I]=vu(_),[b,o]=vu(y),[g,x]=vu(!1),[fu,$u]=vu(""),[tu,ju]=vu(null),[Gu,qu]=vu(!1),[P,e]=vu(!1),uu=r?.queue||{},wu=String(uu?.mainProviderId||uu?.defaultProviderId||"D601").trim()||"D601",[s,Qu]=vu(""),[zu,Ou]=vu(""),[bu,eu]=vu("default"),[pu,Ff]=vu(En),[Fl,Tl]=vu(!1),[fl,of]=vu(""),[El,pl]=vu(wu),[cu,Iu]=vu("default"),[Jl,Su]=vu("gpt-5.5"),[ll,rl]=vu(xt(uu,"default",wu)||"/workspace"),[el,nl]=vu(99),[Zl,Q0]=vu(1),[ur,v0]=vu(!1),[Jf,h1]=vu(!1),[lu,Hu]=vu(""),[Yu,gu]=vu(""),[_f,Pf]=vu(""),[rf,Ul]=vu(!0),[Dr,Ly]=vu(()=>typeof window>"u"?!0:window.matchMedia(lE).matches),[Zf,h$]=vu(!1),[X8,zf]=vu(""),[l7,vf]=vu(""),{addNotification:fr}=Dl(),[b1,wy]=vu(""),[v1,b$]=vu(""),[Ky,v$]=vu(!1),[ml,sr]=vu(r?{phase:"complete",taskId:_,queueMs:0,detailMs:0,totalMs:A,chunks:y?1:0,transcriptRows:Array.isArray(y?.transcript)?y.transcript.length:0,partial:Boolean(r?.selected?.hasMore||p_(y)),completedAt:new Date}:null),[k$,Gy]=vu(r?new Date:null),[zy,I$]=vu(!1),ar=a1(cl(T)),g$=ar.filter(D0),pf=T?.queue||X?.body?.queue||X?.queue||{},Y8=gE(T,pf),s$=Gn(T),qr=IU(pf,bu),sn=String(bu||"default").trim()||"default",an=qr.filter((B)=>String(B?.id||"")!==sn),k1=xi(qr,pu),on=Number((vl(pu)?pf?.total:k1?.total)??s$.total??ar.length),Ty=m_(pf),r7=vl(pu)?Ty:[String(xi(qr,pu)?.activeTaskId||"")].filter(Boolean),I1=gU(pf,qr,pu,ar),n7=vl(pu)?V5(pf):V5(k1||{}),Ey=V5(pf),S8=kE(Ey),a$=Math.max(IE(Ey),Ty.length),p8=Cf((vl(pu)?pf?.unreadTerminal:k1?.unreadTerminal)??g$.length),k0=T?g$.length:p8,I0=vl(pu)?"All queues":P5(k1||{id:pu,name:pu}),dn=m5(fu),Pl=dn.length>0,Zy=Pl?a1(cl(tu)):[],m8=Gn(tu),or=Pl?Zy:ar,i7=or.filter(D0),zw=or.filter((B)=>!xr(B)).sort(eT),Tw=or.filter((B)=>xr(B)&&!D0(B)),y7=Pl?m8:s$,g1=Pl?Number(m8.total??Zy.length):on,_7=y7.hasMore===!0&&String(y7.nextBeforeId||"").length>0,P8=Pl?P:zy,Ew=i?aT(i):{},Zw=i?oT(i):{},M8=bU(()=>qE(s),[s]),q0=bU(()=>{let B=aU(Zl);return M8.flatMap((M)=>Array.from({length:B},()=>NE(M,zu)))},[M8,Zl,zu]),Oy=q0.length,$7=Oy>1&&!ur,Ow=Jf||Zf||Oy===0||$7,t7=fZ(pf,Jl),o$=lZ(pf,El),A7=rZ(pf,cu),Hw=xt(pf,cu,El),C8=b?.id&&b?.activeTurnId&&String(b?.status)==="running",Bw=b?.id&&!["succeeded","failed","canceled"].includes(String(b?.status||"")),Vw=b?.id&&["succeeded","failed","canceled"].includes(String(b?.status||"")),s1=b?.id&&GQ(b);function Nr(B){let M=typeof B==="function"?B(m.current):B;return m.current=M,S(M),M}function Dw(B,M,d=!0){let nu=Array.from(new Set(B.map((Fu)=>String(Fu||"")).filter(Boolean)));for(let Fu of nu)if(Y.current.set(Fu,M),d)p.current.add(Fu);return nu}function c7(B){for(let M of B.map((d)=>String(d||"")).filter(Boolean))Y.current.delete(M),p.current.delete(M)}function d$(B){let M=String(B?.id||""),d=M?Y.current.get(M):void 0;if(!d)return B;if(String(B?.status||"").length>0&&!xr(B))return Y.current.delete(M),p.current.delete(M),B;return{...B,readAt:B?.readAt||d,terminalUnread:!1}}function R8(B){let M=String(B?.id||"");return M.length>0&&p.current.has(M)&&xr(B)}function a1(B,M=!0){let d=[];for(let nu of Array.isArray(B)?B:[]){let Fu=d$(nu);if(M&&R8(Fu))continue;d.push(Fu)}return d}function Xw(B,M=!0){if(!B||!Array.isArray(B?.tasks))return B;let d=a1(cl(B),M),nu=Gn(B);return{...B,tasks:d,pagination:B.pagination?{...nu,returned:d.length}:B.pagination}}function Yw(B){let M=String(B||pf?.mainProviderId||"D601").trim()||"D601";pl(M),rl(xt(pf,cu,M))}function Sw(B){let M=String(B||"default").trim()||"default",d=El;if(M==="windows-native"){if(!o$.find((Fu)=>Fu.id===El)?.supportsWindowsNativeCodex)d=String(o$.find((Fu)=>Fu.supportsWindowsNativeCodex)?.id||El||"D601"),pl(d)}Iu(M),rl(xt(pf,M,d))}function e$(B,M,d=null,nu=null){let Fu=new Set(Dw(B,M));if(Fu.size===0&&nu===null&&d===null)return;Nr((Ku)=>{if(!Ku)return Ku;let Wu=cl(Ku).flatMap((Cu)=>{let xu=String(Cu?.id||"");if(!Fu.has(xu)){let cf=d$(Cu);return R8(cf)?[]:[cf]}let mu=nu&&String(nu?.id||"")===xu?nu:{},Ru={...Cu,...mu,readAt:M,terminalUnread:!1};return R8(Ru)?[]:[Ru]});return{...Ku,queue:d||Ku.queue,tasks:Fu.size>0?Mi([Wu],I1):Wu}});for(let Ku of Fu){let Wu=O.current.get(Ku);if(Wu?.task){let Cu=nu&&String(nu?.id||"")===Ku?nu:{},xu={...Wu.task,...Cu,readAt:M,terminalUnread:!1};if(O.current.set(Ku,{...Wu,task:xu}),c.current===Ku)o(xu)}}}zn(()=>{v0(!1)},[s,Zl,zu]),zn(()=>{let B=m5(fu);F.current+=1;let M=F.current;if(!i||B.length===0){ju(null),qu(!1),e(!1),w.current=!1;return}qu(!0),ju(null);let d=window.setTimeout(()=>{(async()=>{try{let nu=await _E(l,pu,B);if(M!==F.current)return;ju(Xw(nu))}catch(nu){if(M===F.current)ju(null),zf(Al(nu,"搜索 Codex tasks 失败"))}finally{if(M===F.current)qu(!1)}})()},240);return()=>window.clearTimeout(d)},[i?.id,l,pu,fu]),zn(()=>{gu(b?ht(b):""),Pf(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},[k]);function N0(B,M,d){let nu=O.current.get(B)||{},Fu=nu.task||{},Ku=Array.isArray(Fu.transcript)?Fu.transcript:[],Wu=lQ(Fu,M),Cu=Object.prototype.hasOwnProperty.call(M,"transcript")?Y5(Ku,Array.isArray(M.transcript)?M.transcript:[]):Ku,xu={...Fu,...Wu,transcript:Cu,output:Array.isArray(Wu.output)?h5(Fu,Wu,"output"):Array.isArray(Fu.output)?Fu.output:[],events:Array.isArray(Wu.events)?h5(Fu,Wu,"events"):Array.isArray(Fu.events)?Fu.events:[]},mu=d$(xu),Ru=String(mu?.updatedAt||""),cf=Boolean(M._transcriptComplete)&&xr(mu),il=Boolean(nu.complete)&&xr(mu)&&String(nu.completeUpdatedAt||"")===Ru,du=cf||il,df={...nu,task:mu,maxSeq:Rt(Cu),complete:du,completeUpdatedAt:du?Ru:""};if(O.current.set(B,df),d===U.current&&c.current===B)o(mu);return df}async function o1(B,M=!1,d,nu){if(!i||!B)return;let Ku=O.current.get(B)?.task;if(!M&&Mt(Ku))return;let Wu=B,Cu=N.current.get(Wu);if(Cu){if(M||!Mt(Ku))Cu.refreshAfter=!0;return Cu.promise}let xu=U.current,mu=performance.now();if(c.current===B)x(!0);let Ru={promise:Promise.resolve(),refreshAfter:!1},cf=(async()=>{try{let il=await tE(l,B);if(xu!==U.current||c.current!==B)return;let du=il?.summary||{},df=String(du.updatedAt||"");N0(B,{id:B,status:du.status,updatedAt:df,startedAt:du.startedAt,finishedAt:du.finishedAt,currentAttempt:du.currentAttempt,maxAttempts:du.maxAttempts,finalResponse:du.finalResponse,lastJudge:du.lastJudge,lastError:du.lastError,attempts:Array.isArray(du.attempts)?du.attempts:[],stepCount:du.stepCount,llmStepCount:du.llmStepCount,traceStats:du.traceStats,statsSource:du.statsSource,timing:du.timing,_traceSummary:du,_traceSummaryLoaded:!0,_traceSummaryUpdatedAt:df,_detailLoaded:!0},xu),sr({phase:"complete",taskId:B,queueMs:nu??0,detailMs:performance.now()-mu,totalMs:d===void 0?performance.now()-mu:performance.now()-d,chunks:1,transcriptRows:Number(du?.execution?.traceLineCount||du?.execution?.stepCount||0),partial:!1,completedAt:new Date})}finally{let il=Boolean(Ru.refreshAfter&&c.current===B&&!Mt(O.current.get(B)?.task));if(N.current.delete(Wu),xu===U.current&&c.current===B)x(!1);if(il)window.setTimeout(()=>{o1(B,!0).catch((du)=>zf(Al(du,"自动刷新 Trace Summary 失败")))},0)}})();Ru.promise=cf,N.current.set(Wu,Ru),await cf}async function pw(B,M=null){let d=c.current;if(!i||!d||!B)return;let nu=O.current.get(d)?.task,Fu=bt(nu),Ku=B==="feedback"||B==="judge-feedback"?WQ(M):B;if(Fu[Ku]?.text)return;let Wu=`${d}:${Ku}`,Cu=q.current.get(Wu);if(Cu)return Cu;let xu=U.current;if(c.current===d)x(!0);let mu=(async()=>{try{let Ru=await AE(l,d,B,M);if(xu!==U.current||c.current!==d)return;let cf=O.current.get(d)?.task,il=bt(cf);N0(d,{...B==="full"?{prompt:String(Ru?.text||""),promptChars:Number(Ru?.chars||0)}:{},_promptDetails:{...il,[Ku]:Ru}},xu)}finally{if(q.current.delete(Wu),xu===U.current&&c.current===d)x(!1)}})();q.current.set(Wu,mu),await mu}async function x8(B=null,M={}){let d=c.current;if(!i||!d)return;let nu=O.current.get(d)?.task,Fu=B===null||B===void 0||String(B).length===0?"":String(B),Ku=C5(nu,Fu||null),Wu=Boolean(M.force),Cu=Boolean(M.incremental);if(Ku&&!Wu)return;let xu=LQ(nu,Fu||null),mu=Cu&&xu.length>0?DE(xu):0,Ru=`${d}:${Fu||"all"}:${mu}`,cf=W.current.get(Ru);if(cf)return cf;let il=U.current;if(c.current===d)x(!0);let du=(async()=>{try{let df=await cE(l,d,mu,500,Fu||null);if(il!==U.current||c.current!==d)return;let g0=Array.isArray(df?.steps)?df.steps:[],s0=mu>0?XE(xu,g0):g0;if(Fu){let a0=O.current.get(d)?.task,d1=Wf(a0?._traceStepsByAttempt)||{},yl=Wf(a0?._traceStepsLoadedByAttempt)||{},W0=Wf(a0?._traceStepsNextAfterSeqByAttempt)||{};N0(d,{_traceStepsByAttempt:{...d1,[Fu]:s0},_traceStepsLoadedByAttempt:{...yl,[Fu]:!0},_traceStepsNextAfterSeqByAttempt:{...W0,[Fu]:df?.nextAfterSeq}},il)}else N0(d,{_traceSteps:s0,_traceStepsLoaded:!0,_traceStepsHasMore:Boolean(df?.hasMore),_traceStepsNextAfterSeq:df?.nextAfterSeq},il)}finally{if(W.current.delete(Ru),il===U.current&&c.current===d)x(!1)}})();W.current.set(Ru,du),await du}async function mw(B){let M=c.current,d=String(B??"");if(!i||!M||d.length===0)return;let nu=O.current.get(M)?.task;if(R5(nu)[d]?.line)return;let Ku=`${M}:${d}`,Wu=z.current.get(Ku);if(Wu)return Wu;let Cu=U.current;if(c.current===M)x(!0);let xu=(async()=>{try{let mu=await jE(l,M,B);if(Cu!==U.current||c.current!==M)return;let Ru=O.current.get(M)?.task,cf=R5(Ru);N0(M,{_traceStepDetails:{...cf,[d]:mu}},Cu)}finally{if(z.current.delete(Ku),Cu===U.current&&c.current===M)x(!1)}})();z.current.set(Ku,xu),await xu}function Pw(B){if(c.current!==B)return;let M=O.current.get(B)?.task;if(!M)return;if(C5(M,null))x8(null,{force:!0,incremental:!0}).catch((nu)=>zf(Al(nu,"增量刷新 Trace Steps 失败")));let d=Wf(M?._traceStepsLoadedByAttempt)||{};for(let nu of Object.keys(d).filter((Fu)=>d[Fu]))x8(nu,{force:!0,incremental:!0}).catch((Fu)=>zf(Al(Fu,"增量刷新 Attempt Trace Steps 失败")))}async function hp(B,M,d){if(!i||!B)return;let nu=performance.now(),Fu=U.current,Ku=O.current.get(B);if(Ku?.task){if(o(Ku.task),x(p_(Ku.task)||!Ku.complete),!p_(Ku.task)&&Ku.complete&&xr(Ku.task)&&String(Ku.completeUpdatedAt||"")===String(Ku.task?.updatedAt||"")){sr({phase:"complete",taskId:B,queueMs:d??0,detailMs:0,totalMs:M===void 0?0:performance.now()-M,chunks:0,transcriptRows:Array.isArray(Ku.task.transcript)?Ku.task.transcript.length:0,completedAt:new Date});return}}else x(!0);let Wu=J.current;if(Wu?.taskId===B&&Wu.token===Fu)return Wu.promise;let Cu=(async()=>{try{let xu=await Rf(xf(l,`/api/tasks/${encodeURIComponent(B)}?meta=1`));if(Fu!==U.current||c.current!==B)return;let mu=O.current.get(B),Ru=Array.isArray(mu?.task?.transcript)?mu.task.transcript:[],cf=xu?.task||{},il=Boolean(mu?.complete)&&String(mu?.completeUpdatedAt||"")===String(cf?.updatedAt||"");N0(B,{...cf,summaryOnly:!1,_metaLoaded:!0,transcript:Ru,_detailLoaded:Ru.length>0,_transcriptComplete:il},Fu);let du=p_(mu?.task)||Boolean(mu?.task?._transcriptPreview),df=du?0:Ru.length>0?rQ(Ru):0,g0=!du&&mu?.complete&&xr(cf)&&String(mu?.completeUpdatedAt||"")===String(cf?.updatedAt||"")?Rt(Ru):df,s0=!0,a0=0,d1=Ru.length;while(s0){let yl=await Rf(xf(l,`/api/tasks/${encodeURIComponent(B)}/transcript?afterSeq=${encodeURIComponent(String(g0))}&limit=${IT}&fullText=1`));if(Fu!==U.current||c.current!==B)return;let W0=O.current.get(B),u3=Array.isArray(W0?.task?.transcript)?W0.task.transcript:[],kf=Y5(u3,Array.isArray(yl?.transcript)?yl.transcript:[]);a0+=1,d1=kf.length;let f3=Boolean(!yl?.hasMore);if(N0(B,{status:yl?.status||cf.status,updatedAt:yl?.updatedAt||cf.updatedAt,transcript:kf,_detailLoaded:f3||kf.length>0,_transcriptComplete:f3,_transcriptPreview:du&&!f3},Fu),s0=Boolean(yl?.hasMore),g0=Number(yl?.nextAfterSeq??Rt(kf)),!s0)break;await new Promise((e1)=>window.setTimeout(e1,0))}sr({phase:"complete",taskId:B,queueMs:d??0,detailMs:performance.now()-nu,totalMs:M===void 0?performance.now()-nu:performance.now()-M,chunks:a0,transcriptRows:d1,completedAt:new Date})}finally{if(J.current?.taskId===B&&J.current?.token===Fu)J.current=null;if(Fu===U.current&&c.current===B)x(!1)}})();J.current={taskId:B,token:Fu,promise:Cu},await Cu}async function Ml(B=c.current,M=!0,d=pu){if(!i)return;if(!M&&h.current)return;let nu=performance.now();if(M)h.current=!0;if(M)sr({phase:"loading",taskId:String(B||c.current||""),startedAt:new Date});let Fu=j.current+1;j.current=Fu;let Ku=String(B||c.current||""),Wu=Ku?O.current.get(Ku):null,Cu=Array.isArray(Wu?.task?.transcript)?Wu.task.transcript:[],xu=rQ(Cu),mu=null;if(mu=await $E(l,Ku,xu,d),Fu!==j.current){if(M)h.current=!1;return}let Ru=performance.now()-nu;v(X||{});let cf=mu?.queue||{},il=String(cf?.activeTaskId||m_(cf)[0]||""),du=mu;Nr((rr)=>{let Hy=cl(mu),en=cl(rr),By=en.length>0?Mi([en,Hy],il):Mi([Hy],il),l3=a1(By),jK=Gn(mu),r3=Gn(rr),FK=en.length>Hy.length&&(r3.hasMore===!1||String(r3.nextBeforeId||"").length>0),JK={...jK,...FK?{hasMore:r3.hasMore,nextBeforeId:r3.nextBeforeId}:{},returned:l3.length};return du={...mu,tasks:l3,pagination:JK},du});let df=cl(du),g0=IU(cf,bu),s0=gU(cf,g0,d,df),a0=yE(g0,d,df),d1=Ku||c.current,yl=du?.selected||null,W0=yl?.task||null,u3=Array.isArray(yl?.transcript)?yl.transcript:null,kf=d1||s0||a0||df[0]?.id||"";if(c.current!==kf)U.current+=1;c.current=kf,I(kf);let e1=df.find((rr)=>rr.id===kf);if(e1){let rr=O.current.get(kf);if(rr?.task)O.current.set(kf,{...rr,task:{...e1,...rr.task,status:e1.status,updatedAt:e1.updatedAt}})}if(W0?.id===kf&&u3!==null){let rr=O.current.get(kf),Hy=Array.isArray(rr?.task?.transcript)?rr.task.transcript:[],en=Y5(Hy,u3),By=Boolean(yl?.preview);if(N0(kf,{...W0,_summaryLoaded:!0,transcript:en,_detailLoaded:!yl?.hasMore||en.length>0,_transcriptComplete:!By&&!yl?.hasMore&&xr(W0),_transcriptPreview:By},U.current),x(!1),M)sr({phase:"complete",taskId:kf,queueMs:Ru,detailMs:Math.max(0,performance.now()-nu-Ru),totalMs:performance.now()-nu,chunks:1,transcriptRows:en.length,partial:Boolean(By||yl?.hasMore||p_(W0)),completedAt:new Date});if(Gy(new Date),M)h.current=!1;o1(kf,!1,M?nu:void 0,M?Ru:void 0).catch((l3)=>zf(Al(l3,"加载 Codex Trace Summary 失败")));return}if(M)sr({phase:"session",taskId:kf,queueMs:Ru,totalMs:Ru,startedAt:new Date(Date.now()-Ru)});if(kf)o1(kf,!0,M?nu:void 0,M?Ru:void 0).catch((rr)=>zf(Al(rr,"加载 Codex Trace Summary 失败")));else if(U.current+=1,o(null),x(!1),M)sr({phase:"complete",taskId:"",queueMs:Ru,detailMs:0,totalMs:performance.now()-nu,chunks:0,transcriptRows:0,completedAt:new Date});if(Gy(new Date),M)h.current=!1}async function j7(){if(Pl){if(!i||P||w.current)return;let M=String(m8.nextBeforeId||"");if(!M)return;w.current=!0,e(!0),zf("");try{let d=await sU(l,pu,M,yQ,dn),nu=cl(d),Fu=d?.queue||pf||{},Ku=String(Fu?.activeTaskId||m_(Fu)[0]||I1||"");ju((Wu)=>{let Cu=a1(Mi([cl(Wu),nu],Ku)),xu=Gn(d);return{...Wu||{},queue:Fu,tasks:Cu,pagination:{...xu,returned:Cu.length}}})}catch(d){zf(Al(d,"加载更多搜索结果失败"))}finally{w.current=!1,e(!1)}return}if(!i||zy||L.current)return;let B=String(Gn(T).nextBeforeId||"");if(!B)return;L.current=!0,I$(!0),zf("");try{let M=await sU(l,pu,B),d=cl(M),nu=M?.queue||pf||{},Fu=String(nu?.activeTaskId||m_(nu)[0]||I1||"");Nr((Ku)=>{let Wu=a1(Mi([cl(Ku),d],Fu)),Cu=Gn(M);return{...Ku||{},queue:nu,statistics:M?.statistics||Ku?.statistics,tasks:Wu,pagination:{...Cu,returned:Wu.length}}})}catch(M){zf(Al(M,"加载更早 Codex tasks 失败"))}finally{L.current=!1,I$(!1)}}function Mw(B){let M=B.currentTarget;if(!M||P8||!_7)return;if(M.scrollHeight-M.scrollTop-M.clientHeight<120)j7()}async function lr(B,M){h$(!0),zf("");try{await B()}catch(d){zf(Al(d,M))}finally{h$(!1)}}async function h8(B){if(!B)return;try{let M=!1;try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(B),M=!0}catch{M=!1}if(!M){let nu=document.createElement("textarea");nu.value=B,nu.style.position="fixed",nu.style.opacity="0",document.body.appendChild(nu),nu.select(),M=document.execCommand("copy"),document.body.removeChild(nu)}if(!M)throw Error("browser clipboard rejected the copy request");wy(B);let d=`已复制任务 ID:${B}`;vf(d),fr("success",d),window.setTimeout(()=>wy((nu)=>nu===B?"":nu),1600)}catch(M){zf(`复制任务 ID 失败:${Al(M)}`)}}function b8(B){if(!B)return;Ou(B);let M=`已引用任务 ID:${B};提交时后端会读取并注入该任务上下文`;vf(M),fr("success",M)}async function v8(B){if(!i||!B)return;let M=new Date().toISOString();j.current+=1,e$([B],M,null,{id:B,readAt:M,terminalUnread:!1}),b$(B);let d=!1;if(await lr(async()=>{let nu=await FE(l,B),Fu=nu?.task||{id:B,readAt:new Date().toISOString(),terminalUnread:!1},Ku=String(Fu?.readAt||new Date().toISOString());e$([B],Ku,nu?.queue||null,Fu),d=!0;let Wu=`已将任务 ${B} 标为已读`;vf(Wu),fr("success",Wu)},"标记 Codex task 已读失败"),!d)c7([B]),Ml(c.current,!1).catch((nu)=>zf(Al(nu,"刷新 Codex tasks 失败")));b$((nu)=>nu===B?"":nu)}async function Cw(){if(!i||Ky)return;v$(!0);let B=new Date().toISOString(),M=Array.from(new Set([...cl(m.current).filter(D0).map((nu)=>String(nu?.id||"")).filter(Boolean),...Array.from(O.current.entries()).filter(([,nu])=>D0(nu?.task)).map(([nu])=>nu)]));if(j.current+=1,M.length>0)e$(M,B);let d=!1;if(await lr(async()=>{let nu=await JE(l),Fu=String(nu?.readAt||new Date().toISOString()),Ku=cl(m.current).filter(D0).map((Ru)=>String(Ru?.id||"")).filter(Boolean),Wu=Array.from(O.current.entries()).filter(([,Ru])=>D0(Ru?.task)).map(([Ru])=>Ru),Cu=Array.from(new Set([...M,...Ku,...Wu]));e$(Cu,Fu,nu?.queue||null);let xu=Number(nu?.count||Cu.length);d=!0;let mu=`已将 ${xu} 个已结束未读任务标为已读`;vf(mu),fr("success",mu)},"全部标为已读失败"),!d&&M.length>0)c7(M),Ml(c.current,!1).catch((nu)=>zf(Al(nu,"刷新 Codex tasks 失败")));v$(!1)}function Rw(B){let M=B||En;if(Ff(M),!vl(M))eu(M);if(Nr(null),!(vl(M)?c.current:""))c.current="",U.current+=1,I(""),o(null),x(!0)}async function xw(){let B=typeof window>"u"?"":window.prompt("输入新的 Codex queue ID(字母/数字/._-,最长 64)","new-lane"),M=String(B||"").trim();if(!M)return;await lr(async()=>{let d=await Rf(xf(l,"/api/queues"),{method:"POST",body:{queueId:M}}),nu=String(d?.queue?.id||M);eu(nu),Ff(nu),Nr(null),c.current="",U.current+=1,I(""),o(null);let Fu=`已创建并切换到 queue:${nu}`;vf(Fu),fr("success",Fu),await Ml("",!0,nu)},"创建 Codex queue 失败")}async function hw(){let B=String(bu||"default").trim()||"default",M=xi(qr,B)||{id:B,name:B},d=typeof window>"u"?null:window.prompt(`输入 queue 显示名称(ID 不变:${B};留空恢复为 ID)`,AQ(M));if(d===null)return;await lr(async()=>{let nu=await Rf(xf(l,`/api/queues/${encodeURIComponent(B)}`),{method:"PATCH",body:{name:String(d)}}),Fu=nu?.queue||{id:B,name:String(d||B)};if(nu?.summary)Nr((Wu)=>Wu?{...Wu,queue:nu.summary}:Wu);let Ku=`已更新 queue 名称:${P5(Fu)}`;vf(Ku),fr("success",Ku),await Ml(c.current,!0,pu)},"修改 Codex queue 名称失败")}function bw(){if(an.length===0){vf("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let B=an.some((M)=>String(M?.id||"")===fl)?fl:"";of(B),Tl(!0)}async function vw(){let B=sn;if(an.length===0){vf("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let d=String(fl||""||"").trim();if(!d){vf("请先选择要合并的源 queue。");return}if(d===B){zf("源 queue 和目标 queue 不能相同。");return}await lr(async()=>{let nu=await Rf(xf(l,`/api/queues/${encodeURIComponent(B)}/merge`),{method:"POST",body:{sourceQueueId:d}});if(nu?.summary)Nr((Wu)=>Wu?{...Wu,queue:nu.summary}:Wu);eu(B),Ff(B),Nr(null);let Fu=Number(nu?.mergedTaskCount||0),Ku=`已将 queue=${d} 合并到 ${B},移动 ${Fu} 个任务;源 queue 已自动删除。`;vf(Ku),fr("success",Ku),Tl(!1),of(""),await Ml(c.current,!0,B)},"合并 Codex queue 失败")}async function kw(B){if(B.preventDefault(),Q.current){vf("任务正在提交中,请等待当前请求完成,已阻止重复提交。");return}if(q0.length>1&&!ur){zf(`检测到将创建 ${q0.length} 个任务;请先勾选“确认批量入队”,避免误传多个任务。`);return}Q.current=!0,h1(!0),vf("正在提交 Code Queue 任务,请等待后端确认,输入已临时锁定。"),await lr(async()=>{if(q0.length===0)throw Error("prompt 不能为空");let M=L1(zu),d=bu.trim()||"default",nu=[...q0],Fu=(Ru)=>({prompt:Ru,queueId:d,providerId:El,executionMode:cu,model:Jl,cwd:ll,maxAttempts:Number(el),...M.length>0?{referenceTaskIds:M}:{}}),Ku=nu.length===1?Fu(nu[0]):{tasks:nu.map(Fu)},Wu=await Rf(xf(l,nu.length===1?"/api/tasks":"/api/tasks/batch"),{method:"POST",body:Ku}),Cu=Wu?.tasks?.[0]?.id||"",xu=Array.isArray(Wu?.tasks)?Wu.tasks.map((Ru)=>String(Ru?.id||"")).filter(Boolean):[],mu=`已创建 ${xu.length||nu.length} 个任务${xu.length>0?`:${xu.join(" / ")}`:""}`;if(vf(mu),fr("success",mu),Qu(""),Ou(""),v0(!1),c.current=Cu,pu!==d)Nr(null);eu(d),await Ml(Cu,!0,d)},"Codex 任务入队失败"),Q.current=!1,h1(!1)}async function Iw(B){if(B.preventDefault(),!b?.id)return;await lr(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/steer`),{method:"POST",body:{prompt:lu}}),Hu(""),await Ml(b.id)},"追加 prompt 失败")}async function gw(B){B.preventDefault();let M=String(b?.id||"");if(!M||!s1)return;await lr(async()=>{let d=L1(_f),nu=await Rf(xf(l,`/api/tasks/${encodeURIComponent(M)}/edit`),{method:"POST",body:{prompt:Yu,referenceTaskIds:d}}),Fu={...nu?.task||b||{},_traceSummary:null,_traceSummaryLoaded:!1,_traceSummaryUpdatedAt:"",_promptDetails:{},_traceSteps:[],_traceStepsLoaded:!1,_traceStepsByAttempt:{},_traceStepsLoadedByAttempt:{},_traceStepsNextAfterSeqByAttempt:{},_traceStepDetails:{}};O.current.set(M,{...O.current.get(M)||{},task:Fu,complete:!1,completeUpdatedAt:""}),c.current=M,o(Fu),I(M),gu(ht(Fu)),Pf(Array.isArray(Fu?.referenceTaskIds)?Fu.referenceTaskIds.join(" "):""),Nr((Wu)=>{if(!Wu)return Wu;let Cu=cl(Wu).map((xu)=>String(xu?.id||"")===M?{...xu,...Fu}:xu);return{...Wu,queue:nu?.queue||Wu.queue,tasks:Mi([Cu],I1)}});let Ku=nu?.changed===!1?`任务 ${M} 的 prompt 未变化`:`已更新 queued 任务 ${M} 的用户 prompt`;vf(Ku),fr("success",Ku),await Ml(M,!0,pu)},"编辑 queued 任务 prompt 失败")}async function sw(){if(!b?.id)return;await lr(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/interrupt`),{method:"POST",body:{}}),await Ml(b.id)},"打断 Codex session 失败")}async function aw(){if(!b?.id)return;await lr(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/retry`),{method:"POST",body:{}}),await Ml(b.id)},"重新入队失败")}async function ow(B){let M=String(b?.id||""),d=String(B||"").trim();if(!M||!d)return;let nu=M_(b);if(d===nu){vf(`任务 ${M} 已在 queue=${d}`);return}await lr(async()=>{let Ku=(await Rf(xf(l,`/api/tasks/${encodeURIComponent(M)}/move`),{method:"POST",body:{queueId:d}}))?.task||{...b,queueId:d};if(O.current.set(M,{...O.current.get(M)||{},task:Ku}),c.current=M,o(Ku),I(M),eu(d),!vl(pu))Nr(null),Ff(d);let Wu=`已将任务 ${M} 从 ${nu} 移动到 ${d}`;vf(Wu),fr("success",Wu),await Ml(M,!0,vl(pu)?En:d)},"移动任务 queue 失败")}async function dw(){let B=c.current;if(!B)return;let M=performance.now();await lr(async()=>{sr({phase:"session",taskId:B,queueMs:0,totalMs:0,partial:!0,startedAt:new Date}),await o1(B,!0,M,0)},"刷新 Trace Summary 失败")}function ew(B){c.current=B,U.current+=1,I(B);let M=O.current.get(B);if(M?.task)o(M.task),x(!1);else{x(!0);let d=ar.find((nu)=>nu.id===B);if(d)o(d);else o(null)}Ml(B).catch((d)=>zf(Al(d,"切换 Codex session 失败")))}function k8(B){if(ew(B),rE())Ly(!1)}function F7(B,M,d){if(!B||!Array.isArray(B?.tasks)||M.length===0||Object.keys(d).length===0)return B;let nu=!1,Fu=cl(B).map((Ku)=>{if(String(Ku?.id||"")!==M)return Ku;return nu=!0,d$(lQ(Ku,d))});return nu?{...B,tasks:Fu}:B}function uK(B,M){Nr((d)=>F7(d,B,M)),ju((d)=>F7(d,B,M))}function fK(B,M,d){let nu=String(B?.type||"");if(nu==="queue-updated")return!0;if(nu==="trace-stats-updated"||nu==="trace-step-created")return!1;if(M.length===0)return!0;if(!d)return!0;if(B?.queueId&&String(B.queueId)!==M_(d))return!0;if(B?.status&&String(B.status)!==String(d?.status||""))return!0;return String(B?.reason||"")!=="output"}function J7(){if(!i||!B5())return;if(H.current!==null)window.clearTimeout(H.current);H.current=window.setTimeout(()=>{H.current=null,Ml(c.current,!1).catch((B)=>zf(Al(B,"Code Queue 事件刷新失败")))},120)}function lK(B,M){if(!i||!B5()||c.current!==B)return;if(D.current=D.current||M,E.current!==null)return;E.current=window.setTimeout(()=>{E.current=null;let d=D.current;if(D.current=!1,o1(B,!0).catch((nu)=>zf(Al(nu,"事件刷新 Trace Summary 失败"))),d)Pw(B)},250)}function rK(B){let M=Wf(B?.payload)||B,d=Wf(M?.stats),nu=String(B?.type||M?.type||""),Fu=String(M?.subjectKind||d?.subjectKind||""),Ku=String(M?.scopeId||d?.scopeId||""),Wu=String(M?.taskId||(Fu==="task"?M?.subjectId:"")||d?.taskId||B?.taskId||""),Cu=M?.attemptIndex??d?.attemptIndex,xu=Cu===null||Cu===void 0||Cu===""?null:X0(Cu),mu=d||Wf(M?.traceStats),Ru=mu?.stepCount??mu?.llmStepCount,cf=mu?.outputMaxSeq;return{...M,type:nu,eventId:B?.eventId||M?.eventId,sequence:B?.sequence??M?.sequence,taskId:Wu,subjectKind:Fu,scopeId:Ku,attemptIndex:xu,stepCount:Ru,outputMaxSeq:cf,updatedAt:mu?.updatedAt||M?.updatedAt||B?.createdAt,traceStats:mu,statsSource:mu?"oa-event-flow":M?.statsSource}}function nK(B){let M=rK(B),d=String(M?.taskId||""),nu=String(M?.scopeId||M?.traceStats?.scopeId||""),Fu=String(M?.subjectKind||M?.traceStats?.subjectKind||"")==="task-attempt"||Number(M?.attemptIndex)>0||/:attempt:\d+$/u.test(nu),Ku=oU(M?.stepCount),Wu={},Cu=d.length>0?cl(m.current).find((xu)=>String(xu?.id||"")===d):null;if(d.length>0){if(M?.status)Wu.status=String(M.status);if(M?.updatedAt)Wu.updatedAt=String(M.updatedAt);if(M?.queueId)Wu.queueId=String(M.queueId);if(!Fu&&Number.isFinite(Number(M?.stepCount)))Wu.stepCount=Ku,Wu.llmStepCount=Ku;if(!Fu&&Number.isFinite(Number(M?.outputMaxSeq)))Wu.outputMaxSeq=oU(M.outputMaxSeq);if(!Fu&&Wf(M?.traceStats))Wu.traceStats=M.traceStats,Wu.statsSource="oa-event-flow";if(Object.keys(Wu).length>0&&(O.current.has(d)||c.current===d))N0(d,Wu,U.current);if(Object.keys(Wu).length>0)uK(d,Wu);if(c.current===d&&(M?.type==="trace-step-created"||M?.type==="task-updated"||M?.type==="trace-stats-updated")){let xu=JQ(Cu),mu=M?.type==="trace-step-created"||M?.type==="trace-stats-updated"&&!Fu&&Number.isFinite(Number(M?.stepCount))&&(xu===null||Ku>xu);lK(d,mu)}}if(fK(M,d,Cu))J7()}zn(()=>{if(V.current){V.current=!1;return}lr(()=>Ml(c.current),"Code Queue 加载失败")},[i?.id,pu]),zn(()=>{if(!i||typeof EventSource>"u")return;let B=new EventSource(dT(l),{withCredentials:!0}),M=(nu)=>{try{nK(JSON.parse(String(nu.data||"{}")))}catch(Fu){zf(Al(Fu,"解析 Code Queue 事件失败"))}},d=()=>{if(B5())J7()};return B.addEventListener("trace-step-created",M),B.addEventListener("task-updated",M),B.addEventListener("queue-updated",M),B.addEventListener("trace-stats-updated",M),document.addEventListener("visibilitychange",d),()=>{if(B.close(),document.removeEventListener("visibilitychange",d),H.current!==null)window.clearTimeout(H.current),H.current=null;if(E.current!==null)window.clearTimeout(E.current),E.current=null}},[i?.id,l,pu]),zn(()=>{if(!i||!b||g)return;let B=String(b.id||"");if(!B)return;let M=String(b.updatedAt||"");if(Mt(b))return;let d=`${B}:${M||"unknown"}:${String(b?._traceSummaryUpdatedAt||"")}`;if(Z.current.has(d))return;Z.current.add(d),o1(B,!0).catch((nu)=>zf(Al(nu,"自动加载 Trace Summary 失败")))},[i?.id,b?.id,b?.updatedAt,b?.traceStats?.statsRevision,b?._traceSummaryUpdatedAt,b?._traceSummaryLoaded,g]);let iK=or.length===0?K(z1,{title:Pl?Gu?"搜索中":"没有匹配任务":"队列为空",text:Pl?Gu?`正在搜索包含“${dn}”的 task...`:`未找到包含“${dn}”的 task;可换个关键词或切换 queue。`:"提交一个任务后,Codex 会串行执行并保存输出。"}):[i7.length>0?K(S5,{key:"unread",title:"已结束未读",tasks:i7,selectedId:k,emptyText:"暂无已结束未读任务。",onSelect:k8,onCopy:h8,onReference:b8,onMarkRead:v8,copiedTaskId:b1,markingReadTaskId:v1}):null,K(S5,{key:"active",title:"运行 / 排队",tasks:zw,selectedId:k,emptyText:"当前没有运行或排队任务。",onSelect:k8,onCopy:h8,onReference:b8,onMarkRead:v8,copiedTaskId:b1,markingReadTaskId:v1}),K(S5,{key:"history",title:"历史 session",tasks:Tw,selectedId:k,emptyText:"最近没有完成、失败或取消的 session。",onSelect:k8,onCopy:h8,onReference:b8,onMarkRead:v8,copiedTaskId:b1,markingReadTaskId:v1}),K("div",{key:"pagination",className:"codex-task-pagination","data-testid":"codex-task-pagination"},K("span",null,Pl?`搜索“${dn}” · 已显示 ${or.length} / ${Number.isFinite(g1)?g1:or.length}`:`已加载 ${or.length} / ${Number.isFinite(g1)?g1:or.length}`),_7?K("button",{type:"button",className:"ghost-btn",disabled:P8,onClick:()=>void j7(),"data-testid":"codex-load-more-tasks-button"},P8?"加载中":Pl?"加载更多结果":"加载更早任务"):K("code",null,Pl?"已到结果末尾":"已到队列末尾"))],U7=(B,M=!1)=>K("label",{className:`code-queue-switcher ${M?"compact":""}`},K("span",null,M?"Queue":"查看 queue"),K("select",{value:pu,onChange:(d)=>Rw(String(d.target.value||En)),"data-testid":B},K("option",{value:En},`All queues · ${Number.isFinite(on)?on:ar.length} tasks · ${Ty.length} running`),qr.map((d)=>K("option",{key:String(d?.id||""),value:String(d?.id||"")},P_(d))))),yK=K("div",{className:"codex-task-search","data-testid":"codex-task-search"},K("label",{htmlFor:"codex-task-search-input"},"搜索 task"),K("div",{className:"codex-task-search-row"},K("input",{id:"codex-task-search-input",type:"search",value:fu,placeholder:"关键词 / task ID / prompt",autoComplete:"off",onChange:(B)=>$u(String(B.target.value||"")),"data-testid":"codex-task-search-input"}),fu?K("button",{type:"button",className:"ghost-btn",onClick:()=>$u(""),"data-testid":"codex-task-search-clear"},"清除"):null),K("small",{"data-testid":"codex-task-search-summary"},Pl?Gu?"搜索中...":`匹配 ${or.length}/${Number.isFinite(g1)?g1:or.length}`:"支持 task ID、prompt、状态、provider、模型和最近输出关键词")),_K=K("div",{className:"codex-trace-status","data-testid":"codex-trace-status-summary"},K("span",{className:"codex-trace-status-chip queued"},K("b",null,"排队"),String(S8)),K("span",{className:"codex-trace-status-chip running"},K("b",null,"运行"),String(a$)),K("span",{className:`codex-trace-status-chip unread ${k0>0?"warn":""}`},K("b",null,"结束未读"),String(k0)),K("span",{className:"codex-trace-status-chip service"},K("b",null,"服务"),`${Ew.providerStatus||"unknown"} · ${i?.providerId||"D601"} · ${Zw.public?"公网暴露":"仅 UniDesk frontend 代理访问"}`),K("span",{className:"codex-trace-status-chip"},K("b",null,"执行节点"),o$.map((B)=>B.id).join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"执行模式"),A7.map((B)=>B.id).join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"模型"),t7.join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"加载"),ml?.phase==="complete"?sT(ml?.totalMs):String(ml?.phase||"idle")),K("span",{className:"codex-trace-status-chip"},K("b",null,"刷新"),k$?$f(k$):"--")),$K=K(Ci,{title:b?`Trace ${String(b.id).slice(0,22)}`:"Trace 输出",eyebrow:b?`${b.status} / view=${I0} / task queue=${M_(b)} / provider=${b.providerId||"D601"} / mode=${b.executionMode||"default"} / ${b.model} / agent loop trace`:`Agent loop trace / view=${I0}`,summary:_K,loading:g||zy||Gu||P||ml?.phase==="loading",actions:K("div",{className:"panel-actions"},U7("code-queue-filter-select"),K("button",{type:"button",className:"ghost-btn codex-mark-all-read-btn",disabled:k0===0||Zf||Ky,onClick:()=>void Cw(),"data-testid":"codex-mark-all-read-button"},Ky?"标记中":`全部标已读${k0>0?` (${k0})`:""}`),b?K("button",{type:"button",className:"ghost-btn",disabled:g||Zf,onClick:()=>void dw(),"data-testid":"codex-load-full-trace-button"},g?"加载中":cr(b)?"刷新 Summary":"加载 Summary"):null,K("button",{type:"button",className:"codex-session-title-toggle",onClick:()=>Ly((B)=>!B),"data-testid":"code-queue-sidebar-toggle"},Dr?"收起队列":"展开队列"),K("label",{className:"inline-check"},K("input",{type:"checkbox",checked:rf,onChange:(B)=>Ul(Boolean(B.target.checked))}),"自动滚动"),K("button",{type:"button",className:"ghost-btn",disabled:!Bw||Zf,onClick:()=>void sw(),"data-testid":"codex-interrupt-button"},"打断"),K("button",{type:"button",className:"ghost-btn",disabled:!Vw||Zf,onClick:()=>void aw()},"重试"),b?K(tQ,{title:"Codex Task",data:b,onOpen:f,testId:"raw-codex-task"}):null),className:"codex-output-panel"},K("div",{className:`codex-session-shell ${Dr?"":"queue-collapsed"}`},Dr?K("aside",{className:"codex-session-sidebar","data-testid":"codex-session-sidebar"},K("div",{className:"codex-session-sidebar-head"},K("div",null,K("span",null,vl(pu)?"All queues":"Queue lane"),K("strong",null,`${I0} · ${ar.length}/${Number.isFinite(on)?on:ar.length} sessions · 未读 ${k0}`)),K("button",{type:"button",className:"ghost-btn",onClick:()=>Ly(!1)},"收起")),U7("code-queue-filter-sidebar",!0),yK,K("div",{className:"codex-task-list codex-task-list-session",onScroll:Mw,"data-testid":"codex-task-list-scroll"},iK)):null,K("div",{className:"codex-session-main"},K("div",{className:"codex-output-stack"},K(FZ,{task:b,loading:g,onLoadPromptPart:pw,onLoadSteps:x8,onLoadStep:mw}),K(JZ,{task:b})))));if(!i)return K(z1,{title:"Code Queue 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=code-queue"});let Q7=Number(ml?.totalMs),q7=Number(ml?.queueMs),N7=Number(ml?.detailMs),W7=Number(ml?.transcriptRows),tK=ml?.phase==="complete"?"complete":String(ml?.phase||"idle"),AK=xi(qr,sn)||{id:sn,name:sn},cK=Fl?K(hU,{title:"合并 queue",titleId:"codex-merge-dialog-title",className:"codex-merge-dialog",backdropClassName:"codex-merge-dialog-backdrop",bodyClassName:"codex-merge-dialog-body",actionsClassName:"codex-merge-dialog-actions",testId:"codex-merge-queue-dialog",closeTestId:"codex-merge-queue-close",disableClose:Zf,onClose:()=>Tl(!1),actions:[K("button",{key:"cancel",type:"button",className:"ghost-btn",onClick:()=>Tl(!1),disabled:Zf,"data-testid":"codex-merge-queue-cancel"},"取消"),K("button",{key:"confirm",type:"button",className:"primary-btn",onClick:()=>void vw(),disabled:Zf||Jf||!fl,"data-testid":"codex-merge-queue-confirm"},Zf?"合并中...":"确认合并")]},K("p",{className:"codex-merge-dialog-target"},"目标 queue:",K("code",null,P_(AK))),K("label",null,"源 queue",K("select",{value:fl,disabled:Zf||Jf,onChange:(B)=>of(String(B.target.value||"")),"data-testid":"codex-merge-source-queue-select"},K("option",{value:""},"选择要合并进来的源 queue"),an.map((B)=>K("option",{key:String(B?.id||""),value:String(B?.id||"")},P_(B))))),K("p",{className:"codex-merge-dialog-note"},"会把源 queue 的任务归属合并到目标 queue,并自动删除源 queue;目标 queue 会按原 queueEnteredAt/createdAt 时间顺序运行。")):null;return K("div",{className:`code-queue-page ${n?"codex-standalone-page":""}`,"data-testid":"code-queue-page","data-load-state":tK,"data-load-total-ms":Number.isFinite(Q7)?String(Math.round(Q7*10)/10):"","data-load-queue-ms":Number.isFinite(q7)?String(Math.round(q7*10)/10):"","data-load-detail-ms":Number.isFinite(N7)?String(Math.round(N7*10)/10):"","data-load-transcript-rows":Number.isFinite(W7)?String(W7):"","data-load-task-id":String(ml?.taskId||k||""),"data-load-partial":ml?.partial?"true":"false"},K(yf,{error:X8,wide:!0}),cK,K("div",{className:"codex-session-stage codex-session-stage-top"},$K),K("div",{className:"code-queue-layout"},K("div",{className:"codex-left-rail"},K(Ci,{title:"提交任务",eyebrow:Jf?"Submitting...":q0.length>1?`${q0.length} tasks`:"Single or Batch",className:"codex-compose-panel",loading:Jf},K("form",{className:`codex-task-form ${Jf?"is-submitting":""}`,onSubmit:kw,"data-testid":"code-queue-task-form","aria-busy":Jf?"true":"false"},K("label",null,"Prompt / 多任务用单独一行 --- 分隔",K("textarea",{value:s,rows:8,disabled:Jf,onChange:(B)=>Qu(B.target.value),placeholder:"写入 Codex 任务;多个任务之间用 --- 分隔。"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选)",K("input",{value:zu,disabled:Jf,onChange:(B)=>Ou(B.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-reference-task-id"}),L1(zu).length>0?K("code",null,`后端将解析并注入:${L1(zu).join(" / ")}`):null),K("div",{className:"codex-form-grid"},K("label",{className:"codex-submit-queue-field"},"Queue",K("div",{className:"codex-submit-queue-row"},K("select",{className:"codex-submit-queue-select",value:bu,disabled:Jf,onChange:(B)=>eu(String(B.target.value||"default")),"data-testid":"code-queue-id-select"},qr.map((B)=>K("option",{key:String(B?.id||""),value:String(B?.id||"")},P_(B)))),K("button",{type:"button",className:"ghost-btn codex-rename-queue-btn",onClick:()=>void hw(),disabled:Zf||Jf||!bu,title:"修改当前 queue 的显示名称,ID 不变","data-testid":"codex-rename-queue-button"},"改名"),K("button",{type:"button",className:"ghost-btn codex-merge-queue-btn",onClick:()=>bw(),disabled:Zf||Jf||an.length===0,title:"打开独立窗口选择源 queue 并合并到当前 queue;合并后自动删除源 queue","data-testid":"codex-merge-queue-button"},"合并 queue"),K("button",{type:"button",className:"ghost-btn codex-create-queue-btn",onClick:()=>void xw(),disabled:Zf||Jf,"data-testid":"codex-create-queue-button"},"创建 queue"))),K("label",null,"模型",K("select",{value:Jl,disabled:Jf,onChange:(B)=>Su(B.target.value),"data-testid":"codex-model-select"},t7.map((B)=>K("option",{key:B,value:B},B)))),K("label",null,"执行 Provider",K("select",{value:El,disabled:Jf,onChange:(B)=>Yw(String(B.target.value||"D601")),"data-testid":"codex-provider-select"},o$.map((B)=>K("option",{key:B.id,value:B.id},`${B.label||B.id} · ${B.defaultWorkdir||s5(pf,B.id)}${B.supportsWindowsNativeCodex?" · Windows native":""}`)))),K("label",null,"执行模式",K("select",{value:cu,disabled:Jf,onChange:(B)=>Sw(String(B.target.value||"default")),"data-testid":"codex-execution-mode-select"},A7.map((B)=>K("option",{key:B.id,value:B.id},`${B.label||B.id}${B.id==="windows-native"?" · 宿主 Codex":""}`)))),K("label",null,"工作目录",K("input",{value:ll,disabled:Jf,onChange:(B)=>rl(B.target.value),placeholder:Hw||pf?.defaultWorkdir||"/workspace","data-testid":"codex-cwd-input"})),K("label",null,"最大尝试",K("input",{type:"number",min:1,max:99,value:el,disabled:Jf,onChange:(B)=>nl(Number(B.target.value)),"data-testid":"codex-max-attempts-input"})),K("label",null,"入队份数",K("input",{type:"number",min:1,max:50,value:Zl,disabled:Jf,onChange:(B)=>Q0(Number(B.target.value)),"data-testid":"codex-repeat-count-input"}))),Oy>1?K("label",{className:`codex-batch-confirm ${ur?"confirmed":""}`,"data-testid":"codex-batch-confirm-row"},K("input",{type:"checkbox",checked:ur,disabled:Jf,onChange:(B)=>v0(Boolean(B.target.checked)),"data-testid":"codex-batch-confirm-checkbox"}),K("span",null,`确认批量入队 ${Oy} 个任务(prompt 分段 ${M8.length} × 入队份数 ${aU(Zl)})`)):null,Jf?K("div",{className:"codex-submit-wait","data-testid":"codex-submit-wait"},"正在提交到后端,已锁定输入以防重复提交..."):null,K("div",{className:"codex-form-actions"},K("button",{type:"button",className:"ghost-btn",disabled:Zf||Jf||s.length===0&&zu.length===0,onClick:()=>{Qu(""),Ou(""),v0(!1);let B="已清空任务输入栏";vf(B),fr("success",B)},"data-testid":"codex-clear-input-button"},"清空输入"),K("button",{type:"submit",className:"primary-btn",disabled:Ow,"data-testid":"codex-enqueue-button"},Jf?"提交中,请等待...":$7?`请确认批量入队 ${Oy} 个任务`:q0.length>1?`批量入队 ${q0.length} 个任务`:"入队并运行"))))),K("div",{className:"codex-main-stage"},K("div",{className:"codex-detail-grid"},K(Ci,{title:"运行控制",eyebrow:s1?"Queued prompt editable":C8?"Active turn steer":"Steer when running",loading:Zf},K("div",{className:"codex-run-control-stack"},K($Z,{task:b,queueRows:qr,busy:Zf,onMove:ow}),b?.id?K("form",{className:"codex-steer-form codex-edit-prompt-form",onSubmit:gw,"data-testid":"codex-edit-prompt-form"},K("label",null,"编辑 queued 用户 prompt",K("textarea",{value:Yu,rows:5,onChange:(B)=>gu(B.target.value),placeholder:"仅 QUEUED 且尚未开始运行的任务可在这里修改原始用户 prompt。",disabled:!s1||Zf,"data-testid":"codex-edit-prompt-textarea"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选,留空会清除引用)",K("input",{value:_f,disabled:!s1||Zf,onChange:(B)=>Pf(B.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-edit-reference-task-id"}),L1(_f).length>0?K("code",null,`将保留/注入:${L1(_f).join(" / ")}`):null),K("div",{className:"codex-form-actions"},K("button",{type:"button",className:"ghost-btn",disabled:!b?.id||Zf,onClick:()=>{gu(b?ht(b):""),Pf(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},"data-testid":"codex-edit-prompt-reset"},"恢复当前值"),K("button",{type:"submit",className:"primary-btn",disabled:!s1||Zf||Yu.trim().length===0,title:s1?"保存后会重写尚未运行任务的用户 prompt":"只有 QUEUED 且尚未开始的任务可编辑 prompt","data-testid":"codex-edit-prompt-submit"},"保存 queued prompt"))):null,K("form",{className:"codex-steer-form",onSubmit:Iw},K("label",null,"追加 prompt",K("textarea",{value:lu,rows:4,onChange:(B)=>Hu(B.target.value),placeholder:"给正在运行的 Codex session 推入新的指令或纠偏。",disabled:!C8})),K("button",{type:"submit",className:"primary-btn",disabled:!C8||Zf||lu.trim().length===0,"data-testid":"codex-steer-button"},"推入运行中 session")))),K(Ci,{title:"完成判定",eyebrow:b?.lastJudge?b.lastJudge.source:"judge",loading:g},b?.lastJudge?K("div",{className:"codex-judge-card","data-testid":"codex-task-judge-card"},K(G1,{status:b.lastJudge.decision},b.lastJudge.decision),K("strong",null,`${Math.round(Number(b.lastJudge.confidence||0)*100)}% confidence`),K("p",{"data-testid":"codex-task-judge-reason"},p5(b.lastJudge.reason||"--",180)),K(qQ,{judge:b.lastJudge,testId:"codex-task-judge-failure-details"}),b.lastJudge.continuePrompt?K("code",{"data-testid":"codex-task-judge-continue-prompt"},p5(b.lastJudge.continuePrompt,160)):null):K(z1,{title:"尚未判定",text:"Codex turn 结束后会由 MiniMax M2.7 或 fallback judge 判定 complete/retry/fail;retry 会在已有 thread 追加继续执行 prompt。"}))),K(_Z,{stats:Y8,queueName:I0,onRaw:f}),K(Ci,{title:"Attempts",eyebrow:"terminal vs interruption",loading:g},K(UZ,{task:b})))))}var x_=Pu(Qf(),1);var Bu=x_.default.createElement,{useEffect:a5}=x_.default,o5=x_.default.useState,QZ=x_.default.useRef,e5=` :root { --surfacePrimary: #ffffff; --surfaceSecondary: #f8fafc; @@ -226,58 +226,58 @@ nav .material-icons::before { display: none !important; } } -`;function a5({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Bu("section",{className:`panel ${n||""}`},Bu("div",{className:"panel-head"},Bu("div",null,f?Bu("p",{className:"panel-eyebrow"},f):null,Bu(nf,{title:u,loading:i})),l?Bu("div",{className:"panel-actions"},l):null),Bu("div",{className:"panel-body"},r))}function UZ({title:u,data:f,onOpen:l,testId:r}){return Bu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function QZ({title:u,text:f}){return Bu("div",{className:"empty-state"},Bu("strong",null,u),Bu("span",null,f))}function OQ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function HQ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function BQ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function qZ(u){return u.filter((l)=>l?.id==="filebrowser"||String(l?.id||"").startsWith("filebrowser-")).sort((l,r)=>{let n=(i)=>i.providerId==="D518"?0:i.providerId==="D601"?1:i.id==="filebrowser"?2:3;return n(l)-n(r)||String(l.id).localeCompare(String(r.id))})}function NZ(u){if(u?.providerId==="D518")return"D518";return u?.providerId||u?.name||u?.id||"Unknown"}function WZ(u,f,l="/"){let r=l.startsWith("/")?l:`/${l}`;return`${u}/microservices/${encodeURIComponent(f)}/proxy${r}`}function LZ(u,f){return`${u}/microservices/${encodeURIComponent(f)}/health`}async function wZ(u,f=16000){let l=new AbortController,r=setTimeout(()=>l.abort(),f);try{return await Eu(u,{signal:l.signal,failureFields:[!1]})}finally{clearTimeout(r)}}function VQ(u){if(u?.providerId==="main-server")return"host / -> /srv";if(u?.providerId==="D601"||u?.providerId==="D518")return"WSL / + /mnt/c -> /srv";return"provider / -> /srv"}function vt(u){return u?.status==="OK"||u?.ok===!0}function KZ({service:u,active:f,health:l,onSelect:r,onRaw:n}){let i=OQ(u),y=HQ(u),_=BQ(u),$=i.container||{},A=vt(l?.body);return Bu("button",{type:"button",className:`filebrowser-target-card ${f?"active":""}`,"data-testid":`filebrowser-target-card-${u.id}`,onClick:r},Bu("span",{className:`status-badge ${A?"ok":i.providerStatus==="online"?"running":"warn"}`},A?"Health OK":i.providerStatus||"unknown"),Bu("strong",null,u.name||u.id),Bu("span",null,VQ(u)),Bu("code",null,`${y.nodeBindHost||"--"}:${y.nodePort||"--"}`),Bu("small",null,$.name?`${$.name} / ${$.state||"--"}`:`${_.composeService||"--"}`),Bu("span",{className:"filebrowser-card-raw",onClick:(c)=>{c.stopPropagation(),n(`${u.name} service`,u)}},"JSON"))}function DQ(u){try{return u?.contentDocument||u?.contentWindow?.document||null}catch{return null}}function d5(u){let f=DQ(u);if(f===null||f.head===null)return!1;let l=f.getElementById("unidesk-filebrowser-compact-style");if(l===null)l=f.createElement("style"),l.id="unidesk-filebrowser-compact-style",f.head.appendChild(l);if(l.textContent!==o5)l.textContent=o5;return!0}function GZ(u,f){let l=URL.createObjectURL(u),r=document.createElement("a");r.href=l,r.download=f,document.body.appendChild(r),r.click(),r.remove(),setTimeout(()=>URL.revokeObjectURL(l),2000)}function zZ(u,f){let l=DQ(u);if(l===null||l.documentElement===null)throw Error("无法访问 File Browser iframe 文档");d5(u);let r=Math.max(640,Math.ceil(u.clientWidth||l.documentElement.clientWidth||1280)),n=Math.max(480,Math.ceil(u.clientHeight||l.documentElement.clientHeight||720)),i=l.documentElement.cloneNode(!0);i.querySelectorAll("script, style, link[rel='stylesheet'], link[rel='preload'], link[rel='icon']").forEach((c)=>c.remove()),i.querySelectorAll("img").forEach((c)=>{c.removeAttribute("src"),c.removeAttribute("srcset")});let y=i.querySelector("head");if(y===null)y=l.createElement("head"),i.insertBefore(y,i.firstChild);let _=l.createElement("style");_.textContent=`${o5} -html,body{width:${r}px!important;min-height:${n}px!important;overflow:hidden!important;}`,y.appendChild(_);let $=new XMLSerializer().serializeToString(i),A=`${$}`;GZ(new Blob([A],{type:"image/svg+xml;charset=utf-8"}),f.replace(/\.png$/i,".svg"))}function XQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=qZ(Array.isArray(u)?u:[]),n=new URLSearchParams(window.location.search).get("target")||"",i=n==="filebrowser-d518"?"filebrowser":n,y=r.some((Z)=>Z.id===i)?i:r[0]?.id||"",[_,$]=s5(y),[A,c]=s5({loading:!1,refreshedAt:null,health:{},error:""}),[j,F]=s5({exporting:!1,message:"",error:""}),U=JZ(null),Q=r.find((Z)=>Z.id===_)||r[0]||null,L=OQ(Q),w=HQ(Q),J=BQ(Q),N=Q?A.health[Q.id]:null,q=Q?WZ(l,Q.id,"/"):"about:blank";g5(()=>{if(r.length===0)return;if(!_||!r.some((Z)=>Z.id===_))$(r[0].id)},[r.map((Z)=>Z.id).join(",")]),g5(()=>{let Z=0,H=setInterval(()=>{if(Z+=1,d5(U.current)||Z>=24)clearInterval(H)},500);return()=>clearInterval(H)},[q]),g5(()=>{if(r.length===0)return;let Z=!1;async function H(){c((h)=>({...h,loading:!0,error:""}));let D=await Promise.all(r.map(async(h)=>{try{let V=await wZ(LZ(l,h.id));return[h.id,{ok:!0,body:V}]}catch(V){return[h.id,{ok:!1,error:Hu(V,"File Browser health failed")}]}}));if(Z)return;c({loading:!1,refreshedAt:new Date().toISOString(),health:Object.fromEntries(D),error:""})}H();let E=setInterval(H,30000);return()=>{Z=!0,clearInterval(E)}},[r.map((Z)=>`${Z.id}:${Z.runtime?.providerStatus||""}`).join(","),l]);function W(Z){$(Z);let H=new URL(window.location.href);H.searchParams.set("target",Z),window.history.replaceState({},"",`${H.pathname}${H.search}`)}async function z(){if(j.exporting)return;F({exporting:!0,message:"",error:""});try{let Z=new Date().toISOString().replace(/[-:.TZ]/g,"").slice(0,14);await zZ(U.current,`unidesk-filebrowser-${Q?.id||"target"}-${Z}.png`),F({exporting:!1,message:"截图已导出",error:""})}catch(Z){F({exporting:!1,message:"",error:Hu(Z,"截图导出失败")})}}if(r.length===0)return Bu(QZ,{title:"File Browser 未登记",text:"请在 config.json 的 microservices 中登记 id=filebrowser 或 filebrowser-* 用户服务"});return Bu("div",{className:"filebrowser-page","data-testid":"filebrowser-page"},A.error?Bu(yf,{error:A.error,wide:!0}):null,Bu(a5,{title:"文件管理器",eyebrow:"File Browser / Host Files",loading:A.loading,actions:Bu("div",{className:"panel-actions"},Q?Bu("button",{type:"button",className:"ghost-btn",onClick:z,disabled:j.exporting,"data-testid":"filebrowser-export-screenshot"},j.exporting?"导出中...":"导出截图"):null,Q?Bu("a",{className:"ghost-btn",href:q,target:"_blank",rel:"noreferrer"},"新窗口打开"):null,Q?Bu(UZ,{title:"File Browser 当前目标",data:{service:Q,health:N},onOpen:f,testId:"raw-filebrowser-active"}):null)},Bu("div",{className:"filebrowser-hero"},Bu("div",null,Bu("span",{className:`status-badge ${vt(N?.body)?"ok":"warn"}`},vt(N?.body)?"Health OK":"Health Pending"),Bu("h3",null,Q?.name||"File Browser"),Bu("p",{className:"muted paragraph"},Q?.description||"通过 UniDesk 登录态代理访问,不开放 File Browser 公网端口。"),j.error?Bu("p",{className:"filebrowser-shot-error"},j.error):null,j.message?Bu("p",{className:"filebrowser-shot-ok"},j.message):null),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Provider"),Bu("strong",null,Q?.providerId||"--"),Bu("code",null,L.providerName||Q?.providerId||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Private Backend"),Bu("strong",null,`${w.nodeBindHost||"--"}:${w.nodePort||"--"}`),Bu("code",null,w.nodeBaseUrl||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Image"),Bu("strong",null,J.dockerfile||"filebrowser/filebrowser:v2.63.3"),Bu("code",null,J.commitId||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Mount"),Bu("strong",null,VQ(Q)),Bu("code",null,Q?.providerId==="main-server"?"/root, /var, /home":"/home, /mnt/c, /mnt/d")))),Bu(a5,{title:"浏览目标",eyebrow:`${r.length} host targets`,loading:A.loading},Bu("div",{className:"filebrowser-target-grid"},r.map((Z)=>Bu(KZ,{key:Z.id,service:Z,active:Z.id===Q?.id,health:A.health[Z.id],onSelect:()=>W(Z.id),onRaw:f})))),Bu(a5,{title:`${NZ(Q)} 文件视图`,eyebrow:N?.body?`Health ${vt(N.body)?"OK":"UNKNOWN"} / ${A.refreshedAt?tf(A.refreshedAt):"--"}`:"Embedded WebUI",className:"filebrowser-frame-panel"},Bu("div",{className:"filebrowser-frame-shell"},Bu("div",{className:"filebrowser-frame-toolbar"},Bu("span",null,"BaseURL"),Bu("code",null,`/api/microservices/${Q?.id||"filebrowser"}/proxy`),Bu("span",null,"Root"),Bu("code",null,"/srv"),Bu("span",{className:"filebrowser-compact-note"},"Compact layout injected")),Bu("iframe",{ref:U,key:q,title:`${Q?.name||"File Browser"} WebUI`,src:q,className:"filebrowser-frame","data-testid":"filebrowser-frame",onLoad:(Z)=>d5(Z.currentTarget),sandbox:"allow-downloads allow-forms allow-modals allow-same-origin allow-scripts"}))))}var st=Pu(qf(),1);var Ju=st.default.createElement,{useEffect:TZ}=st.default,EZ=st.default.useState;function kt({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return Ju("span",{className:`status-badge ${l}`},f||u||"unknown")}function zn({label:u,value:f,hint:l,tone:r}){return Ju("article",{className:`metric-card ${r||""}`},Ju("div",{className:"metric-label"},u),Ju("div",{className:"metric-value"},f),Ju("div",{className:"metric-hint"},l))}function It({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Ju("section",{className:`panel ${n||""}`},Ju("div",{className:"panel-head"},Ju("div",null,f?Ju("p",{className:"panel-eyebrow"},f):null,Ju(nf,{title:u,loading:i})),l?Ju("div",{className:"panel-actions"},l):null),Ju("div",{className:"panel-body"},r))}function gt({title:u,data:f,onOpen:l,testId:r}){return Ju("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function e5({title:u,text:f}){return Ju("div",{className:"empty-state"},Ju("strong",null,u),Ju("span",null,f))}function ZZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function OZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function HZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function K1(u,f){let l=u&&typeof u==="object"?u[f]:void 0;return Number.isFinite(Number(l))?String(l):"--"}function BZ(u){return(Array.isArray(u?.jobs)?u.jobs:[]).slice(0,40)}function VZ(u){return(Array.isArray(u?.drafts)?u.drafts:[]).slice(0,12)}function YQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((Q)=>Q.id==="findjob")||null,[n,i]=EZ({loading:!1,error:"",health:null,summary:null,jobs:null,drafts:null,refreshedAt:null});async function y(){if(!r)return;i((Q)=>({...Q,loading:!0,error:""}));try{let[Q,L,w,J]=await Promise.all([Eu(`${l}/microservices/findjob/health`),Eu(`${l}/microservices/findjob/proxy/api/summary`),Eu(`${l}/microservices/findjob/proxy/api/jobs?__unideskArrayLimit=jobs:40`),Eu(`${l}/microservices/findjob/proxy/api/drafts`)]);i({loading:!1,error:"",health:Q,summary:L,jobs:w,drafts:J,refreshedAt:new Date})}catch(Q){i((L)=>({...L,loading:!1,error:Hu(Q,"FindJob 加载失败")}))}}if(TZ(()=>{y()},[r?.id,r?.runtime?.providerStatus]),!r)return Ju(e5,{title:"FindJob 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=findjob"});let _=ZZ(r),$=HZ(r),A=OZ(r),c=n.summary||{},j=BZ(n.jobs),F=VZ(n.drafts),U=n.jobs?._unidesk?.arrayLimits?.jobs;return Ju("div",{className:"findjob-page","data-testid":"findjob-page"},Ju(It,{title:"FindJob 工作台",eyebrow:"D601 用户服务",loading:n.loading,actions:Ju("div",{className:"panel-actions"},Ju("button",{type:"button",className:"ghost-btn",onClick:y,disabled:n.loading,"data-testid":"findjob-refresh-button"},n.loading?"刷新中":"刷新"),Ju(gt,{title:"FindJob 用户服务",data:r,onOpen:f,testId:"raw-findjob-service"}))},Ju("div",{className:"findjob-hero"},Ju("div",null,Ju("div",{className:"node-version-line"},Ju(kt,{status:_.providerStatus==="online"?"online":"warn"},_.providerStatus||"unknown"),Ju("span",null,r.providerId),Ju("span",null,A.public?"公网暴露":"仅 UniDesk frontend 代理访问")),Ju("p",{className:"muted paragraph"},r.description)),Ju("div",{className:"microservice-ref-card"},Ju("span",null,"Repo"),Ju("strong",null,$.url||"--"),Ju("code",null,$.commitId||"--")),Ju("div",{className:"microservice-ref-card"},Ju("span",null,"D601 Docker"),Ju("strong",null,`${A.nodeBindHost||"--"}:${A.nodePort||"--"}`),Ju("code",null,`${$.composeFile||"--"} / ${$.composeService||"--"}`))),Ju(yf,{error:n.error,wide:!0})),Ju("div",{className:"findjob-grid"},Ju(It,{title:"岗位指标",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Summary",loading:n.loading},Ju("div",{className:"metric-grid"},Ju(zn,{label:"岗位总量",value:K1(c,"totalJobs"),hint:"tracked jobs",tone:"ok"}),Ju(zn,{label:"原始岗位",value:K1(c,"rawJobs"),hint:"raw queue"}),Ju(zn,{label:"已验证",value:K1(c,"verifiedJobs"),hint:"verified set"}),Ju(zn,{label:"优先处理",value:K1(c,"prioritizedJobs"),hint:"prioritized"}),Ju(zn,{label:"过期",value:K1(c,"staleJobs"),hint:"stale jobs",tone:"warn"}),Ju(zn,{label:"无效",value:K1(c,"invalidJobs"),hint:"invalid jobs",tone:"warn"}),Ju(zn,{label:"上海",value:K1(c,"shanghaiJobs"),hint:"city filter"}),Ju(zn,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /api/health"})),Ju("div",{className:"panel-actions inline-actions"},Ju(gt,{title:"FindJob Summary",data:c,onOpen:f,testId:"raw-findjob-summary"}))),Ju(It,{title:"近期岗位",eyebrow:U?`${U.returnedLength}/${U.originalLength} Preview`:`${j.length} Preview`,loading:n.loading},j.length===0?Ju(e5,{title:"暂无岗位预览",text:"等待 D601 findjob backend 返回 /api/jobs"}):Ju("div",{className:"table-wrap findjob-job-table"},Ju("table",null,Ju("thead",null,Ju("tr",null,Ju("th",null,"优先级"),Ju("th",null,"状态"),Ju("th",null,"单位"),Ju("th",null,"职位"),Ju("th",null,"城市"),Ju("th",null,"阶段"),Ju("th",null,"截止"),Ju("th",null,"证据"))),Ju("tbody",null,j.map((Q)=>Ju("tr",{key:Q.id},Ju("td",null,Ju(kt,{status:String(Q.priority||"").toLowerCase()||"unknown"},Q.priority||"--")),Ju("td",null,Ju(kt,{status:String(Q.status||"").toLowerCase()||"unknown"},Q.status||"--")),Ju("td",null,Q.organization_name||"--",Ju("code",null,Q.id||"--")),Ju("td",null,Q.display_title||Q.title||"--"),Ju("td",null,Q.display_city||Q.city||"--"),Ju("td",null,Q.workflow_stage||"--"),Ju("td",null,Q.deadline||"--"),Ju("td",null,Q.evidence_url?Ju("a",{href:Q.evidence_url,target:"_blank",rel:"noreferrer"},"打开"):Ju("span",{className:"muted"},"无"))))))),Ju("div",{className:"panel-actions inline-actions"},Ju(gt,{title:"FindJob Jobs Preview",data:n.jobs,onOpen:f,testId:"raw-findjob-jobs"}))),Ju(It,{title:"草稿与报告",eyebrow:`${F.length} Drafts`,loading:n.loading},F.length===0?Ju(e5,{title:"暂无草稿",text:"D601 findjob backend 未返回 drafts"}):Ju("div",{className:"draft-list"},F.map((Q)=>Ju("article",{key:Q.id,className:"draft-card"},Ju("div",{className:"node-card-head"},Ju("strong",null,Q.id),Ju(kt,{status:Q.status},Q.status||"--")),Ju("div",{className:"docker-meta compact"},Ju("span",null,Q.workflow_stage||"--"),Ju("span",null,`jobs ${Q.counts?.jobs??0}`),Ju("span",null,`reports ${Q.counts?.reports??0}`)),Ju("span",null,Q.latestReportPath||"暂无报告"),Ju("code",null,Nu(Q.updated_at||Q.updatedAt))))),Ju("div",{className:"panel-actions inline-actions"},Ju(gt,{title:"FindJob Drafts",data:n.drafts,onOpen:f,testId:"raw-findjob-drafts"})))))}var h_=Pu(qf(),1);var C=h_.default.createElement,{useEffect:DZ}=h_.default,uA=h_.default.useState;function C_(u){let f=Number(u);return Number.isFinite(f)?`${Math.max(0,Math.min(100,f)).toFixed(1)}%`:"--"}function lA(u){if(u===null||u===void 0||u==="")return"--";let f=Number(u);if(!Number.isFinite(f))return"--";if(f<60)return`${Math.max(0,Math.round(f))}s`;if(f<3600)return`${Math.floor(f/60)}m ${Math.round(f%60)}s`;return`${Math.floor(f/3600)}h ${Math.floor(f%3600/60)}m`}function rA(u,f=2){let l=Number(u);if(!Number.isFinite(l))return u===!1?"false":u===!0?"true":"--";let r=Math.abs(l);if(Number.isInteger(l)||r>=1000)return l.toLocaleString("zh-CN",{maximumFractionDigits:0});if(r>=1)return l.toLocaleString("zh-CN",{maximumFractionDigits:f});return l.toLocaleString("zh-CN",{maximumFractionDigits:Math.max(f,6)})}function x_(u){if(u===null||u===void 0||u==="")return"--";if(typeof u==="boolean")return u?"true":"false";if(typeof u==="number")return rA(u,4);if(Array.isArray(u))return u.map((f)=>x_(f)).join(" x ");if(typeof u==="object")return"已上报";return String(u)}function at(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=f>=100?0:f>=10?1:2;return`${f.toLocaleString("zh-CN",{maximumFractionDigits:l})} epoch/h`}function ot(u){return u.replace(/[^a-zA-Z0-9_-]/g,"-")}function vl(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function R_({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return C("span",{className:`status-badge ${l}`},f||u||"unknown")}function Tn({label:u,value:f,hint:l,tone:r}){return C("article",{className:`metric-card ${r||""}`},C("div",{className:"metric-label"},u),C("div",{className:"metric-value"},f),C("div",{className:"metric-hint"},l))}function fA({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return C("section",{className:`panel ${n||""}`},C("div",{className:"panel-head"},C("div",null,f?C("p",{className:"panel-eyebrow"},f):null,C(nf,{title:u,loading:i})),l?C("div",{className:"panel-actions"},l):null),C("div",{className:"panel-body"},r))}function hi({title:u,data:f,onOpen:l,testId:r}){return C("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function Y0({title:u,text:f}){return C("div",{className:"empty-state"},C("strong",null,u),C("span",null,f))}function XZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function YZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function SZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function pZ(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function mZ(u){return Array.isArray(u?.jobs)?u.jobs.slice(0,240):[]}function PZ(u){return Array.isArray(u?.projects)?u.projects.slice(0,1000):[]}function dt(u){return Array.isArray(u?.projects)?u.projects:[]}function MZ(u,f){if(Array.isArray(f?.gpu))return f.gpu;if(Array.isArray(u?.gpu))return u.gpu;return[]}function jr(u,f){return`${u}/microservices/met-nonlinear/proxy${f}`}function SQ(u){return u.startedAt&&u.finishedAt?lA((Date.parse(u.finishedAt)-Date.parse(u.startedAt))/1000):"--"}function CZ(u){let f=u.progress||{};if(f.etaSeconds!==null&&f.etaSeconds!==void 0&&f.etaSeconds!==""){let y=Number(f.etaSeconds);if(Number.isFinite(y))return Math.max(0,y)}let l=Number(f.currentEpoch),r=Number(f.epochTarget??u.epochTarget),n=Date.parse(u.startedAt||"");if(!Number.isFinite(l)||l<=0||!Number.isFinite(r)||r<=l||!Number.isFinite(n))return null;let i=Math.max(0,(Date.now()-n)/1000);if(i<=0)return null;return Math.max(0,i/l*(r-l))}function pQ(u){let f=u.progress||{},l=Number(f.epochPerHour);if(Number.isFinite(l)&&l>0)return l;let r=Date.parse(u.startedAt||""),n=["succeeded","failed","canceled"].includes(u.status)?Date.parse(u.finishedAt||""):Date.now();if(!Number.isFinite(r)||!Number.isFinite(n)||n<=r)return null;let i=Number(f.currentEpoch??u.epochTarget);if(!Number.isFinite(i)||i<=0)return null;return i/((n-r)/3600000)}function mQ(u){if(u==="staged")return"待启动";if(u==="queued")return"排队中";if(u==="running")return"训练中";if(u==="succeeded")return"已完成";if(u==="failed")return"失败";if(u==="canceled")return"已取消";return u||"unknown"}function PQ(u,f,l){return{name:u,path:f,depth:l,count:0,children:[],project:null}}function RZ(u){let f=PQ("","",-1);for(let r of u){let i=String(r?.projectPath||"").replace(/\\/g,"/").split("/").filter(Boolean);if(i.length===0)continue;let y=f,_=[];for(let[$,A]of i.entries()){_.push(A);let c=_.join("/"),j=y.children.find((F)=>F.path===c);if(!j)j=PQ(A,c,$),y.children.push(j);if($===i.length-1)j.project=r;y=j}}let l=(r)=>{let n=r.children.reduce((i,y)=>i+l(y),0);return r.count=(r.project?1:0)+n,r.children.sort((i,y)=>{if(Boolean(i.project)!==Boolean(y.project))return i.project?1:-1;return i.name.localeCompare(y.name,"zh-CN",{numeric:!0,sensitivity:"base"})}),r.count};return l(f),f}function xZ(u){let f=vl(u.data);return vl(f.project).projectPath?vl(f.project):f}function hZ(u){return vl(vl(u.data).job)}function MQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((P)=>P.id==="met-nonlinear")||null,[n,i]=uA({loading:!1,actionBusy:!1,error:"",health:null,summary:null,queue:null,projects:null,history:null,images:null,refreshedAt:null}),[y,_]=uA({loading:!1,error:"",kind:"",key:"",title:"",data:null}),[$,A]=uA(()=>({activeTab:"projects",selectedProjects:{},expandedProjectDirs:{},sourceProject:"",forkCount:1,forkEpochs:200,forkPrefix:`ui_fork_${Date.now()}`,maxConcurrency:3,targetGpuName:"2080 Ti",actionMessage:""}));function c(P){A((e)=>({...e,...P}))}async function j(P=$.activeTab){if(!r)return;i((e)=>({...e,loading:!0,error:""}));try{let e=[["health",Eu(`${l}/microservices/met-nonlinear/health`)],["summary",Eu(jr(l,"/api/summary"))]];if(P==="projects")e.push(["projectsRoot",Eu(jr(l,"/api/projects?root=projects&limit=500"))]),e.push(["exProjectsRoot",Eu(jr(l,"/api/projects?root=ex_projects&limit=500"))]);if(P==="current"||P==="completed"||P==="failed")e.push(["queue",Eu(jr(l,"/api/queue"))]);if(P==="completed"||P==="failed")e.push(["history",Eu(jr(l,"/api/history"))]);if(P==="gpu")e.push(["images",Eu(jr(l,"/api/images"))]);let uu=Object.fromEntries(await Promise.all(e.map(async([g,Qu])=>[g,await Qu]))),Wu={loading:!1,actionBusy:!1,error:"",health:uu.health,summary:uu.summary,refreshedAt:new Date};if(uu.projectsRoot||uu.exProjectsRoot){let{projectsRoot:g,exProjectsRoot:Qu}=uu;Wu.projects={ok:g?.ok!==!1&&Qu?.ok!==!1,roots:[{root:"projects",count:dt(g).length},{root:"ex_projects",count:dt(Qu).length}],projects:[...dt(g),...dt(Qu)]}}if(uu.queue)Wu.queue=uu.queue;if(uu.history)Wu.history=uu.history;if(uu.images)Wu.images=uu.images;i((g)=>({...g,...Wu}))}catch(e){i((uu)=>({...uu,loading:!1,actionBusy:!1,error:Hu(e,"MET Nonlinear 加载失败")}))}}async function F(P,e){i((uu)=>({...uu,actionBusy:!0,error:""})),c({actionMessage:`${P}...`});try{let uu=await e();c({actionMessage:uu||`${P}完成`}),await j()}catch(uu){i((Wu)=>({...Wu,actionBusy:!1,error:Hu(uu,`${P}失败`)}))}}async function U(){await F("保存并发设置",async()=>{await Eu(jr(l,"/api/queue/settings"),{method:"PUT",body:JSON.stringify({maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName})})})}function Q(){return Object.entries($.selectedProjects).filter(([,P])=>P).map(([P])=>P)}async function L(){let P=Q();if(P.length===0)throw Error("请先选择至少一个 project");await F("加入待启动队列",async()=>{await Eu(jr(l,"/api/queue"),{method:"POST",body:JSON.stringify({projectPaths:P,maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName,start:!1})}),c({activeTab:"current",selectedProjects:{}})})}async function w(){let P=$.sourceProject||p[0]?.projectPath;if(!P)throw Error("请先选择源 project");await F("Fork Project",async()=>{let e=await Eu(jr(l,"/api/projects/fork"),{method:"POST",body:JSON.stringify({sourceProject:P,count:Number($.forkCount),epochs:Number($.forkEpochs),prefix:$.forkPrefix})}),uu=Array.isArray(e.projectPaths)?e.projectPaths:[],Wu=uu.reduce((g,Qu)=>{return g[Qu]=!0,g},{...$.selectedProjects});return c({selectedProjects:Wu}),`已 fork ${uu.length} 个 project,并已自动勾选;请确认后点击加入待启动队列。`})}async function J(){await F("启动队列",async()=>{await Eu(jr(l,"/api/queue/start"),{method:"POST",body:JSON.stringify({maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName})}),c({activeTab:"current"})})}async function N(P){await F("取消任务",async()=>{await Eu(jr(l,`/api/jobs/${encodeURIComponent(P.id)}/cancel`),{method:"POST",body:JSON.stringify({})})})}async function q(P){let e=String(P?.projectPath||"");if(!e)return;_({loading:!0,error:"",kind:"project",key:e,title:e,data:null});try{let uu=await Eu(jr(l,`/api/projects/config?path=${encodeURIComponent(e)}`));_({loading:!1,error:"",kind:"project",key:e,title:e,data:uu})}catch(uu){_({loading:!1,error:Hu(uu,"Project 详情加载失败"),kind:"project",key:e,title:e,data:null})}}async function W(P){let e=String(P?.id||"");if(!e)return;_({loading:!0,error:"",kind:"job",key:e,title:P.projectPath||e,data:null});try{let uu=await Eu(jr(l,`/api/jobs/${encodeURIComponent(e)}`));_({loading:!1,error:"",kind:"job",key:e,title:uu?.job?.projectPath||P.projectPath||e,data:uu})}catch(uu){_({loading:!1,error:Hu(uu,"Job 详情加载失败"),kind:"job",key:e,title:P.projectPath||e,data:null})}}if(DZ(()=>{j($.activeTab)},[r?.id,r?.runtime?.providerStatus,$.activeTab]),!r)return C(Y0,{title:"MET Nonlinear 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=met-nonlinear"});let z=XZ(r),Z=SZ(r),H=YZ(r),E=pZ(n.queue?.queue||n.summary?.queue),D=MZ(n.health,n.queue),h=n.health?.targetGpu||n.summary?.targetGpu||D.find((P)=>String(P.name||"").includes("2080")),V=n.images?.mlImage||n.health?.image||{},Y=mZ(n.queue),p=PZ(n.projects),O=RZ(p),m=$.sourceProject||p[0]?.projectPath||"",X=Y.filter((P)=>["staged","queued","running"].includes(P.status)),v=Y.filter((P)=>P.status==="succeeded"),T=Y.filter((P)=>["failed","canceled"].includes(P.status)),S=Array.isArray(n.history?.jobs)?n.history.jobs.slice(0,120):[],k=[{id:"projects",label:"项目库",count:p.length},{id:"current",label:"当前队列",count:X.length||Number(E.staged||0)+Number(E.queued||0)+Number(E.running||0)},{id:"completed",label:"已完成",count:v.length||Number(E.succeeded||0)},{id:"failed",label:"失败诊断",count:T.length||Number(E.failed||0)+Number(E.canceled||0)},{id:"gpu",label:"GPU/镜像",count:D.length}];function I(P,e){if(P.length===0)return C(Y0,{title:e==="current"?"当前队列为空":"暂无记录",text:e==="current"?"从项目库选择或 fork project 后先加入待启动队列,再启动队列。":"终态任务会显示耗时、exit code 和失败诊断。"});return C("div",{className:"table-wrap met-job-table"},C("table",null,C("thead",null,C("tr",null,C("th",null,"状态"),C("th",null,"Project"),C("th",null,"Epoch"),C("th",null,"速度"),C("th",null,"ETA/耗时"),C("th",null,"GPU"),C("th",null,"Exit"),C("th",null,"更新时间"),C("th",null,"操作"))),C("tbody",null,P.map((uu)=>{let Wu=uu.progress||{},g=["staged","queued","running"].includes(uu.status),Qu=y.kind==="job"&&y.key===uu.id;return C("tr",{key:uu.id,className:`met-click-row ${Qu?"active":""}`,onClick:()=>W(uu),"data-testid":`met-job-row-${ot(uu.id)}`},C("td",null,C(R_,{status:uu.status},mQ(uu.status))),C("td",null,C("button",{type:"button",className:"met-inline-link",onClick:(Tu)=>{Tu.stopPropagation(),W(uu)}},uu.projectPath),C("code",null,uu.id)),C("td",null,C("span",null,`${Wu.currentEpoch??"--"} / ${Wu.epochTarget??uu.epochTarget??"--"}`),C("div",{className:"met-progress"},C("span",{style:{width:C_(Wu.progressPercent)}}))),C("td",null,C("strong",null,at(pQ(uu)))),C("td",null,uu.status==="succeeded"||uu.status==="failed"||uu.status==="canceled"?SQ(uu):uu.status==="running"?`ETA ${lA(CZ(uu))}`:"--"),C("td",null,uu.gpuName||"--"),C("td",null,uu.exitCode??"--"),C("td",null,Nu(uu.updatedAt)),C("td",null,g?C("button",{type:"button",className:"ghost-btn mini",onClick:(Tu)=>{Tu.stopPropagation(),N(uu)},disabled:n.actionBusy},"取消"):null,C(hi,{title:`MET Job ${uu.id}`,data:uu,onOpen:f,testId:`raw-met-job-${uu.id}`})))}))))}function b(){return C("div",{className:"met-queue-summary","data-testid":"met-current-summary"},C(R_,{status:"staged"},`待启动 ${E.staged??0}`),C(R_,{status:"queued"},`排队中 ${E.queued??0}`),C(R_,{status:"running"},`训练中 ${E.running??0}`),C("span",null,`最大并发 ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??$.maxConcurrency}`),C("span",null,`目标 GPU ${n.summary?.queue?.targetGpuName??n.queue?.queue?.targetGpuName??$.targetGpuName}`))}function o(P,e){let uu=$.expandedProjectDirs[P];return uu===void 0?e<2:Boolean(uu)}function s(P,e){let uu=o(P,e);c({expandedProjectDirs:{...$.expandedProjectDirs,[P]:!uu}})}function x(P){let e=8+Math.max(0,P.depth)*16;if(Boolean(P.project)){let g=P.project,Qu=Boolean($.selectedProjects[g.projectPath]),Tu=y.kind==="project"&&y.key===g.projectPath;return C("div",{key:P.path,className:`met-tree-row project ${Qu?"selected":""} ${Tu?"active":""}`,style:{paddingLeft:e},onClick:()=>q(g),"data-testid":`met-project-node-${ot(g.projectPath)}`},C("div",{className:"met-tree-name"},C("input",{type:"checkbox",checked:Qu,onClick:(Zu)=>Zu.stopPropagation(),onChange:(Zu)=>c({selectedProjects:{...$.selectedProjects,[g.projectPath]:Zu.target.checked}}),"data-testid":`met-project-checkbox-${ot(g.projectPath)}`}),C("button",{type:"button",className:"met-inline-link project-path",onClick:(Zu)=>{Zu.stopPropagation(),q(g)}},P.name)),C("span",null,g.useModel||"--"),C("span",null,g.epochTrain??"--"),C("span",null,C_(g.progress?.progressPercent)),C("span",null,at(g.progress?.epochPerHour)))}let Wu=o(P.path,P.depth);return C(h_.default.Fragment,{key:P.path},C("div",{className:"met-tree-row folder",style:{paddingLeft:e},"data-testid":`met-project-folder-${ot(P.path)}`},C("button",{type:"button",className:"met-tree-toggle",onClick:()=>s(P.path,P.depth),"aria-label":Wu?`折叠 ${P.path}`:`展开 ${P.path}`},Wu?"-":"+"),C("strong",null,P.name),C("span",{className:"met-tree-count"},`${P.count} projects`)),Wu?P.children.map((g)=>x(g)):null)}function fu(P){return C("div",{className:"met-detail-kv"},P.map((e)=>C("div",{key:e.label,className:"met-detail-kv-item"},C("span",null,e.label),C("strong",null,x_(e.value)),e.hint?C("small",null,e.hint):null)))}function $u(P,e){return C("div",{className:"met-detail-section"},C("h3",null,P),fu(e))}function tu(P){if(!Array.isArray(P)||P.length===0)return C(Y0,{title:"模型层未上报",text:"等待 data/model_info.json 或 compute_analysis.json 生成。"});return C("div",{className:"table-wrap met-layer-table"},C("table",null,C("thead",null,C("tr",null,C("th",null,"Layer"),C("th",null,"Type"),C("th",null,"Params"),C("th",null,"Trainable"),C("th",null,"Compute"))),C("tbody",null,P.slice(0,18).map((e,uu)=>C("tr",{key:`${e.name||"layer"}-${uu}`},C("td",null,e.name||`#${uu+1}`),C("td",null,e.type||"--"),C("td",null,rA(e.num_params)),C("td",null,e.trainable===void 0?"--":String(Boolean(e.trainable))),C("td",null,rA(e.compute?.total??e.estimated_cost?.weighted_units?.total)))))))}function ju(P){let e=Array.isArray(P)?P:[];if(e.length===0)return C(Y0,{title:"data/ 暂无文件",text:"训练或评估完成后会生成 training_state、metrics、model_info 等文件。"});return C("div",{className:"met-file-chip-grid"},e.slice(0,48).map((uu)=>C("span",{key:uu},uu)),e.length>48?C("span",null,`+${e.length-48}`):null)}function Gu(P){let e=String(P||"").replace(/\x1b\[[0-9;]*[A-Za-z]/g,"").split(/\r?\n/).map((uu)=>uu.trim()).filter(Boolean).slice(-12);if(e.length===0)return C(Y0,{title:"暂无日志尾部",text:"该任务未上报 logTail 或日志已轮转。"});return C("div",{className:"met-log-lines"},e.map((uu,Wu)=>C("div",{key:`${Wu}-${uu.slice(0,16)}`},uu)))}function qu(){if(y.loading)return C("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},C("div",{className:"panel-head compact"},C("div",null,C("p",{className:"panel-eyebrow"},"Detail Loading"),C(nf,{title:"详情加载中",loading:!0}))),C(Y0,{title:"详情加载中",text:y.title||"正在读取 D601 data/ 和 config.json"}));if(y.error)return C("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},C(yf,{error:y.error,wide:!0}));if(!y.data)return C("section",{className:"met-detail-panel muted","data-testid":"met-detail-panel"},C(Y0,{title:"选择一个项目或任务查看详情",text:"项目库、当前队列、已完成和失败诊断中的行都可以点击;默认只展示结构化字段,原始 JSON 需显式点击按钮。"}));let P=xZ(y),e=hZ(y),uu=vl(P.config),Wu=vl(P.progress||e.progress),g=vl(P.data),Qu=vl(P.metrics||g.metrics||Wu.trainingInfo?.evaluation_metrics),Tu=vl(g.trainingInfo||Wu.trainingInfo),Zu=vl(g.trainingState),Xu=vl(P.model||g.model),uf=Array.isArray(Xu.modelSummary)&&Xu.modelSummary.length>0?Xu.modelSummary:Xu.computeLayers,_f=vl(Tu.evaluation_metrics),Jf=y.kind==="job"?"训练任务详情":"Project 详情";return C("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},C("div",{className:"panel-head compact"},C("div",null,C("p",{className:"panel-eyebrow"},y.kind==="job"?"Job + Project Detail":"Project Library Detail"),C(nf,{title:Jf}),C("code",null,P.projectPath||e.projectPath||y.title)),C("div",{className:"panel-actions"},C(hi,{title:`MET ${Jf}`,data:y.data,onOpen:f,testId:"raw-met-detail"}))),y.kind==="job"?$u("任务状态",[{label:"Job ID",value:e.id},{label:"状态",value:mQ(e.status)},{label:"GPU",value:e.gpuName},{label:"Exit Code",value:e.exitCode},{label:"耗时",value:SQ(e)},{label:"训练速度",value:at(pQ({...e,progress:Wu}))}]):null,$u("config.json",[{label:"use_model",value:uu.use_model},{label:"epoch_train",value:uu.epoch_train},{label:"step_per_epoch",value:uu.step_per_epoch},{label:"learning_rate",value:uu.learning_rate},{label:"using_gpu",value:uu.using_gpu},{label:"use_points",value:uu.use_points},{label:"sample_rate",value:uu.sample_rate},{label:"time_clipped_s",value:uu.time_clipped_s},{label:"H_UNITS",value:uu.H_UNITS},{label:"INNER_KAN_UNITS",value:uu.INNER_KAN_UNITS},{label:"INNER_KAN_LAYERS",value:uu.INNER_KAN_LAYERS},{label:"GRID_SIZE",value:uu.GRID_SIZE},{label:"SPLINE_ORDER",value:uu.SPLINE_ORDER},{label:"USE_FAST_MODEL",value:uu.USE_FAST_MODEL},{label:"IIR_TRAINABLE",value:uu.IIR_TRAINABLE}]),$u("data/ 训练状态",[{label:"Epoch",value:`${Wu.currentEpoch??Zu.current_epoch??Zu.completed_epoch??"--"} / ${Wu.epochTarget??uu.epoch_train??"--"}`},{label:"Progress",value:C_(Wu.progressPercent)},{label:"Last Loss",value:Wu.lastLoss??Zu.loss},{label:"Last Val Loss",value:Wu.lastValLoss??Zu.val_loss},{label:"Min Loss",value:Tu.min_loss??Zu.min_loss},{label:"Min Val Loss",value:Tu.min_val_loss??Zu.min_val_loss},{label:"Log Lines",value:Wu.logLineCount},{label:"ETA",value:lA(Wu.etaSeconds??Zu.remaining_time)},{label:"训练速度",value:at(Wu.epochPerHour??Zu.smoothed_speed)},{label:"Training Alive",value:Zu.training_alive}]),$u("模型参数",[{label:"Model Type",value:Xu.modelType??uu.use_model},{label:"Total Params",value:Xu.totalParams,hint:Xu.totalParams===null||Xu.totalParams===void 0?"未上报":"data/model_info.json"},{label:"Trainable",value:Xu.trainableParams},{label:"Non-trainable",value:Xu.nonTrainableParams},{label:"Compute Cost",value:Xu.computeCost},{label:"Estimate Status",value:Xu.estimateStatus},{label:"Unsupported Layers",value:Xu.unsupportedLayerCount}]),$u("指标",[{label:"train_loss",value:Qu.train_loss??_f.train_loss},{label:"val_loss",value:Qu.val_loss??_f.val_loss},{label:"train_mae",value:Qu.train_mae??_f.train_mae},{label:"val_mae",value:Qu.val_mae??_f.val_mae},{label:"train_afmae",value:Qu.train_afmae??_f.train_afmae},{label:"val_afmae",value:Qu.val_afmae??_f.val_afmae},{label:"freq_drift_hz",value:Qu.freq_drift_hz},{label:"sens_drift_percent",value:Qu.sens_drift_percent},{label:"linearity_percent",value:Qu.linearity_percent},{label:"weights_source",value:Qu.weights_source??_f.weights_source},{label:"lr min/mean/max",value:`${x_(Tu.learning_rate_min)} / ${x_(Tu.learning_rate_mean)} / ${x_(Tu.learning_rate_max)}`}]),C("div",{className:"met-detail-section"},C("h3",null,"模型层"),tu(uf)),C("div",{className:"met-detail-section"},C("h3",null,"data/ 文件"),ju(g.files)),y.kind==="job"?C("div",{className:"met-detail-section"},C("h3",null,"日志尾部"),Gu(vl(y.data).logTail)):null)}return C("div",{className:"met-page","data-testid":"met-nonlinear-page"},C(fA,{title:"MET Nonlinear 训练编排",eyebrow:"D601 GPU 用户服务",loading:n.loading||n.actionBusy,actions:C("div",{className:"panel-actions"},C("button",{type:"button",className:"ghost-btn",onClick:j,disabled:n.loading,"data-testid":"met-refresh-button"},n.loading?"刷新中":"刷新"),C(hi,{title:"MET Nonlinear 用户服务",data:r,onOpen:f,testId:"raw-met-service"}))},C("div",{className:"findjob-hero"},C("div",null,C("div",{className:"node-version-line"},C(R_,{status:z.providerStatus==="online"?"online":"warn"},z.providerStatus||"unknown"),C("span",null,r.providerId),C("span",null,H.public?"公网暴露":"仅 UniDesk frontend 代理访问")),C("p",{className:"muted paragraph"},r.description)),C("div",{className:"microservice-ref-card"},C("span",null,"Repo"),C("strong",null,Z.url||"--"),C("code",null,Z.commitId||"--")),C("div",{className:"microservice-ref-card"},C("span",null,"D601 Docker"),C("strong",null,`${H.nodeBindHost||"--"}:${H.nodePort||"--"}`),C("code",null,`${Z.composeFile||"--"} / ${Z.containerName||"--"}`))),C(yf,{error:n.error,wide:!0}),$.actionMessage?C("div",{className:"met-action-log","data-testid":"met-action-message"},$.actionMessage):null),C("div",{className:"met-grid"},C(fA,{title:"核心状态",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Queue + GPU",loading:n.loading},C("div",{className:"metric-grid"},C(Tn,{label:"Staged",value:E.staged??0,hint:"加入队列未开始",tone:Number(E.staged||0)>0?"warn":""}),C(Tn,{label:"Queued",value:E.queued??0,hint:"排队等待调度",tone:Number(E.queued||0)>0?"warn":""}),C(Tn,{label:"Running",value:E.running??0,hint:`max ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??"--"}`,tone:Number(E.running||0)>0?"ok":""}),C(Tn,{label:"Succeeded",value:E.succeeded??0,hint:"已完成"}),C(Tn,{label:"Failed",value:E.failed??0,hint:"需要诊断",tone:Number(E.failed||0)>0?"warn":""}),C(Tn,{label:"2080Ti Free",value:h?C_(Number(h.freeRatio)*100):"--",hint:h?`${h.memoryFreeMiB}/${h.memoryTotalMiB} MiB`:"等待 GPU 上报"}),C(Tn,{label:"ML Image",value:V.present?"READY":"MISSING",hint:V.image||"met-nonlinear-ml:tf26",tone:V.present?"ok":"warn"}),C(Tn,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /health"}))),C(fA,{title:"队列控制",eyebrow:"Downloader-like staging",loading:n.actionBusy},C("div",{className:"met-control-strip"},C("label",null,"最大并发",C("input",{type:"number",min:1,max:16,value:$.maxConcurrency,"data-testid":"met-max-concurrency-input",onChange:(P)=>c({maxConcurrency:P.target.value})})),C("label",null,"目标 GPU",C("input",{value:$.targetGpuName,"data-testid":"met-target-gpu-input",onChange:(P)=>c({targetGpuName:P.target.value})})),C("button",{type:"button",className:"ghost-btn",onClick:U,disabled:n.actionBusy,"data-testid":"met-save-settings-button"},"保存设置"),C("button",{type:"button",className:"primary-btn",onClick:J,disabled:n.actionBusy||Number(E.staged||0)===0,"data-testid":"met-start-queue-button"},"启动队列")),C("p",{className:"muted paragraph"},"Project 先进入待启动队列,不会立即训练;点击启动队列后才切换为排队中,并由 D601 scheduler 按最大并发和 2080Ti 显存策略调度。")),C("section",{className:"panel met-workspace"},C("div",{className:"met-tabs",role:"tablist"},k.map((P)=>C("button",{key:P.id,type:"button",className:$.activeTab===P.id?"active":"",onClick:()=>c({activeTab:P.id}),"data-testid":`met-tab-${P.id}`},`${P.label} ${P.count}`))),C("div",{className:"panel-body"},$.activeTab==="projects"?C("div",{className:"met-form-grid","data-testid":"met-projects-pane"},C("div",{className:"met-fork-card"},C("h3",null,"Fork Project"),C("label",null,"源 Project",C("select",{value:m,"data-testid":"met-source-project-select",onChange:(P)=>c({sourceProject:P.target.value})},p.map((P)=>C("option",{key:P.projectPath,value:P.projectPath},`${P.projectPath} · ${P.useModel||"model?"}`)))),C("label",null,"Fork 数量",C("input",{type:"number",min:1,max:100,value:$.forkCount,"data-testid":"met-fork-count-input",onChange:(P)=>c({forkCount:P.target.value})})),C("label",null,"训练轮数",C("input",{type:"number",min:1,max:1e5,value:$.forkEpochs,"data-testid":"met-fork-epochs-input",onChange:(P)=>c({forkEpochs:P.target.value})})),C("label",null,"目标前缀",C("input",{value:$.forkPrefix,"data-testid":"met-fork-prefix-input",onChange:(P)=>c({forkPrefix:P.target.value})})),C("button",{type:"button",className:"primary-btn",onClick:w,disabled:n.actionBusy||!m,"data-testid":"met-fork-button"},"Fork Project"),C("p",{className:"muted paragraph"},"Fork 只创建新 Project 并自动勾选,不会直接训练;需要在右侧确认后加入待启动队列。")),C("div",{className:"met-project-list"},C("div",{className:"panel-head compact"},C("div",null,C("p",{className:"panel-eyebrow"},`Existing Projects · ${(n.projects?.roots||[]).map((P)=>`${P.root} ${P.count}`).join(" / ")}`),C(nf,{title:"选择已有 Project",loading:n.loading||n.actionBusy})),C("button",{type:"button",className:"ghost-btn",onClick:L,disabled:n.actionBusy||Q().length===0,"data-testid":"met-stage-selected-button"},`加入待启动队列 (${Q().length})`)),p.length===0?C(Y0,{title:"暂无 project",text:"等待 D601 返回 /api/projects"}):C("div",{className:"met-project-table","data-testid":"met-project-tree"},C("div",{className:"met-tree-header"},C("span",null,"文件树 Project"),C("span",null,"Model"),C("span",null,"Epochs"),C("span",null,"Progress"),C("span",null,"速度")),O.children.map((P)=>x(P)))),qu()):null,$.activeTab==="current"?C("div",{"data-testid":"met-current-pane"},b(),I(X,"current"),qu(),C("div",{className:"panel-actions inline-actions"},C(hi,{title:"MET Queue",data:n.queue,onOpen:f,testId:"raw-met-queue"}))):null,$.activeTab==="completed"?C("div",{"data-testid":"met-completed-pane"},I(v.length>0?v:S.filter((P)=>P.status==="succeeded"),"completed"),qu()):null,$.activeTab==="failed"?C("div",{"data-testid":"met-failed-pane"},I(T.length>0?T:S.filter((P)=>["failed","canceled"].includes(P.status)),"failed"),qu(),C("div",{className:"panel-actions inline-actions"},C(hi,{title:"MET History",data:n.history,onOpen:f,testId:"raw-met-history"}))):null,$.activeTab==="gpu"?C("div",{className:"met-gpu-pane","data-testid":"met-gpu-pane"},D.length===0?C(Y0,{title:"暂无 GPU 上报",text:"等待 D601 met-nonlinear-ts 或 ML image 提供 nvidia-smi 数据"}):C("div",{className:"table-wrap"},C("table",null,C("thead",null,C("tr",null,C("th",null,"Index"),C("th",null,"Name"),C("th",null,"Free"),C("th",null,"Policy"))),C("tbody",null,D.map((P)=>C("tr",{key:P.index},C("td",null,P.index),C("td",null,P.name),C("td",null,`${P.memoryFreeMiB} / ${P.memoryTotalMiB} MiB`,C("div",{className:"met-progress"},C("span",{style:{width:C_(Number(P.freeRatio)*100)}}))),C("td",null,String(P.name||"").includes("2080")?"target 2080Ti, <20% 限制并发":"non-target")))))),C("div",{className:"panel-actions inline-actions"},C(hi,{title:"MET Images",data:n.images,onOpen:f,testId:"raw-met-images"}))):null))))}var u6=[{id:"ops",label:"运行总览",code:"OPS",tabs:[{id:"status",label:"态势总览"},{id:"performance",label:"性能面板"},{id:"events",label:"事件摘要"},{id:"logs",label:"服务日志"}]},{id:"nodes",label:"资源节点",code:"NODE",tabs:[{id:"list",label:"节点清单"},{id:"monitor",label:"资源监控"},{id:"docker",label:"Docker 状态"},{id:"gateway",label:"网关版本"},{id:"labels",label:"资源标签"},{id:"heartbeats",label:"心跳状态"}]},{id:"tasks",label:"任务调度",code:"TASK",tabs:[{id:"dispatch",label:"下发任务"},{id:"scheduled",label:"定时任务"},{id:"pending",label:"待处理任务"},{id:"history",label:"任务历史"},{id:"results",label:"执行结果"}]},{id:"apps",label:"用户服务",code:"APP",routeSegment:"app",tabs:[{id:"catalog",label:"服务目录"},{id:"todo-note",label:"Todo Note"},{id:"findjob",label:"FindJob"},{id:"pipeline",label:"Pipeline"},{id:"met-nonlinear",label:"MET Nonlinear"},{id:"claudeqq",label:"ClaudeQQ"},{id:"baidu-netdisk",label:"Baidu Netdisk"},{id:"filebrowser",label:"File Browser"},{id:"oa-event-flow",label:"OA Event Flow"},{id:"code-queue",label:"Code Queue"},{id:"project-manager",label:"Project Manager"}]},{id:"config",label:"系统配置",code:"CFG",tabs:[{id:"topology",label:"连接拓扑"},{id:"auth",label:"认证策略"},{id:"security",label:"安全边界"}]}],b_=Object.fromEntries(u6.map((u)=>[u.id,u.tabs[0]?.id??""]));function bZ(u){let f=String(u||"").trim();if(!f)return"";try{return decodeURIComponent(f)}catch{return f}}function et(u){let f=String(u||"/"),[l]=f.split(/[?#]/u,1);if(l==="/")return"/";let n=`/${l.split("/").map(bZ).filter(Boolean).join("/")}`;return n.endsWith("/")?n:`${n}/`}function vZ(u){let f=2166136261;for(let l of u)f^=l.charCodeAt(0),f=Math.imul(f,16777619);return Math.abs(f>>>0).toString(36)}function nA(u){return String(u||"").normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"")}function CQ(u){return String(u||"").trim().toLowerCase().replace(/[\s/\\?#%]+/gu,"-").replace(/-+/gu,"-").replace(/^-+|-+$/gu,"")}function RQ(u){let f=nA(u.routeSegment||"")||CQ(u.routeSegment||"");if(f)return f;let l=nA(u.id||"");if(l)return l;let r=nA(u.label||"")||CQ(u.label||"");if(r)return r;return`route-${vZ(JSON.stringify(u))}`}function iA(u,f){return`${u}:${f}`}function xQ(u){let f=u.map(($)=>{let A=RQ($);return{...$,routeSegment:A,tabs:$.tabs.map((c)=>({...c,routeSegment:RQ(c)}))}}),l={},r={},n={},i=f.map(($)=>{let A=$.tabs[0]?.id??"";n[$.id]=A;let c=$.tabs.map((U)=>{let Q=`/${$.routeSegment}/${U.routeSegment}/`,L=[Q],w={moduleId:$.id,tabId:U.id};for(let J of L)l[et(J)]=w;return r[iA($.id,U.id)]=Q,{...U,canonicalPath:Q,aliases:L}}),j=`/${$.routeSegment}/`,F={moduleId:$.id,tabId:A};return l[et(j)]=F,{...$,routeSegment:$.routeSegment,canonicalPath:j,tabs:c}}),y=i[0],_={moduleId:y?.id||"",tabId:y?.tabs[0]?.id||""};return l["/"]=_,{modules:i,moduleById:Object.fromEntries(i.map(($)=>[$.id,$])),defaultActiveTabs:n,routeMap:l,canonicalPathByTarget:r,fallbackTarget:_}}function yA(u,f){return u.routeMap[et(f)]||u.fallbackTarget}function f6(u,f,l){return u.canonicalPathByTarget[iA(f,l)]||u.canonicalPathByTarget[iA(u.fallbackTarget.moduleId,u.fallbackTarget.tabId)]||"/"}function hQ(u,f){let l=u.routeMap[et(f)];if(!l)return null;return f6(u,l.moduleId,l.tabId)}var i6=Pu(qf(),1);var iu=i6.default.createElement,{useEffect:bQ,useMemo:kZ}=i6.default,_A=i6.default.useState;function n6({status:u,children:f,title:l}){let r=String(u||"unknown").toLowerCase();return iu("span",{className:`status-badge ${r}`,title:l},f||u||"unknown")}function v_({label:u,value:f,hint:l,tone:r}){return iu("article",{className:`metric-card ${r||""}`},iu("div",{className:"metric-label"},u),iu("div",{className:"metric-value"},f),iu("div",{className:"metric-hint"},l))}function l6({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return iu("section",{className:`panel ${n||""}`},iu("div",{className:"panel-head"},iu("div",null,f?iu("p",{className:"panel-eyebrow"},f):null,iu(nf,{title:u,loading:i})),l?iu("div",{className:"panel-actions"},l):null),iu("div",{className:"panel-body"},r))}function k_({title:u,data:f,onOpen:l,testId:r}){return iu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l?.(u,f)},"查看原始JSON")}function $A({title:u,text:f}){return iu("div",{className:"empty-state"},iu("strong",null,u),iu("span",null,f))}function IZ(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function S0(u){return Array.isArray(u)?u:[]}function kl(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}function vQ(u,f=140){if(u===null||u===void 0)return"--";let l=typeof u==="string"?u:JSON.stringify(u),r=String(l||"").replace(/\s+/gu," ").trim();return r.length>f?`${r.slice(0,f-1)}...`:r||"--"}function gZ(u){return S0(u?.tags).map((f)=>String(f||"").trim()).filter(Boolean)}function G1(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):0}function sZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function aZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function oZ(u){return String(u||"").split(/[\s,]+/u).map((f)=>f.trim()).filter(Boolean).join(",")}function r6(u,f){return`${u}/microservices/oa-event-flow/proxy${f}`}function dZ(u){if(u.includes("error")||u.includes("failed"))return"failed";if(u.includes("stats"))return"ok";if(u.includes("step")||u.includes("updated"))return"running";return"queued"}function eZ(u){let f=String(u?.subjectKind||"trace"),l=String(u?.subjectId||u?.scopeId||"");return l?`${f}:${l}`:String(u?.scopeId||"--")}function uO({tags:u}){let f=gZ({tags:u}).slice(0,6);return iu("div",{className:"oa-tag-rail"},f.length===0?iu("span",{className:"muted"},"--"):f.map((l)=>iu("code",{key:l},l)))}function fO({events:u,onRaw:f}){let l=[...S0(u)].reverse();return l.length===0?iu($A,{title:"事件表暂无记录",text:"等待 Code Queue 或 Pipeline 按 tag 发布 OA 事件"}):iu("div",{className:"table-wrap oa-event-table-wrap"},iu("table",{className:"oa-event-table","data-testid":"oa-event-flow-event-table"},iu("thead",null,iu("tr",null,iu("th",null,"Seq"),iu("th",null,"Type"),iu("th",null,"Source"),iu("th",null,"Aggregate"),iu("th",null,"Tags"),iu("th",null,"Payload"),iu("th",null,"Created"),iu("th",null,"Raw"))),iu("tbody",null,l.map((r)=>{let n=String(r?.type||"event"),i=`${String(r?.aggregateType||"--")}:${String(r?.aggregateId||"--")}`;return iu("tr",{key:r?.eventId||r?.sequence},iu("td",null,iu("code",null,kl(r?.sequence))),iu("td",null,iu(n6,{status:dZ(n)},n)),iu("td",null,iu("strong",null,r?.sourceId||"--"),iu("code",null,r?.sourceKind||"--")),iu("td",null,iu("code",null,i)),iu("td",null,iu(uO,{tags:r?.tags})),iu("td",null,iu("span",{className:"oa-payload-preview"},vQ(r?.payload,180))),iu("td",null,Nu(r?.createdAt)),iu("td",null,iu(k_,{title:`OA Event ${r?.sequence||""}`,data:r,onOpen:f,testId:`raw-oa-event-${r?.sequence||"unknown"}`})))}))))}function lO({stats:u,onRaw:f}){let l=S0(u);return l.length===0?iu($A,{title:"统计中心暂无投影",text:"trace-stats-snapshot / trace-step-created 进入事件流后会更新这里"}):iu("div",{className:"table-wrap oa-stats-table-wrap"},iu("table",{className:"oa-stats-table","data-testid":"oa-event-flow-stats"},iu("thead",null,iu("tr",null,iu("th",null,"Scope"),iu("th",null,"Service"),iu("th",null,"STEP"),iu("th",null,"Read"),iu("th",null,"Edit"),iu("th",null,"Run"),iu("th",null,"Error"),iu("th",null,"Output Seq"),iu("th",null,"Revision"),iu("th",null,"Updated"),iu("th",null,"Raw"))),iu("tbody",null,l.map((r)=>iu("tr",{key:r?.scopeId||`${r?.serviceId}-${r?.subjectId}`},iu("td",null,iu("strong",null,eZ(r)),iu("code",null,r?.scopeId||"--")),iu("td",null,iu(n6,{status:String(r?.serviceId||"unknown")==="code-queue"?"running":"queued"},r?.serviceId||"--")),iu("td",null,iu("strong",null,kl(G1(r?.stepCount??r?.llmStepCount)))),iu("td",null,kl(G1(r?.readCount))),iu("td",null,kl(G1(r?.editCount))),iu("td",null,kl(G1(r?.runCount))),iu("td",null,kl(G1(r?.errorCount))),iu("td",null,iu("code",null,kl(G1(r?.outputMaxSeq)))),iu("td",null,kl(G1(r?.statsRevision))),iu("td",null,Nu(r?.updatedAt)),iu("td",null,iu(k_,{title:`OA Trace Stats ${r?.scopeId||""}`,data:r,onOpen:f,testId:`raw-oa-stats-${String(r?.scopeId||"unknown").replace(/[^a-zA-Z0-9_-]/gu,"_")}`})))))))}function kQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((z)=>z.id==="oa-event-flow")||null,[n,i]=_A("service:code-queue"),[y,_]=_A({loading:!1,error:"",health:null,diagnostics:null,events:[],stats:[],refreshedAt:null}),[$,A]=_A({status:"idle",message:"未连接",lastEventAt:""}),c=kZ(()=>oZ(n),[n]);async function j(){if(!r)return;_((z)=>({...z,loading:!0,error:""}));try{let z=c?`tags=${encodeURIComponent(c)}&`:"",[Z,H,E,D]=await Promise.all([Eu(`${l}/microservices/oa-event-flow/health`,{failureFields:[]}),Eu(r6(l,"/api/diagnostics")),Eu(r6(l,`/api/events?${z}limit=100`)),Eu(r6(l,`/api/stats/trace?${z}limit=100`))]);_({loading:!1,error:"",health:Z,diagnostics:H,events:S0(E?.events),stats:S0(D?.stats),refreshedAt:new Date})}catch(z){_((Z)=>({...Z,loading:!1,error:Hu(z,"OA Event Flow 加载失败")}))}}if(bQ(()=>{j()},[r?.id,r?.runtime?.providerStatus,c]),bQ(()=>{if(!r||typeof EventSource>"u")return;let z=c?`?tags=${encodeURIComponent(c)}`:"",Z=new EventSource(`${r6(l,"/api/events/stream")}${z}`,{withCredentials:!0});A({status:"running",message:"SSE connecting",lastEventAt:""});let H=(h)=>{A({status:"online",message:vQ(h.data,120),lastEventAt:new Date().toISOString()})},E=(h)=>{try{let V=JSON.parse(String(h.data||"{}"));A({status:"online",message:String(V?.type||h.type||"event"),lastEventAt:new Date().toISOString()}),_((Y)=>{let p=[...S0(Y.events).filter((m)=>String(m?.eventId||"")!==String(V?.eventId||"")),V].sort((m,X)=>Number(m?.sequence||0)-Number(X?.sequence||0)).slice(-100),O=V?.type==="trace-stats-updated"&&IZ(V?.payload?.stats)?[V.payload.stats,...S0(Y.stats).filter((m)=>String(m?.scopeId||"")!==String(V.payload.stats.scopeId||""))].slice(0,100):Y.stats;return{...Y,events:p,stats:O}})}catch(V){A({status:"warn",message:Hu(V,"SSE 事件解析失败"),lastEventAt:new Date().toISOString()})}},D=()=>{A((h)=>({...h,status:"warn",message:"SSE reconnecting"}))};return Z.addEventListener("hello",H),Z.addEventListener("task-updated",E),Z.addEventListener("queue-updated",E),Z.addEventListener("trace-step-created",E),Z.addEventListener("trace-stats-snapshot",E),Z.addEventListener("trace-stats-updated",E),Z.addEventListener("trace-error",E),Z.onerror=D,()=>Z.close()},[r?.id,l,c]),!r)return iu($A,{title:"OA Event Flow 未登记",text:"请在 config.json 的 microservices 中登记 id=oa-event-flow"});let F=sZ(r),U=aZ(r),Q=y.diagnostics||{},L=y.health||{},w=Q.eventCount??L.eventCount,J=Q.traceStatsCount??L.traceStatsCount,N=Q.latestSequence??L.latestSequence,q=Q.pipelineBridge||L.pipelineBridge||{},W=S0(Q.eventTypes).slice(0,8);return iu("div",{className:"oa-event-flow-page","data-testid":"oa-event-flow-page"},iu(l6,{title:"OA Event Flow 控制台",eyebrow:"Unified OA Event Bus + Stats Projection",loading:y.loading,actions:iu("div",{className:"panel-actions"},iu("button",{type:"button",className:"ghost-btn",onClick:j,disabled:y.loading,"data-testid":"oa-event-flow-refresh"},y.loading?"刷新中":"刷新"),iu(k_,{title:"OA Event Flow Service",data:r,onOpen:f,testId:"raw-oa-event-flow-service"}))},iu("div",{className:"oa-flow-hero"},iu("div",null,iu("div",{className:"node-version-line"},iu(n6,{status:L?.ok||F.providerStatus==="online"?"online":"warn"},L?.ok?"HEALTH OK":F.providerStatus||"unknown"),iu(n6,{status:$.status},$.status.toUpperCase()),iu("span",null,U.public?"公网暴露":"仅 UniDesk frontend 代理访问")),iu("p",{className:"muted paragraph"},"独立事件流微服务统一承载 Code Queue 与 Pipeline 的事件发布、tag 订阅、事件表审计和 Trace/STEP 统计投影。")),iu("div",{className:"oa-flow-signal"},iu("span",null,"stream"),iu("strong",null,$.message||"--"),iu("code",null,$.lastEventAt?tf(new Date($.lastEventAt)):"waiting"))),iu(yf,{error:y.error,wide:!0})),iu("div",{className:"oa-flow-metrics"},iu(v_,{label:"事件总量",value:kl(w),hint:`latest seq ${kl(N)}`,tone:"ok"}),iu(v_,{label:"Trace Stats",value:kl(J),hint:"oa_trace_stats 投影"}),iu(v_,{label:"SSE Clients",value:kl(L?.sseClientCount??S0(Q.sseClients).length),hint:$.message||"tag subscription"}),iu(v_,{label:"Pipeline Bridge",value:q?.enabled?kl(q?.insertedCount):"OFF",hint:q?.lastError||q?.lastFinishedAt||`${q?.mode||"snapshot"} service:pipeline`}),iu(v_,{label:"DB",value:L?.databaseReady||Q.databaseReady?"READY":"WAIT",hint:L?.databaseLastError||Q.databaseLastError||"PostgreSQL persisted"})),iu(l6,{title:"标签订阅",eyebrow:y.refreshedAt?`Updated ${tf(y.refreshedAt)}`:"Tag Pub/Sub"},iu("div",{className:"oa-filter-bar"},iu("label",null,iu("span",null,"tags"),iu("input",{value:n,onChange:(z)=>i(z.target.value),placeholder:"service:code-queue, trace","data-testid":"oa-event-flow-tag-filter"})),iu("div",{className:"oa-filter-presets"},iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("service:code-queue")},"Code Queue"),iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("service:pipeline")},"Pipeline"),iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("trace")},"Trace"),iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("")},"All")),iu("code",null,c||"all events")),iu("div",{className:"oa-type-strip"},W.length===0?iu("span",{className:"muted"},"等待事件类型统计"):W.map((z)=>iu("span",{key:z.type,className:"data-chip"},`${z.type} ${kl(z.count)}`)))),iu("div",{className:"oa-flow-grid"},iu(l6,{title:"事件表",eyebrow:"oa_events persisted log",className:"oa-flow-wide",loading:y.loading,actions:iu(k_,{title:"OA Event Query",data:{events:y.events,diagnostics:Q},onOpen:f,testId:"raw-oa-events"})},iu(fO,{events:y.events,onRaw:f})),iu(l6,{title:"统计中心",eyebrow:"oa_trace_stats read model",className:"oa-flow-wide",loading:y.loading,actions:iu(k_,{title:"OA Trace Stats",data:y.stats,onOpen:f,testId:"raw-oa-trace-stats"})},iu(lO,{stats:y.stats,onRaw:f}))))}var Mn=Pu(qf(),1);var ru=Pu(aQ(),1),yu=Pu(qf(),1);function Yf(u){if(typeof u==="string"||typeof u==="number")return""+u;let f="";if(Array.isArray(u)){for(let l=0,r;l{}};function dQ(){for(var u=0,f=arguments.length,l={},r;u=0)r=l.slice(n+1),l=l.slice(0,n);if(l&&!f.hasOwnProperty(l))throw Error("unknown type: "+l);return{type:l,name:r}})}_6.prototype=dQ.prototype={constructor:_6,on:function(u,f){var l=this._,r=AO(u+"",l),n,i=-1,y=r.length;if(arguments.length<2){while(++i0)for(var l=Array(n),r=0,n,i;r=0&&(f=u.slice(0,l))!=="xmlns")u=u.slice(l+1);return tA.hasOwnProperty(f)?{space:tA[f],local:u}:u}function AA(u){let f;while(f=u.sourceEvent)u=f;return u}function Kl(u,f){if(u=AA(u),f===void 0)f=u.currentTarget;if(f){var l=f.ownerSVGElement||f;if(l.createSVGPoint){var r=l.createSVGPoint();return r.x=u.clientX,r.y=u.clientY,r=r.matrixTransform(f.getScreenCTM().inverse()),[r.x,r.y]}if(f.getBoundingClientRect){var n=f.getBoundingClientRect();return[u.clientX-n.left-f.clientLeft,u.clientY-n.top-f.clientTop]}}return[u.pageX,u.pageY]}function jO(){}function En(u){return u==null?jO:function(){return this.querySelector(u)}}function cA(u){if(typeof u!=="function")u=En(u);for(var f=this._groups,l=f.length,r=Array(l),n=0;n=q)q=N+1;while(!(z=w[q])&&++q=0;)if(y=r[n]){if(i&&y.compareDocumentPosition(i)^4)i.parentNode.insertBefore(y,i);i=y}return this}function zA(u){if(!u)u=TO;function f(j,F){return j&&F?u(j.__data__,F.__data__):!j-!F}for(var l=this._groups,r=l.length,n=Array(r),i=0;if?1:u>=f?0:NaN}function TA(){var u=arguments[0];return arguments[0]=this,u.apply(null,arguments),this}function EA(){return Array.from(this)}function ZA(){for(var u=this._groups,f=0,l=u.length;f1?this.each((f==null?DO:typeof f==="function"?YO:XO)(u,f,l==null?"":l)):Zn(this.node(),u)}function Zn(u,f){return u.style.getPropertyValue(f)||s_(u).getComputedStyle(u,null).getPropertyValue(f)}function SO(u){return function(){delete this[u]}}function pO(u,f){return function(){this[u]=f}}function mO(u,f){return function(){var l=f.apply(this,arguments);if(l==null)delete this[u];else this[u]=l}}function XA(u,f){return arguments.length>1?this.each((f==null?SO:typeof f==="function"?mO:pO)(u,f)):this.node()[u]}function eQ(u){return u.trim().split(/^|\s+/)}function YA(u){return u.classList||new uq(u)}function uq(u){this._node=u,this._names=eQ(u.getAttribute("class")||"")}uq.prototype={add:function(u){var f=this._names.indexOf(u);if(f<0)this._names.push(u),this._node.setAttribute("class",this._names.join(" "))},remove:function(u){var f=this._names.indexOf(u);if(f>=0)this._names.splice(f,1),this._node.setAttribute("class",this._names.join(" "))},contains:function(u){return this._names.indexOf(u)>=0}};function fq(u,f){var l=YA(u),r=-1,n=f.length;while(++r=0)l=f.slice(r+1),f=f.slice(0,r);return{type:f,name:l}})}function rH(u){return function(){var f=this.__on;if(!f)return;for(var l=0,r=-1,n=f.length,i;l()=>u;function e_(u,{sourceEvent:f,subject:l,target:r,identifier:n,active:i,x:y,y:_,dx:$,dy:A,dispatch:c}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:f,enumerable:!0,configurable:!0},subject:{value:l,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:n,enumerable:!0,configurable:!0},active:{value:i,enumerable:!0,configurable:!0},x:{value:y,enumerable:!0,configurable:!0},y:{value:_,enumerable:!0,configurable:!0},dx:{value:$,enumerable:!0,configurable:!0},dy:{value:A,enumerable:!0,configurable:!0},_:{value:c}})}e_.prototype.on=function(){var u=this._.on.apply(this._,arguments);return u===this._?this:u};function UH(u){return!u.ctrlKey&&!u.button}function QH(){return this.parentNode}function qH(u,f){return f==null?{x:u.x,y:u.y}:f}function NH(){return navigator.maxTouchPoints||"ontouchstart"in this}function u$(){var u=UH,f=QH,l=qH,r=NH,n={},i=z1("start","drag","end"),y=0,_,$,A,c,j=0;function F(W){W.on("mousedown.drag",U).filter(r).on("touchstart.drag",w).on("touchmove.drag",J,iq).on("touchend.drag touchcancel.drag",N).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function U(W,z){if(c||!u.call(this,W,z))return;var Z=q(this,f.call(this,W,z),W,z,"mouse");if(!Z)return;af(W.view).on("mousemove.drag",Q,T1).on("mouseup.drag",L,T1),ki(W.view),A6(W),A=!1,_=W.clientX,$=W.clientY,Z("start",W)}function Q(W){if(m0(W),!A){var z=W.clientX-_,Z=W.clientY-$;A=z*z+Z*Z>j}n.mouse("drag",W)}function L(W){af(W.view).on("mousemove.drag mouseup.drag",null),o_(W.view,A),m0(W),n.mouse("end",W)}function w(W,z){if(!u.call(this,W,z))return;var Z=W.changedTouches,H=f.call(this,W,z),E=Z.length,D,h;for(D=0;D>8&15|f>>4&240,f>>4&15|f&240,(f&15)<<4|f&15,1):l===8?c6(f>>24&255,f>>16&255,f>>8&255,(f&255)/255):l===4?c6(f>>12&15|f>>8&240,f>>8&15|f>>4&240,f>>4&15|f&240,((f&15)<<4|f&15)/255):null):(f=LH.exec(u))?new Il(f[1],f[2],f[3],1):(f=wH.exec(u))?new Il(f[1]*255/100,f[2]*255/100,f[3]*255/100,1):(f=KH.exec(u))?c6(f[1],f[2],f[3],f[4]):(f=GH.exec(u))?c6(f[1]*255/100,f[2]*255/100,f[3]*255/100,f[4]):(f=zH.exec(u))?jq(f[1],f[2]/100,f[3]/100,1):(f=TH.exec(u))?jq(f[1],f[2]/100,f[3]/100,f[4]):yq.hasOwnProperty(u)?tq(yq[u]):u==="transparent"?new Il(NaN,NaN,NaN,0):null}function tq(u){return new Il(u>>16&255,u>>8&255,u&255,1)}function c6(u,f,l,r){if(r<=0)u=f=l=NaN;return new Il(u,f,l,r)}function OH(u){if(!(u instanceof n$))u=vr(u);if(!u)return new Il;return u=u.rgb(),new Il(u.r,u.g,u.b,u.opacity)}function gi(u,f,l,r){return arguments.length===1?OH(u):new Il(u,f,l,r==null?1:r)}function Il(u,f,l,r){this.r=+u,this.g=+f,this.b=+l,this.opacity=+r}f$(Il,gi,sA(n$,{brighter(u){return u=u==null?F6:Math.pow(F6,u),new Il(this.r*u,this.g*u,this.b*u,this.opacity)},darker(u){return u=u==null?l$:Math.pow(l$,u),new Il(this.r*u,this.g*u,this.b*u,this.opacity)},rgb(){return this},clamp(){return new Il(Z1(this.r),Z1(this.g),Z1(this.b),J6(this.opacity))},displayable(){return-0.5<=this.r&&this.r<255.5&&(-0.5<=this.g&&this.g<255.5)&&(-0.5<=this.b&&this.b<255.5)&&(0<=this.opacity&&this.opacity<=1)},hex:Aq,formatHex:Aq,formatHex8:HH,formatRgb:cq,toString:cq}));function Aq(){return`#${E1(this.r)}${E1(this.g)}${E1(this.b)}`}function HH(){return`#${E1(this.r)}${E1(this.g)}${E1(this.b)}${E1((isNaN(this.opacity)?1:this.opacity)*255)}`}function cq(){let u=J6(this.opacity);return`${u===1?"rgb(":"rgba("}${Z1(this.r)}, ${Z1(this.g)}, ${Z1(this.b)}${u===1?")":`, ${u})`}`}function J6(u){return isNaN(u)?1:Math.max(0,Math.min(1,u))}function Z1(u){return Math.max(0,Math.min(255,Math.round(u)||0))}function E1(u){return u=Z1(u),(u<16?"0":"")+u.toString(16)}function jq(u,f,l,r){if(r<=0)u=f=l=NaN;else if(l<=0||l>=1)u=f=NaN;else if(f<=0)u=NaN;return new br(u,f,l,r)}function Jq(u){if(u instanceof br)return new br(u.h,u.s,u.l,u.opacity);if(!(u instanceof n$))u=vr(u);if(!u)return new br;if(u instanceof br)return u;u=u.rgb();var f=u.r/255,l=u.g/255,r=u.b/255,n=Math.min(f,l,r),i=Math.max(f,l,r),y=NaN,_=i-n,$=(i+n)/2;if(_){if(f===i)y=(l-r)/_+(l0&&$<1?0:y;return new br(y,_,$,u.opacity)}function Uq(u,f,l,r){return arguments.length===1?Jq(u):new br(u,f,l,r==null?1:r)}function br(u,f,l,r){this.h=+u,this.s=+f,this.l=+l,this.opacity=+r}f$(br,Uq,sA(n$,{brighter(u){return u=u==null?F6:Math.pow(F6,u),new br(this.h,this.s,this.l*u,this.opacity)},darker(u){return u=u==null?l$:Math.pow(l$,u),new br(this.h,this.s,this.l*u,this.opacity)},rgb(){var u=this.h%360+(this.h<0)*360,f=isNaN(u)||isNaN(this.s)?0:this.s,l=this.l,r=l+(l<0.5?l:1-l)*f,n=2*l-r;return new Il(aA(u>=240?u-240:u+120,n,r),aA(u,n,r),aA(u<120?u+240:u-120,n,r),this.opacity)},clamp(){return new br(Fq(this.h),j6(this.s),j6(this.l),J6(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&(0<=this.l&&this.l<=1)&&(0<=this.opacity&&this.opacity<=1)},formatHsl(){let u=J6(this.opacity);return`${u===1?"hsl(":"hsla("}${Fq(this.h)}, ${j6(this.s)*100}%, ${j6(this.l)*100}%${u===1?")":`, ${u})`}`}}));function Fq(u){return u=(u||0)%360,u<0?u+360:u}function j6(u){return Math.max(0,Math.min(1,u||0))}function aA(u,f,l){return(u<60?f+(l-f)*u/60:u<180?l:u<240?f+(l-f)*(240-u)/60:f)*255}function oA(u,f,l,r,n){var i=u*u,y=i*u;return((1-3*u+3*i-y)*f+(4-6*i+3*y)*l+(1+3*u+3*i-3*y)*r+y*n)/6}function dA(u){var f=u.length-1;return function(l){var r=l<=0?l=0:l>=1?(l=1,f-1):Math.floor(l*f),n=u[r],i=u[r+1],y=r>0?u[r-1]:2*n-i,_=r()=>u;function VH(u,f){return function(l){return u+l*f}}function DH(u,f,l){return u=Math.pow(u,l),f=Math.pow(f,l)-u,l=1/l,function(r){return Math.pow(u+r*f,l)}}function Qq(u){return(u=+u)===1?Q6:function(f,l){return l-f?DH(f,l,u):i$(isNaN(f)?l:f)}}function Q6(u,f){var l=f-u;return l?VH(u,l):i$(isNaN(u)?f:u)}var O1=function u(f){var l=Qq(f);function r(n,i){var y=l((n=gi(n)).r,(i=gi(i)).r),_=l(n.g,i.g),$=l(n.b,i.b),A=Q6(n.opacity,i.opacity);return function(c){return n.r=y(c),n.g=_(c),n.b=$(c),n.opacity=A(c),n+""}}return r.gamma=u,r}(1);function qq(u){return function(f){var l=f.length,r=Array(l),n=Array(l),i=Array(l),y,_;for(y=0;yl)if(i=f.slice(l,i),_[y])_[y]+=i;else _[++y]=i;if((r=r[0])===(n=n[0]))if(_[y])_[y]+=n;else _[++y]=n;else _[++y]=null,$.push({i:y,x:Gl(r,n)});l=rc.lastIndex}if(l180)c+=360;else if(c-A>180)A+=360;F.push({i:j.push(n(j)+"rotate(",null,r)-2,x:Gl(A,c)})}else if(c)j.push(n(j)+"rotate("+c+r)}function _(A,c,j,F){if(A!==c)F.push({i:j.push(n(j)+"skewX(",null,r)-2,x:Gl(A,c)});else if(c)j.push(n(j)+"skewX("+c+r)}function $(A,c,j,F,U,Q){if(A!==j||c!==F){var L=U.push(n(U)+"scale(",null,",",null,")");Q.push({i:L-4,x:Gl(A,j)},{i:L-2,x:Gl(c,F)})}else if(j!==1||F!==1)U.push(n(U)+"scale("+j+","+F+")")}return function(A,c){var j=[],F=[];return A=u(A),c=u(c),i(A.translateX,A.translateY,c.translateX,c.translateY,j,F),y(A.rotate,c.rotate,j,F),_(A.skewX,c.skewX,j,F),$(A.scaleX,A.scaleY,c.scaleX,c.scaleY,j,F),A=c=null,function(U){var Q=-1,L=F.length,w;while(++Q=0)u._call.call(void 0,f);u=u._next}--ai}function Oq(){B1=(w6=t$.now())+K6,ai=_$=0;try{Vq()}finally{ai=0,uB(),B1=0}}function eH(){var u=t$.now(),f=u-w6;if(f>Hq)K6-=f,w6=u}function uB(){var u,f=L6,l,r=1/0;while(f)if(f._call){if(r>f._time)r=f._time;u=f,f=f._next}else l=f._next,f._next=null,f=u?u._next=l:L6=l;$$=u,_c(r)}function _c(u){if(ai)return;if(_$)_$=clearTimeout(_$);var f=u-B1;if(f>24){if(u<1/0)_$=setTimeout(Oq,u-t$.now()-K6);if(y$)y$=clearInterval(y$)}else{if(!y$)w6=t$.now(),y$=setInterval(eH,Hq);ai=1,Bq(Oq)}}function j$(u,f,l){var r=new A$;return f=f==null?0:+f,r.restart((n)=>{r.stop(),u(n+f)},f,l),r}var lB=z1("start","end","cancel","interrupt"),rB=[],Yq=0,Dq=1,T6=2,z6=3,Xq=4,E6=5,F$=6;function P0(u,f,l,r,n,i){var y=u.__transition;if(!y)u.__transition={};else if(l in y)return;nB(u,l,{name:f,index:r,group:n,on:lB,tween:rB,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:Yq})}function J$(u,f){var l=of(u,f);if(l.state>Yq)throw Error("too late; already scheduled");return l}function Fl(u,f){var l=of(u,f);if(l.state>z6)throw Error("too late; already running");return l}function of(u,f){var l=u.__transition;if(!l||!(l=l[f]))throw Error("transition not found");return l}function nB(u,f,l){var r=u.__transition,n;r[f]=l,l.timer=G6(i,0,l.time);function i(A){if(l.state=Dq,l.timer.restart(y,l.delay,l.time),l.delay<=A)y(A-l.delay)}function y(A){var c,j,F,U;if(l.state!==Dq)return $();for(c in r){if(U=r[c],U.name!==l.name)continue;if(U.state===z6)return j$(y);if(U.state===Xq)U.state=F$,U.timer.stop(),U.on.call("interrupt",u,u.__data__,U.index,U.group),delete r[c];else if(+cT6&&r.state=0)f=f.slice(0,l);return!f||f==="start"})}function zB(u,f,l){var r,n,i=GB(f)?J$:Fl;return function(){var y=i(this,u),_=y.on;if(_!==r)(n=(r=_).copy()).on(f,l);y.on=n}}function Nc(u,f){var l=this._id;return arguments.length<2?of(this.node(),l).on.on(u):this.each(zB(l,u,f))}function TB(u){return function(){var f=this.parentNode;for(var l in this.__transition)if(+l!==u)return;if(f)f.removeChild(this)}}function Wc(){return this.on("end.remove",TB(this._id))}function Lc(u){var f=this._name,l=this._id;if(typeof u!=="function")u=En(u);for(var r=this._groups,n=r.length,i=Array(n),y=0;y()=>u;function Bc(u,{sourceEvent:f,target:l,transform:r,dispatch:n}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:f,enumerable:!0,configurable:!0},target:{value:l,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:n}})}function kr(u,f,l){this.k=u,this.x=f,this.y=l}kr.prototype={constructor:kr,scale:function(u){return u===1?this:new kr(this.k*u,this.x,this.y)},translate:function(u,f){return u===0&f===0?this:new kr(this.k,this.x+this.k*u,this.y+this.k*f)},apply:function(u){return[u[0]*this.k+this.x,u[1]*this.k+this.y]},applyX:function(u){return u*this.k+this.x},applyY:function(u){return u*this.k+this.y},invert:function(u){return[(u[0]-this.x)/this.k,(u[1]-this.y)/this.k]},invertX:function(u){return(u-this.x)/this.k},invertY:function(u){return(u-this.y)/this.k},rescaleX:function(u){return u.copy().domain(u.range().map(this.invertX,this).map(u.invert,u))},rescaleY:function(u){return u.copy().domain(u.range().map(this.invertY,this).map(u.invert,u))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var V1=new kr(1,0,0);q$.prototype=kr.prototype;function q$(u){while(!u.__zoom)if(!(u=u.parentNode))return V1;return u.__zoom}function m6(u){u.stopImmediatePropagation()}function D1(u){u.preventDefault(),u.stopImmediatePropagation()}function RB(u){return(!u.ctrlKey||u.type==="wheel")&&!u.button}function xB(){var u=this;if(u instanceof SVGElement){if(u=u.ownerSVGElement||u,u.hasAttribute("viewBox"))return u=u.viewBox.baseVal,[[u.x,u.y],[u.x+u.width,u.y+u.height]];return[[0,0],[u.width.baseVal.value,u.height.baseVal.value]]}return[[0,0],[u.clientWidth,u.clientHeight]]}function mq(){return this.__zoom||V1}function hB(u){return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*(u.ctrlKey?10:1)}function bB(){return navigator.maxTouchPoints||"ontouchstart"in this}function vB(u,f,l){var r=u.invertX(f[0][0])-l[0][0],n=u.invertX(f[1][0])-l[1][0],i=u.invertY(f[0][1])-l[0][1],y=u.invertY(f[1][1])-l[1][1];return u.translate(n>r?(r+n)/2:Math.min(0,r)||Math.max(0,n),y>i?(i+y)/2:Math.min(0,i)||Math.max(0,y))}function N$(){var u=RB,f=xB,l=vB,r=hB,n=bB,i=[0,1/0],y=[[-1/0,-1/0],[1/0,1/0]],_=250,$=H1,A=z1("start","zoom","end"),c,j,F,U=500,Q=150,L=0,w=10;function J(O){O.property("__zoom",mq).on("wheel.zoom",E,{passive:!1}).on("mousedown.zoom",D).on("dblclick.zoom",h).filter(n).on("touchstart.zoom",V).on("touchmove.zoom",Y).on("touchend.zoom touchcancel.zoom",p).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}J.transform=function(O,m,X,v){var T=O.selection?O.selection():O;if(T.property("__zoom",mq),O!==T)z(O,m,X,v);else T.interrupt().each(function(){Z(this,arguments).event(v).start().zoom(null,typeof m==="function"?m.apply(this,arguments):m).end()})},J.scaleBy=function(O,m,X,v){J.scaleTo(O,function(){var T=this.__zoom.k,S=typeof m==="function"?m.apply(this,arguments):m;return T*S},X,v)},J.scaleTo=function(O,m,X,v){J.transform(O,function(){var T=f.apply(this,arguments),S=this.__zoom,k=X==null?W(T):typeof X==="function"?X.apply(this,arguments):X,I=S.invert(k),b=typeof m==="function"?m.apply(this,arguments):m;return l(q(N(S,b),k,I),T,y)},X,v)},J.translateBy=function(O,m,X,v){J.transform(O,function(){return l(this.__zoom.translate(typeof m==="function"?m.apply(this,arguments):m,typeof X==="function"?X.apply(this,arguments):X),f.apply(this,arguments),y)},null,v)},J.translateTo=function(O,m,X,v,T){J.transform(O,function(){var S=f.apply(this,arguments),k=this.__zoom,I=v==null?W(S):typeof v==="function"?v.apply(this,arguments):v;return l(V1.translate(I[0],I[1]).scale(k.k).translate(typeof m==="function"?-m.apply(this,arguments):-m,typeof X==="function"?-X.apply(this,arguments):-X),S,y)},v,T)};function N(O,m){return m=Math.max(i[0],Math.min(i[1],m)),m===O.k?O:new kr(m,O.x,O.y)}function q(O,m,X){var v=m[0]-X[0]*O.k,T=m[1]-X[1]*O.k;return v===O.x&&T===O.y?O:new kr(O.k,v,T)}function W(O){return[(+O[0][0]+ +O[1][0])/2,(+O[0][1]+ +O[1][1])/2]}function z(O,m,X,v){O.on("start.zoom",function(){Z(this,arguments).event(v).start()}).on("interrupt.zoom end.zoom",function(){Z(this,arguments).event(v).end()}).tween("zoom",function(){var T=this,S=arguments,k=Z(T,S).event(v),I=f.apply(T,S),b=X==null?W(I):typeof X==="function"?X.apply(T,S):X,o=Math.max(I[1][0]-I[0][0],I[1][1]-I[0][1]),s=T.__zoom,x=typeof m==="function"?m.apply(T,S):m,fu=$(s.invert(b).concat(o/s.k),x.invert(b).concat(o/x.k));return function($u){if($u===1)$u=x;else{var tu=fu($u),ju=o/tu[2];$u=new kr(ju,b[0]-tu[0]*ju,b[1]-tu[1]*ju)}k.zoom(null,$u)}})}function Z(O,m,X){return!X&&O.__zooming||new H(O,m)}function H(O,m){this.that=O,this.args=m,this.active=0,this.sourceEvent=null,this.extent=f.apply(O,m),this.taps=0}H.prototype={event:function(O){if(O)this.sourceEvent=O;return this},start:function(){if(++this.active===1)this.that.__zooming=this,this.emit("start");return this},zoom:function(O,m){if(this.mouse&&O!=="mouse")this.mouse[1]=m.invert(this.mouse[0]);if(this.touch0&&O!=="touch")this.touch0[1]=m.invert(this.touch0[0]);if(this.touch1&&O!=="touch")this.touch1[1]=m.invert(this.touch1[0]);return this.that.__zoom=m,this.emit("zoom"),this},end:function(){if(--this.active===0)delete this.that.__zooming,this.emit("end");return this},emit:function(O){var m=af(this.that).datum();A.call(O,this.that,new Bc(O,{sourceEvent:this.sourceEvent,target:J,type:O,transform:this.that.__zoom,dispatch:A}),m)}};function E(O,...m){if(!u.apply(this,arguments))return;var X=Z(this,m).event(O),v=this.__zoom,T=Math.max(i[0],Math.min(i[1],v.k*Math.pow(2,r.apply(this,arguments)))),S=Kl(O);if(X.wheel){if(X.mouse[0][0]!==S[0]||X.mouse[0][1]!==S[1])X.mouse[1]=v.invert(X.mouse[0]=S);clearTimeout(X.wheel)}else if(v.k===T)return;else X.mouse=[S,v.invert(S)],On(this),X.start();D1(O),X.wheel=setTimeout(k,Q),X.zoom("mouse",l(q(N(v,T),X.mouse[0],X.mouse[1]),X.extent,y));function k(){X.wheel=null,X.end()}}function D(O,...m){if(F||!u.apply(this,arguments))return;var X=O.currentTarget,v=Z(this,m,!0).event(O),T=af(O.view).on("mousemove.zoom",b,!0).on("mouseup.zoom",o,!0),S=Kl(O,X),k=O.clientX,I=O.clientY;ki(O.view),m6(O),v.mouse=[S,this.__zoom.invert(S)],On(this),v.start();function b(s){if(D1(s),!v.moved){var x=s.clientX-k,fu=s.clientY-I;v.moved=x*x+fu*fu>L}v.event(s).zoom("mouse",l(q(v.that.__zoom,v.mouse[0]=Kl(s,X),v.mouse[1]),v.extent,y))}function o(s){T.on("mousemove.zoom mouseup.zoom",null),o_(s.view,v.moved),D1(s),v.event(s).end()}}function h(O,...m){if(!u.apply(this,arguments))return;var X=this.__zoom,v=Kl(O.changedTouches?O.changedTouches[0]:O,this),T=X.invert(v),S=X.k*(O.shiftKey?0.5:2),k=l(q(N(X,S),v,T),f.apply(this,m),y);if(D1(O),_>0)af(this).transition().duration(_).call(z,k,v,O);else af(this).call(J.transform,k,v,O)}function V(O,...m){if(!u.apply(this,arguments))return;var X=O.touches,v=X.length,T=Z(this,m,O.changedTouches.length===v).event(O),S,k,I,b;m6(O);for(k=0;k"[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001",error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:(u)=>`Node type "${u}" not found. Using fallback type "default".`,error004:()=>"The React Flow parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:(u)=>`The old edge with id=${u} does not exist.`,error009:(u)=>`Marker type "${u}" doesn't exist.`,error008:(u,{id:f,sourceHandle:l,targetHandle:r})=>`Couldn't create edge for ${u} handle id: "${u==="source"?l:r}", edge id: ${f}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:(u)=>`Edge type "${u}" not found. Using fallback type "default".`,error012:(u)=>`Node with id "${u}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(u="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${u}/dist/style.css' or base.css to make sure everything is working properly.`,error014:()=>"useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.",error015:()=>"It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs."},ly=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],Sc=["Enter"," ","Escape"],pc={"node.a11yDescription.default":"Press enter or space to select a node. Press delete to remove it and escape to cancel.","node.a11yDescription.keyboardDisabled":"Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.","node.a11yDescription.ariaLiveMessage":({direction:u,x:f,y:l})=>`Moved selected node ${u}. New position, x: ${f}, y: ${l}`,"edge.a11yDescription.default":"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.","controls.ariaLabel":"Control Panel","controls.zoomIn.ariaLabel":"Zoom In","controls.zoomOut.ariaLabel":"Zoom Out","controls.fitView.ariaLabel":"Fit View","controls.interactive.ariaLabel":"Toggle Interactivity","minimap.ariaLabel":"Mini Map","handle.ariaLabel":"Handle"},Vn;(function(u){u.Strict="strict",u.Loose="loose"})(Vn||(Vn={}));var C0;(function(u){u.Free="free",u.Vertical="vertical",u.Horizontal="horizontal"})(C0||(C0={}));var X1;(function(u){u.Partial="partial",u.Full="full"})(X1||(X1={}));var mc={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null},$0;(function(u){u.Bezier="default",u.Straight="straight",u.Step="step",u.SmoothStep="smoothstep",u.SimpleBezier="simplebezier"})($0||($0={}));var Dn;(function(u){u.Arrow="arrow",u.ArrowClosed="arrowclosed"})(Dn||(Dn={}));var wu;(function(u){u.Left="left",u.Top="top",u.Right="right",u.Bottom="bottom"})(wu||(wu={}));var Pq={[wu.Left]:wu.Right,[wu.Right]:wu.Left,[wu.Top]:wu.Bottom,[wu.Bottom]:wu.Top};function Pc(u){return u===null?null:u?"valid":"invalid"}var Mc=(u)=>("id"in u)&&("source"in u)&&("target"in u),oq=(u)=>("id"in u)&&("position"in u)&&!("source"in u)&&!("target"in u),Cc=(u)=>("id"in u)&&("internals"in u)&&!("source"in u)&&!("target"in u);var w$=(u,f=[0,0])=>{let{width:l,height:r}=t0(u),n=u.origin??f,i=l*n[0],y=r*n[1];return{x:u.position.x-i,y:u.position.y-y}},Rc=(u,f={nodeOrigin:[0,0]})=>{if(u.length===0)return{x:0,y:0,width:0,height:0};let l=u.reduce((r,n)=>{let i=typeof n==="string",y=!f.nodeLookup&&!i?n:void 0;if(f.nodeLookup)y=i?f.nodeLookup.get(n):!Cc(n)?f.nodeLookup.get(n.id):n;let _=y?C6(y,f.nodeOrigin):{x:0,y:0,x2:0,y2:0};return x6(r,_)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return h6(l)},ry=(u,f={})=>{let l={x:1/0,y:1/0,x2:-1/0,y2:-1/0},r=!1;return u.forEach((n)=>{if(f.filter===void 0||f.filter(n))l=x6(l,C6(n)),r=!0}),r?h6(l):{x:0,y:0,width:0,height:0}},R6=(u,f,[l,r,n]=[0,0,1],i=!1,y=!1)=>{let _={...yy(f,[l,r,n]),width:f.width/n,height:f.height/n},$=[];for(let A of u.values()){let{measured:c,selectable:j=!0,hidden:F=!1}=A;if(y&&!j||F)continue;let U=c.width??A.width??A.initialWidth??null,Q=c.height??A.height??A.initialHeight??null,L=ny(_,S1(A)),w=(U??0)*(Q??0),J=i&&L>0;if(!A.internals.handleBounds||J||L>=w||A.dragging)$.push(A)}return $},dq=(u,f)=>{let l=new Set;return u.forEach((r)=>{l.add(r.id)}),f.filter((r)=>l.has(r.source)||l.has(r.target))};function kB(u,f){let l=new Map,r=f?.nodes?new Set(f.nodes.map((n)=>n.id)):null;return u.forEach((n)=>{if(n.measured.width&&n.measured.height&&(f?.includeHiddenNodes||!n.hidden)&&(!r||r.has(n.id)))l.set(n.id,n)}),l}async function eq({nodes:u,width:f,height:l,panZoom:r,minZoom:n,maxZoom:i},y){if(u.size===0)return Promise.resolve(!0);let _=kB(u,y),$=ry(_),A=K$($,f,l,y?.minZoom??n,y?.maxZoom??i,y?.padding??0.1);return await r.setViewport(A,{duration:y?.duration,ease:y?.ease,interpolate:y?.interpolate}),Promise.resolve(!0)}function xc({nodeId:u,nextPosition:f,nodeLookup:l,nodeOrigin:r=[0,0],nodeExtent:n,onError:i}){let y=l.get(u),_=y.parentId?l.get(y.parentId):void 0,{x:$,y:A}=_?_.internals.positionAbsolute:{x:0,y:0},c=y.origin??r,j=y.extent||n;if(y.extent==="parent"&&!y.expandParent)if(!_)i?.("005",Fr.error005());else{let U=_.measured.width,Q=_.measured.height;if(U&&Q)j=[[$,A],[$+U,A+Q]]}else if(_&&fy(y.extent))j=[[y.extent[0][0]+$,y.extent[0][1]+A],[y.extent[1][0]+$,y.extent[1][1]+A]];let F=fy(j)?Y1(f,j,y.measured):f;if(y.measured.width===void 0||y.measured.height===void 0)i?.("015",Fr.error015());return{position:{x:F.x-$+(y.measured.width??0)*c[0],y:F.y-A+(y.measured.height??0)*c[1]},positionAbsolute:F}}async function uN({nodesToRemove:u=[],edgesToRemove:f=[],nodes:l,edges:r,onBeforeDelete:n}){let i=new Set(u.map((F)=>F.id)),y=[];for(let F of l){if(F.deletable===!1)continue;let U=i.has(F.id),Q=!U&&F.parentId&&y.find((L)=>L.id===F.parentId);if(U||Q)y.push(F)}let _=new Set(f.map((F)=>F.id)),$=r.filter((F)=>F.deletable!==!1),c=dq(y,$);for(let F of $)if(_.has(F.id)&&!c.find((Q)=>Q.id===F.id))c.push(F);if(!n)return{edges:c,nodes:y};let j=await n({nodes:y,edges:c});if(typeof j==="boolean")return j?{edges:c,nodes:y}:{edges:[],nodes:[]};return j}var uy=(u,f=0,l=1)=>Math.min(Math.max(u,f),l),Y1=(u={x:0,y:0},f,l)=>({x:uy(u.x,f[0][0],f[1][0]-(l?.width??0)),y:uy(u.y,f[0][1],f[1][1]-(l?.height??0))});function fN(u,f,l){let{width:r,height:n}=t0(l),{x:i,y}=l.internals.positionAbsolute;return Y1(u,[[i,y],[i+r,y+n]],f)}var Mq=(u,f,l)=>{if(ul)return-uy(Math.abs(u-l),1,f)/f;return 0},lN=(u,f,l=15,r=40)=>{let n=Mq(u.x,r,f.width-r)*l,i=Mq(u.y,r,f.height-r)*l;return[n,i]},x6=(u,f)=>({x:Math.min(u.x,f.x),y:Math.min(u.y,f.y),x2:Math.max(u.x2,f.x2),y2:Math.max(u.y2,f.y2)}),Yc=({x:u,y:f,width:l,height:r})=>({x:u,y:f,x2:u+l,y2:f+r}),h6=({x:u,y:f,x2:l,y2:r})=>({x:u,y:f,width:l-u,height:r-f}),S1=(u,f=[0,0])=>{let{x:l,y:r}=Cc(u)?u.internals.positionAbsolute:w$(u,f);return{x:l,y:r,width:u.measured?.width??u.width??u.initialWidth??0,height:u.measured?.height??u.height??u.initialHeight??0}},C6=(u,f=[0,0])=>{let{x:l,y:r}=Cc(u)?u.internals.positionAbsolute:w$(u,f);return{x:l,y:r,x2:l+(u.measured?.width??u.width??u.initialWidth??0),y2:r+(u.measured?.height??u.height??u.initialHeight??0)}},hc=(u,f)=>h6(x6(Yc(u),Yc(f))),ny=(u,f)=>{let l=Math.max(0,Math.min(u.x+u.width,f.x+f.width)-Math.max(u.x,f.x)),r=Math.max(0,Math.min(u.y+u.height,f.y+f.height)-Math.max(u.y,f.y));return Math.ceil(l*r)},bc=(u)=>Er(u.width)&&Er(u.height)&&Er(u.x)&&Er(u.y),Er=(u)=>!isNaN(u)&&isFinite(u),vc=(u,f)=>{},iy=(u,f=[1,1])=>{return{x:f[0]*Math.round(u.x/f[0]),y:f[1]*Math.round(u.y/f[1])}},yy=({x:u,y:f},[l,r,n],i=!1,y=[1,1])=>{let _={x:(u-l)/n,y:(f-r)/n};return i?iy(_,y):_},L$=({x:u,y:f},[l,r,n])=>{return{x:u*n+l,y:f*n+r}};function di(u,f){if(typeof u==="number")return Math.floor((f-f/(1+u))*0.5);if(typeof u==="string"&&u.endsWith("px")){let l=parseFloat(u);if(!Number.isNaN(l))return Math.floor(l)}if(typeof u==="string"&&u.endsWith("%")){let l=parseFloat(u);if(!Number.isNaN(l))return Math.floor(f*l*0.01)}return console.error(`[React Flow] The padding value "${u}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function IB(u,f,l){if(typeof u==="string"||typeof u==="number"){let r=di(u,l),n=di(u,f);return{top:r,right:n,bottom:r,left:n,x:n*2,y:r*2}}if(typeof u==="object"){let r=di(u.top??u.y??0,l),n=di(u.bottom??u.y??0,l),i=di(u.left??u.x??0,f),y=di(u.right??u.x??0,f);return{top:r,right:y,bottom:n,left:i,x:i+y,y:r+n}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function gB(u,f,l,r,n,i){let{x:y,y:_}=L$(u,[f,l,r]),{x:$,y:A}=L$({x:u.x+u.width,y:u.y+u.height},[f,l,r]),c=n-$,j=i-A;return{left:Math.floor(y),top:Math.floor(_),right:Math.floor(c),bottom:Math.floor(j)}}var K$=(u,f,l,r,n,i)=>{let y=IB(i,f,l),_=(f-y.x)/u.width,$=(l-y.y)/u.height,A=Math.min(_,$),c=uy(A,r,n),j=u.x+u.width/2,F=u.y+u.height/2,U=f/2-j*c,Q=l/2-F*c,L=gB(u,U,Q,c,f,l),w={left:Math.min(L.left-y.left,0),top:Math.min(L.top-y.top,0),right:Math.min(L.right-y.right,0),bottom:Math.min(L.bottom-y.bottom,0)};return{x:U-w.left+w.right,y:Q-w.top+w.bottom,zoom:c}},_y=()=>typeof navigator<"u"&&navigator?.userAgent?.indexOf("Mac")>=0;function fy(u){return u!==void 0&&u!==null&&u!=="parent"}function t0(u){return{width:u.measured?.width??u.width??u.initialWidth??0,height:u.measured?.height??u.height??u.initialHeight??0}}function kc(u){return(u.measured?.width??u.width??u.initialWidth)!==void 0&&(u.measured?.height??u.height??u.initialHeight)!==void 0}function Ic(u,f={width:0,height:0},l,r,n){let i={...u},y=r.get(l);if(y){let _=y.origin||n;i.x+=y.internals.positionAbsolute.x-(f.width??0)*_[0],i.y+=y.internals.positionAbsolute.y-(f.height??0)*_[1]}return i}function gc(u,f){if(u.size!==f.size)return!1;for(let l of u)if(!f.has(l))return!1;return!0}function rN(){let u,f;return{promise:new Promise((r,n)=>{u=r,f=n}),resolve:u,reject:f}}function nN(u){return{...pc,...u||{}}}function W$(u,{snapGrid:f=[0,0],snapToGrid:l=!1,transform:r,containerBounds:n}){let{x:i,y}=Zr(u),_=yy({x:i-(n?.left??0),y:y-(n?.top??0)},r),{x:$,y:A}=l?iy(_,f):_;return{xSnapped:$,ySnapped:A,..._}}var b6=(u)=>({width:u.offsetWidth,height:u.offsetHeight}),sc=(u)=>u?.getRootNode?.()||window?.document,sB=["INPUT","SELECT","TEXTAREA"];function ac(u){let f=u.composedPath?.()?.[0]||u.target;if(f?.nodeType!==1)return!1;return sB.includes(f.nodeName)||f.hasAttribute("contenteditable")||!!f.closest(".nokey")}var oc=(u)=>("clientX"in u),Zr=(u,f)=>{let l=oc(u),r=l?u.clientX:u.touches?.[0].clientX,n=l?u.clientY:u.touches?.[0].clientY;return{x:r-(f?.left??0),y:n-(f?.top??0)}},Cq=(u,f,l,r,n)=>{let i=f.querySelectorAll(`.${u}`);if(!i||!i.length)return null;return Array.from(i).map((y)=>{let _=y.getBoundingClientRect();return{id:y.getAttribute("data-handleid"),type:u,nodeId:n,position:y.getAttribute("data-handlepos"),x:(_.left-l.left)/r,y:(_.top-l.top)/r,...b6(y)}})};function v6({sourceX:u,sourceY:f,targetX:l,targetY:r,sourceControlX:n,sourceControlY:i,targetControlX:y,targetControlY:_}){let $=u*0.125+n*0.375+y*0.375+l*0.125,A=f*0.125+i*0.375+_*0.375+r*0.125,c=Math.abs($-u),j=Math.abs(A-f);return[$,A,c,j]}function P6(u,f){if(u>=0)return 0.5*u;return f*25*Math.sqrt(-u)}function Rq({pos:u,x1:f,y1:l,x2:r,y2:n,c:i}){switch(u){case wu.Left:return[f-P6(f-r,i),l];case wu.Right:return[f+P6(r-f,i),l];case wu.Top:return[f,l-P6(l-n,i)];case wu.Bottom:return[f,l+P6(n-l,i)]}}function k6({sourceX:u,sourceY:f,sourcePosition:l=wu.Bottom,targetX:r,targetY:n,targetPosition:i=wu.Top,curvature:y=0.25}){let[_,$]=Rq({pos:l,x1:u,y1:f,x2:r,y2:n,c:y}),[A,c]=Rq({pos:i,x1:r,y1:n,x2:u,y2:f,c:y}),[j,F,U,Q]=v6({sourceX:u,sourceY:f,targetX:r,targetY:n,sourceControlX:_,sourceControlY:$,targetControlX:A,targetControlY:c});return[`M${u},${f} C${_},${$} ${A},${c} ${r},${n}`,j,F,U,Q]}function dc({sourceX:u,sourceY:f,targetX:l,targetY:r}){let n=Math.abs(l-u)/2,i=l0}var aB=({source:u,sourceHandle:f,target:l,targetHandle:r})=>`xy-edge__${u}${f||""}-${l}${r||""}`,oB=(u,f)=>{return f.some((l)=>l.source===u.source&&l.target===u.target&&(l.sourceHandle===u.sourceHandle||!l.sourceHandle&&!u.sourceHandle)&&(l.targetHandle===u.targetHandle||!l.targetHandle&&!u.targetHandle))},ec=(u,f,l={})=>{if(!u.source||!u.target)return vc("006",Fr.error006()),f;let r=l.getEdgeId||aB,n;if(Mc(u))n={...u};else n={...u,id:r(u)};if(oB(n,f))return f;if(n.sourceHandle===null)delete n.sourceHandle;if(n.targetHandle===null)delete n.targetHandle;return f.concat(n)};function I6({sourceX:u,sourceY:f,targetX:l,targetY:r}){let[n,i,y,_]=dc({sourceX:u,sourceY:f,targetX:l,targetY:r});return[`M ${u},${f}L ${l},${r}`,n,i,y,_]}var xq={[wu.Left]:{x:-1,y:0},[wu.Right]:{x:1,y:0},[wu.Top]:{x:0,y:-1},[wu.Bottom]:{x:0,y:1}},dB=({source:u,sourcePosition:f=wu.Bottom,target:l})=>{if(f===wu.Left||f===wu.Right)return u.xMath.sqrt(Math.pow(f.x-u.x,2)+Math.pow(f.y-u.y,2));function eB({source:u,sourcePosition:f=wu.Bottom,target:l,targetPosition:r=wu.Top,center:n,offset:i,stepPosition:y}){let _=xq[f],$=xq[r],A={x:u.x+_.x*i,y:u.y+_.y*i},c={x:l.x+$.x*i,y:l.y+$.y*i},j=dB({source:A,sourcePosition:f,target:c}),F=j.x!==0?"x":"y",U=j[F],Q=[],L,w,J={x:0,y:0},N={x:0,y:0},[,,q,W]=dc({sourceX:u.x,sourceY:u.y,targetX:l.x,targetY:l.y});if(_[F]*$[F]===-1){if(F==="x")L=n.x??A.x+(c.x-A.x)*y,w=n.y??(A.y+c.y)/2;else L=n.x??(A.x+c.x)/2,w=n.y??A.y+(c.y-A.y)*y;let E=[{x:L,y:A.y},{x:L,y:c.y}],D=[{x:A.x,y:w},{x:c.x,y:w}];if(_[F]===U)Q=F==="x"?E:D;else Q=F==="x"?D:E}else{let E=[{x:A.x,y:c.y}],D=[{x:c.x,y:A.y}];if(F==="x")Q=_.x===U?D:E;else Q=_.y===U?E:D;if(f===r){let O=Math.abs(u[F]-l[F]);if(O<=i){let m=Math.min(i-1,i-O);if(_[F]===U)J[F]=(A[F]>u[F]?-1:1)*m;else N[F]=(c[F]>l[F]?-1:1)*m}}if(f!==r){let O=F==="x"?"y":"x",m=_[F]===$[O],X=A[O]>c[O],v=A[O]=p)L=(h.x+V.x)/2,w=Q[0].y;else L=Q[0].x,w=(h.y+V.y)/2}let z={x:A.x+J.x,y:A.y+J.y},Z={x:c.x+N.x,y:c.y+N.y};return[[u,...z.x!==Q[0].x||z.y!==Q[0].y?[z]:[],...Q,...Z.x!==Q[Q.length-1].x||Z.y!==Q[Q.length-1].y?[Z]:[],l],L,w,q,W]}function uV(u,f,l,r){let n=Math.min(hq(u,f)/2,hq(f,l)/2,r),{x:i,y}=f;if(u.x===i&&i===l.x||u.y===y&&y===l.y)return`L${i} ${y}`;if(u.y===y){let A=u.xl.id===f))||null}function g6(u,f){if(!u)return"";if(typeof u==="string")return u;return`${f?`${f}__`:""}${Object.keys(u).sort().map((r)=>`${r}=${u[r]}`).join("&")}`}function $N(u,{id:f,defaultColor:l,defaultMarkerStart:r,defaultMarkerEnd:n}){let i=new Set;return u.reduce((y,_)=>{return[_.markerStart||r,_.markerEnd||n].forEach(($)=>{if($&&typeof $==="object"){let A=g6($,f);if(!i.has(A))y.push({id:A,color:$.color||l,...$}),i.add(A)}}),y},[]).sort((y,_)=>y.id.localeCompare(_.id))}var tN=1000,fV=10,u9={nodeOrigin:[0,0],nodeExtent:ly,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},lV={...u9,checkEquality:!0};function f9(u,f){let l={...u};for(let r in f)if(f[r]!==void 0)l[r]=f[r];return l}function AN(u,f,l){let r=f9(u9,l);for(let n of u.values())if(n.parentId)r9(n,u,f,r);else{let i=w$(n,r.nodeOrigin),y=fy(n.extent)?n.extent:r.nodeExtent,_=Y1(i,y,t0(n));n.internals.positionAbsolute=_}}function rV(u,f){if(!u.handles)return!u.measured?void 0:f?.internals.handleBounds;let l=[],r=[];for(let n of u.handles){let i={id:n.id,width:n.width??1,height:n.height??1,nodeId:u.id,x:n.x,y:n.y,position:n.position,type:n.type};if(n.type==="source")l.push(i);else if(n.type==="target")r.push(i)}return{source:l,target:r}}function l9(u){return u==="manual"}function s6(u,f,l,r={}){let n=f9(lV,r),i={i:0},y=new Map(f),_=n?.elevateNodesOnSelect&&!l9(n.zIndexMode)?tN:0,$=u.length>0,A=!1;f.clear(),l.clear();for(let c of u){let j=y.get(c.id);if(n.checkEquality&&c===j?.internals.userNode)f.set(c.id,j);else{let F=w$(c,n.nodeOrigin),U=fy(c.extent)?c.extent:n.nodeExtent,Q=Y1(F,U,t0(c));j={...n.defaults,...c,measured:{width:c.measured?.width,height:c.measured?.height},internals:{positionAbsolute:Q,handleBounds:rV(c,j),z:cN(c,_,n.zIndexMode),userNode:c}},f.set(c.id,j)}if((j.measured===void 0||j.measured.width===void 0||j.measured.height===void 0)&&!j.hidden)$=!1;if(c.parentId)r9(j,f,l,r,i);A||=c.selected??!1}return{nodesInitialized:$,hasSelectedNodes:A}}function nV(u,f){if(!u.parentId)return;let l=f.get(u.parentId);if(l)l.set(u.id,u);else f.set(u.parentId,new Map([[u.id,u]]))}function r9(u,f,l,r,n){let{elevateNodesOnSelect:i,nodeOrigin:y,nodeExtent:_,zIndexMode:$}=f9(u9,r),A=u.parentId,c=f.get(A);if(!c){console.warn(`Parent node ${A} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}if(nV(u,l),n&&!c.parentId&&c.internals.rootParentIndex===void 0&&$==="auto")c.internals.rootParentIndex=++n.i,c.internals.z=c.internals.z+n.i*fV;if(n&&c.internals.rootParentIndex!==void 0)n.i=c.internals.rootParentIndex;let j=i&&!l9($)?tN:0,{x:F,y:U,z:Q}=iV(u,c,y,_,j,$),{positionAbsolute:L}=u.internals,w=F!==L.x||U!==L.y;if(w||Q!==u.internals.z)f.set(u.id,{...u,internals:{...u.internals,positionAbsolute:w?{x:F,y:U}:L,z:Q}})}function cN(u,f,l){let r=Er(u.zIndex)?u.zIndex:0;if(l9(l))return r;return r+(u.selected?f:0)}function iV(u,f,l,r,n,i){let{x:y,y:_}=f.internals.positionAbsolute,$=t0(u),A=w$(u,l),c=fy(u.extent)?Y1(A,u.extent,$):A,j=Y1({x:y+c.x,y:_+c.y},r,$);if(u.extent==="parent")j=fN(j,$,f);let F=cN(u,n,i),U=f.internals.z??0;return{x:j.x,y:j.y,z:U>=F?U+1:F}}function a6(u,f,l,r=[0,0]){let n=[],i=new Map;for(let y of u){let _=f.get(y.parentId);if(!_)continue;let $=i.get(y.parentId)?.expandedRect??S1(_),A=hc($,y.rect);i.set(y.parentId,{expandedRect:A,parent:_})}if(i.size>0)i.forEach(({expandedRect:y,parent:_},$)=>{let A=_.internals.positionAbsolute,c=t0(_),j=_.origin??r,F=y.x0||U>0||w||J)n.push({id:$,type:"position",position:{x:_.position.x-F+w,y:_.position.y-U+J}}),l.get($)?.forEach((N)=>{if(!u.some((q)=>q.id===N.id))n.push({id:N.id,type:"position",position:{x:N.position.x+F,y:N.position.y+U}})});if(c.width0){let U=a6(F,f,l,n);A.push(...U)}return{changes:A,updatedInternals:$}}async function FN({delta:u,panZoom:f,transform:l,translateExtent:r,width:n,height:i}){if(!f||!u.x&&!u.y)return Promise.resolve(!1);let y=await f.setViewportConstrained({x:l[0]+u.x,y:l[1]+u.y,zoom:l[2]},[[0,0],[n,i]],r),_=!!y&&(y.x!==l[0]||y.y!==l[1]||y.k!==l[2]);return Promise.resolve(_)}function Iq(u,f,l,r,n,i){let y=n,_=r.get(y)||new Map;r.set(y,_.set(l,f)),y=`${n}-${u}`;let $=r.get(y)||new Map;if(r.set(y,$.set(l,f)),i){y=`${n}-${u}-${i}`;let A=r.get(y)||new Map;r.set(y,A.set(l,f))}}function n9(u,f,l){u.clear(),f.clear();for(let r of l){let{source:n,target:i,sourceHandle:y=null,targetHandle:_=null}=r,$={edgeId:r.id,source:n,target:i,sourceHandle:y,targetHandle:_},A=`${n}-${y}--${i}-${_}`,c=`${i}-${_}--${n}-${y}`;Iq("source",$,c,u,n,y),Iq("target",$,A,u,i,_),f.set(r.id,r)}}function JN(u,f){if(!u.parentId)return!1;let l=f.get(u.parentId);if(!l)return!1;if(l.selected)return!0;return JN(l,f)}function gq(u,f,l){let r=u;do{if(r?.matches?.(f))return!0;if(r===l)return!1;r=r?.parentElement}while(r);return!1}function yV(u,f,l,r){let n=new Map;for(let[i,y]of u)if((y.selected||y.id===r)&&(!y.parentId||!JN(y,u))&&(y.draggable||f&&typeof y.draggable>"u")){let _=u.get(i);if(_)n.set(i,{id:i,position:_.position||{x:0,y:0},distance:{x:l.x-_.internals.positionAbsolute.x,y:l.y-_.internals.positionAbsolute.y},extent:_.extent,parentId:_.parentId,origin:_.origin,expandParent:_.expandParent,internals:{positionAbsolute:_.internals.positionAbsolute||{x:0,y:0}},measured:{width:_.measured.width??0,height:_.measured.height??0}})}return n}function Vc({nodeId:u,dragItems:f,nodeLookup:l,dragging:r=!0}){let n=[];for(let[y,_]of f){let $=l.get(y)?.internals.userNode;if($)n.push({...$,position:_.position,dragging:r})}if(!u)return[n[0],n];let i=l.get(u)?.internals.userNode;return[!i?n[0]:{...i,position:f.get(u)?.position||i.position,dragging:r},n]}function _V({dragItems:u,snapGrid:f,x:l,y:r}){let n=u.values().next().value;if(!n)return null;let i={x:l-n.distance.x,y:r-n.distance.y},y=iy(i,f);return{x:y.x-i.x,y:y.y-i.y}}function UN({onNodeMouseDown:u,getStoreItems:f,onDragStart:l,onDrag:r,onDragStop:n}){let i={x:null,y:null},y=0,_=new Map,$=!1,A={x:0,y:0},c=null,j=!1,F=null,U=!1,Q=!1,L=null;function w({noDragClassName:N,handleSelector:q,domNode:W,isSelectable:z,nodeId:Z,nodeClickDistance:H=0}){F=af(W);function E({x:Y,y:p}){let{nodeLookup:O,nodeExtent:m,snapGrid:X,snapToGrid:v,nodeOrigin:T,onNodeDrag:S,onSelectionDrag:k,onError:I,updateNodePositions:b}=f();i={x:Y,y:p};let o=!1,s=_.size>1,x=s&&m?Yc(ry(_)):null,fu=s&&v?_V({dragItems:_,snapGrid:X,x:Y,y:p}):null;for(let[$u,tu]of _){if(!O.has($u))continue;let ju={x:Y-tu.distance.x,y:p-tu.distance.y};if(v)ju=fu?{x:Math.round(ju.x+fu.x),y:Math.round(ju.y+fu.y)}:iy(ju,X);let Gu=null;if(s&&m&&!tu.extent&&x){let{positionAbsolute:e}=tu.internals,uu=e.x-x.x+m[0][0],Wu=e.x+tu.measured.width-x.x2+m[1][0],g=e.y-x.y+m[0][1],Qu=e.y+tu.measured.height-x.y2+m[1][1];Gu=[[uu,g],[Wu,Qu]]}let{position:qu,positionAbsolute:P}=xc({nodeId:$u,nextPosition:ju,nodeLookup:O,nodeExtent:Gu?Gu:m,nodeOrigin:T,onError:I});o=o||tu.position.x!==qu.x||tu.position.y!==qu.y,tu.position=qu,tu.internals.positionAbsolute=P}if(Q=Q||o,!o)return;if(b(_,!0),L&&(r||S||!Z&&k)){let[$u,tu]=Vc({nodeId:Z,dragItems:_,nodeLookup:O});if(r?.(L,_,$u,tu),S?.(L,$u,tu),!Z)k?.(L,tu)}}async function D(){if(!c)return;let{transform:Y,panBy:p,autoPanSpeed:O,autoPanOnNodeDrag:m}=f();if(!m){$=!1,cancelAnimationFrame(y);return}let[X,v]=lN(A,c,O);if(X!==0||v!==0){if(i.x=(i.x??0)-X/Y[2],i.y=(i.y??0)-v/Y[2],await p({x:X,y:v}))E(i)}y=requestAnimationFrame(D)}function h(Y){let{nodeLookup:p,multiSelectionActive:O,nodesDraggable:m,transform:X,snapGrid:v,snapToGrid:T,selectNodesOnDrag:S,onNodeDragStart:k,onSelectionDragStart:I,unselectNodesAndEdges:b}=f();if(j=!0,(!S||!z)&&!O&&Z){if(!p.get(Z)?.selected)b()}if(z&&S&&Z)u?.(Z);let o=W$(Y.sourceEvent,{transform:X,snapGrid:v,snapToGrid:T,containerBounds:c});if(i=o,_=yV(p,m,o,Z),_.size>0&&(l||k||!Z&&I)){let[s,x]=Vc({nodeId:Z,dragItems:_,nodeLookup:p});if(l?.(Y.sourceEvent,_,s,x),k?.(Y.sourceEvent,s,x),!Z)I?.(Y.sourceEvent,x)}}let V=u$().clickDistance(H).on("start",(Y)=>{let{domNode:p,nodeDragThreshold:O,transform:m,snapGrid:X,snapToGrid:v}=f();if(c=p?.getBoundingClientRect()||null,U=!1,Q=!1,L=Y.sourceEvent,O===0)h(Y);i=W$(Y.sourceEvent,{transform:m,snapGrid:X,snapToGrid:v,containerBounds:c}),A=Zr(Y.sourceEvent,c)}).on("drag",(Y)=>{let{autoPanOnNodeDrag:p,transform:O,snapGrid:m,snapToGrid:X,nodeDragThreshold:v,nodeLookup:T}=f(),S=W$(Y.sourceEvent,{transform:O,snapGrid:m,snapToGrid:X,containerBounds:c});if(L=Y.sourceEvent,Y.sourceEvent.type==="touchmove"&&Y.sourceEvent.touches.length>1||Z&&!T.has(Z))U=!0;if(U)return;if(!$&&p&&j)$=!0,D();if(!j){let k=Zr(Y.sourceEvent,c),I=k.x-A.x,b=k.y-A.y;if(Math.sqrt(I*I+b*b)>v)h(Y)}if((i.x!==S.xSnapped||i.y!==S.ySnapped)&&_&&j)A=Zr(Y.sourceEvent,c),E(S)}).on("end",(Y)=>{if(!j||U)return;if($=!1,j=!1,cancelAnimationFrame(y),_.size>0){let{nodeLookup:p,updateNodePositions:O,onNodeDragStop:m,onSelectionDragStop:X}=f();if(Q)O(_,!1),Q=!1;if(n||m||!Z&&X){let[v,T]=Vc({nodeId:Z,dragItems:_,nodeLookup:p,dragging:!1});if(n?.(Y.sourceEvent,_,v,T),m?.(Y.sourceEvent,v,T),!Z)X?.(Y.sourceEvent,T)}}}).filter((Y)=>{let p=Y.target;return!Y.button&&(!N||!gq(p,`.${N}`,W))&&(!q||gq(p,q,W))});F.call(V)}function J(){F?.on(".drag",null)}return{update:w,destroy:J}}function $V(u,f,l){let r=[],n={x:u.x-l,y:u.y-l,width:l*2,height:l*2};for(let i of f.values())if(ny(n,S1(i))>0)r.push(i);return r}var tV=250;function AV(u,f,l,r){let n=[],i=1/0,y=$V(u,l,f+tV);for(let _ of y){let $=[..._.internals.handleBounds?.source??[],..._.internals.handleBounds?.target??[]];for(let A of $){if(r.nodeId===A.nodeId&&r.type===A.type&&r.id===A.id)continue;let{x:c,y:j}=Xn(_,A,A.position,!0),F=Math.sqrt(Math.pow(c-u.x,2)+Math.pow(j-u.y,2));if(F>f)continue;if(F1){let _=r.type==="source"?"target":"source";return n.find(($)=>$.type===_)??n[0]}return n[0]}function QN(u,f,l,r,n,i=!1){let y=r.get(u);if(!y)return null;let _=n==="strict"?y.internals.handleBounds?.[f]:[...y.internals.handleBounds?.source??[],...y.internals.handleBounds?.target??[]],$=(l?_?.find((A)=>A.id===l):_?.[0])??null;return $&&i?{...$,...Xn(y,$,$.position,!0)}:$}function qN(u,f){if(u)return u;else if(f?.classList.contains("target"))return"target";else if(f?.classList.contains("source"))return"source";return null}function cV(u,f){let l=null;if(f)l=!0;else if(u&&!f)l=!1;return l}var NN=()=>!0;function jV(u,{connectionMode:f,connectionRadius:l,handleId:r,nodeId:n,edgeUpdaterType:i,isTarget:y,domNode:_,nodeLookup:$,lib:A,autoPanOnConnect:c,flowId:j,panBy:F,cancelConnection:U,onConnectStart:Q,onConnect:L,onConnectEnd:w,isValidConnection:J=NN,onReconnectEnd:N,updateConnection:q,getTransform:W,getFromHandle:z,autoPanSpeed:Z,dragThreshold:H=1,handleDomNode:E}){let D=sc(u.target),h=0,V,{x:Y,y:p}=Zr(u),O=qN(i,E),m=_?.getBoundingClientRect(),X=!1;if(!m||!O)return;let v=QN(n,O,r,$,f);if(!v)return;let T=Zr(u,m),S=!1,k=null,I=!1,b=null;function o(){if(!c||!m)return;let[qu,P]=lN(T,m,Z);F({x:qu,y:P}),h=requestAnimationFrame(o)}let s={...v,nodeId:n,type:O,position:v.position},x=$.get(n),$u={inProgress:!0,isValid:null,from:Xn(x,s,wu.Left,!0),fromHandle:s,fromPosition:s.position,fromNode:x,to:T,toHandle:null,toPosition:Pq[s.position],toNode:null,pointer:T};function tu(){X=!0,q($u),Q?.(u,{nodeId:n,handleId:r,handleType:O})}if(H===0)tu();function ju(qu){if(!X){let{x:Qu,y:Tu}=Zr(qu),Zu=Qu-Y,Xu=Tu-p;if(!(Zu*Zu+Xu*Xu>H*H))return;tu()}if(!z()||!s){Gu(qu);return}let P=W();if(T=Zr(qu,m),V=AV(yy(T,P,!1,[1,1]),l,$,s),!S)o(),S=!0;let e=WN(qu,{handle:V,connectionMode:f,fromNodeId:n,fromHandleId:r,fromType:y?"target":"source",isValidConnection:J,doc:D,lib:A,flowId:j,nodeLookup:$});b=e.handleDomNode,k=e.connection,I=cV(!!V,e.isValid);let uu=$.get(n),Wu=uu?Xn(uu,s,wu.Left,!0):$u.from,g={...$u,from:Wu,isValid:I,to:e.toHandle&&I?L$({x:e.toHandle.x,y:e.toHandle.y},P):T,toHandle:e.toHandle,toPosition:I&&e.toHandle?e.toHandle.position:Pq[s.position],toNode:e.toHandle?$.get(e.toHandle.nodeId):null,pointer:T};q(g),$u=g}function Gu(qu){if("touches"in qu&&qu.touches.length>0)return;if(X){if((V||b)&&k&&I)L?.(k);let{inProgress:P,...e}=$u,uu={...e,toPosition:$u.toHandle?$u.toPosition:null};if(w?.(qu,uu),i)N?.(qu,uu)}U(),cancelAnimationFrame(h),S=!1,I=!1,k=null,b=null,D.removeEventListener("mousemove",ju),D.removeEventListener("mouseup",Gu),D.removeEventListener("touchmove",ju),D.removeEventListener("touchend",Gu)}D.addEventListener("mousemove",ju),D.addEventListener("mouseup",Gu),D.addEventListener("touchmove",ju),D.addEventListener("touchend",Gu)}function WN(u,{handle:f,connectionMode:l,fromNodeId:r,fromHandleId:n,fromType:i,doc:y,lib:_,flowId:$,isValidConnection:A=NN,nodeLookup:c}){let j=i==="target",F=f?y.querySelector(`.${_}-flow__handle[data-id="${$}-${f?.nodeId}-${f?.id}-${f?.type}"]`):null,{x:U,y:Q}=Zr(u),L=y.elementFromPoint(U,Q),w=L?.classList.contains(`${_}-flow__handle`)?L:F,J={handleDomNode:w,isValid:!1,connection:null,toHandle:null};if(w){let N=qN(void 0,w),q=w.getAttribute("data-nodeid"),W=w.getAttribute("data-handleid"),z=w.classList.contains("connectable"),Z=w.classList.contains("connectableend");if(!q||!N)return J;let H={source:j?q:r,sourceHandle:j?W:n,target:j?r:q,targetHandle:j?n:W};J.connection=H;let D=z&&Z&&(l===Vn.Strict?j&&N==="source"||!j&&N==="target":q!==r||W!==n);J.isValid=D&&A(H),J.toHandle=QN(q,N,W,c,l,!0)}return J}var o6={onPointerDown:jV,isValid:WN};function LN({domNode:u,panZoom:f,getTransform:l,getViewScale:r}){let n=af(u);function i({translateExtent:_,width:$,height:A,zoomStep:c=1,pannable:j=!0,zoomable:F=!0,inversePan:U=!1}){let Q=(q)=>{if(q.sourceEvent.type!=="wheel"||!f)return;let W=l(),z=q.sourceEvent.ctrlKey&&_y()?10:1,Z=-q.sourceEvent.deltaY*(q.sourceEvent.deltaMode===1?0.05:q.sourceEvent.deltaMode?1:0.002)*c,H=W[2]*Math.pow(2,Z*z);f.scaleTo(H)},L=[0,0],w=(q)=>{if(q.sourceEvent.type==="mousedown"||q.sourceEvent.type==="touchstart")L=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY]},J=(q)=>{let W=l();if(q.sourceEvent.type!=="mousemove"&&q.sourceEvent.type!=="touchmove"||!f)return;let z=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY],Z=[z[0]-L[0],z[1]-L[1]];L=z;let H=r()*Math.max(W[2],Math.log(W[2]))*(U?-1:1),E={x:W[0]-Z[0]*H,y:W[1]-Z[1]*H},D=[[0,0],[$,A]];f.setViewportConstrained({x:E.x,y:E.y,zoom:W[2]},D,_)},N=N$().on("start",w).on("zoom",j?J:null).on("zoom.wheel",F?Q:null);n.call(N,{})}function y(){n.on("zoom",null)}return{update:i,destroy:y,pointer:Kl}}var d6=(u)=>({x:u.x,y:u.y,zoom:u.k}),Dc=({x:u,y:f,zoom:l})=>V1.translate(u,f).scale(l),ei=(u,f)=>u.target.closest(`.${f}`),wN=(u,f)=>f===2&&Array.isArray(u)&&u.includes(2),FV=(u)=>((u*=2)<=1?u*u*u:(u-=2)*u*u+2)/2,Xc=(u,f=0,l=FV,r=()=>{})=>{let n=typeof f==="number"&&f>0;if(!n)r();return n?u.transition().duration(f).ease(l).on("end",r):u},KN=(u)=>{let f=u.ctrlKey&&_y()?10:1;return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*f};function JV({zoomPanValues:u,noWheelClassName:f,d3Selection:l,d3Zoom:r,panOnScrollMode:n,panOnScrollSpeed:i,zoomOnPinch:y,onPanZoomStart:_,onPanZoom:$,onPanZoomEnd:A}){return(c)=>{if(ei(c,f)){if(c.ctrlKey)c.preventDefault();return!1}c.preventDefault(),c.stopImmediatePropagation();let j=l.property("__zoom").k||1;if(c.ctrlKey&&y){let w=Kl(c),J=KN(c),N=j*Math.pow(2,J);r.scaleTo(l,N,w,c);return}let F=c.deltaMode===1?20:1,U=n===C0.Vertical?0:c.deltaX*F,Q=n===C0.Horizontal?0:c.deltaY*F;if(!_y()&&c.shiftKey&&n!==C0.Vertical)U=c.deltaY*F,Q=0;r.translateBy(l,-(U/j)*i,-(Q/j)*i,{internal:!0});let L=d6(l.property("__zoom"));if(clearTimeout(u.panScrollTimeout),!u.isPanScrolling)u.isPanScrolling=!0,_?.(c,L);else $?.(c,L),u.panScrollTimeout=setTimeout(()=>{A?.(c,L),u.isPanScrolling=!1},150)}}function UV({noWheelClassName:u,preventScrolling:f,d3ZoomHandler:l}){return function(r,n){let i=r.type==="wheel",y=!f&&i&&!r.ctrlKey,_=ei(r,u);if(r.ctrlKey&&i&&_)r.preventDefault();if(y||_)return null;r.preventDefault(),l.call(this,r,n)}}function QV({zoomPanValues:u,onDraggingChange:f,onPanZoomStart:l}){return(r)=>{if(r.sourceEvent?.internal)return;let n=d6(r.transform);if(u.mouseButton=r.sourceEvent?.button||0,u.isZoomingOrPanning=!0,u.prevViewport=n,r.sourceEvent?.type==="mousedown")f(!0);if(l)l?.(r.sourceEvent,n)}}function qV({zoomPanValues:u,panOnDrag:f,onPaneContextMenu:l,onTransformChange:r,onPanZoom:n}){return(i)=>{if(u.usedRightMouseButton=!!(l&&wN(f,u.mouseButton??0)),!i.sourceEvent?.sync)r([i.transform.x,i.transform.y,i.transform.k]);if(n&&!i.sourceEvent?.internal)n?.(i.sourceEvent,d6(i.transform))}}function NV({zoomPanValues:u,panOnDrag:f,panOnScroll:l,onDraggingChange:r,onPanZoomEnd:n,onPaneContextMenu:i}){return(y)=>{if(y.sourceEvent?.internal)return;if(u.isZoomingOrPanning=!1,i&&wN(f,u.mouseButton??0)&&!u.usedRightMouseButton&&y.sourceEvent)i(y.sourceEvent);if(u.usedRightMouseButton=!1,r(!1),n){let _=d6(y.transform);u.prevViewport=_,clearTimeout(u.timerId),u.timerId=setTimeout(()=>{n?.(y.sourceEvent,_)},l?150:0)}}}function WV({zoomActivationKeyPressed:u,zoomOnScroll:f,zoomOnPinch:l,panOnDrag:r,panOnScroll:n,zoomOnDoubleClick:i,userSelectionActive:y,noWheelClassName:_,noPanClassName:$,lib:A,connectionInProgress:c}){return(j)=>{let F=u||f,U=l&&j.ctrlKey,Q=j.type==="wheel";if(j.button===1&&j.type==="mousedown"&&(ei(j,`${A}-flow__node`)||ei(j,`${A}-flow__edge`)))return!0;if(!r&&!F&&!n&&!i&&!l)return!1;if(y)return!1;if(c&&!Q)return!1;if(ei(j,_)&&Q)return!1;if(ei(j,$)&&(!Q||n&&Q&&!u))return!1;if(!l&&j.ctrlKey&&Q)return!1;if(!l&&j.type==="touchstart"&&j.touches?.length>1)return j.preventDefault(),!1;if(!F&&!n&&!U&&Q)return!1;if(!r&&(j.type==="mousedown"||j.type==="touchstart"))return!1;if(Array.isArray(r)&&!r.includes(j.button)&&j.type==="mousedown")return!1;let L=Array.isArray(r)&&r.includes(j.button)||!j.button||j.button<=1;return(!j.ctrlKey||Q)&&L}}function GN({domNode:u,minZoom:f,maxZoom:l,translateExtent:r,viewport:n,onPanZoom:i,onPanZoomStart:y,onPanZoomEnd:_,onDraggingChange:$}){let A={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},c=u.getBoundingClientRect(),j=N$().scaleExtent([f,l]).translateExtent(r),F=af(u).call(j);N({x:n.x,y:n.y,zoom:uy(n.zoom,f,l)},[[0,0],[c.width,c.height]],r);let U=F.on("wheel.zoom"),Q=F.on("dblclick.zoom");j.wheelDelta(KN);function L(V,Y){if(F)return new Promise((p)=>{j?.interpolate(Y?.interpolate==="linear"?_0:H1).transform(Xc(F,Y?.duration,Y?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function w({noWheelClassName:V,noPanClassName:Y,onPaneContextMenu:p,userSelectionActive:O,panOnScroll:m,panOnDrag:X,panOnScrollMode:v,panOnScrollSpeed:T,preventScrolling:S,zoomOnPinch:k,zoomOnScroll:I,zoomOnDoubleClick:b,zoomActivationKeyPressed:o,lib:s,onTransformChange:x,connectionInProgress:fu,paneClickDistance:$u,selectionOnDrag:tu}){if(O&&!A.isZoomingOrPanning)J();let ju=m&&!o&&!O;j.clickDistance(tu?1/0:!Er($u)||$u<0?0:$u);let Gu=ju?JV({zoomPanValues:A,noWheelClassName:V,d3Selection:F,d3Zoom:j,panOnScrollMode:v,panOnScrollSpeed:T,zoomOnPinch:k,onPanZoomStart:y,onPanZoom:i,onPanZoomEnd:_}):UV({noWheelClassName:V,preventScrolling:S,d3ZoomHandler:U});if(F.on("wheel.zoom",Gu,{passive:!1}),!O){let P=QV({zoomPanValues:A,onDraggingChange:$,onPanZoomStart:y});j.on("start",P);let e=qV({zoomPanValues:A,panOnDrag:X,onPaneContextMenu:!!p,onPanZoom:i,onTransformChange:x});j.on("zoom",e);let uu=NV({zoomPanValues:A,panOnDrag:X,panOnScroll:m,onPaneContextMenu:p,onPanZoomEnd:_,onDraggingChange:$});j.on("end",uu)}let qu=WV({zoomActivationKeyPressed:o,panOnDrag:X,zoomOnScroll:I,panOnScroll:m,zoomOnDoubleClick:b,zoomOnPinch:k,userSelectionActive:O,noPanClassName:Y,noWheelClassName:V,lib:s,connectionInProgress:fu});if(j.filter(qu),b)F.on("dblclick.zoom",Q);else F.on("dblclick.zoom",null)}function J(){j.on("zoom",null)}async function N(V,Y,p){let O=Dc(V),m=j?.constrain()(O,Y,p);if(m)await L(m);return new Promise((X)=>X(m))}async function q(V,Y){let p=Dc(V);return await L(p,Y),new Promise((O)=>O(p))}function W(V){if(F){let Y=Dc(V),p=F.property("__zoom");if(p.k!==V.zoom||p.x!==V.x||p.y!==V.y)j?.transform(F,Y,null,{sync:!0})}}function z(){let V=F?q$(F.node()):{x:0,y:0,k:1};return{x:V.x,y:V.y,zoom:V.k}}function Z(V,Y){if(F)return new Promise((p)=>{j?.interpolate(Y?.interpolate==="linear"?_0:H1).scaleTo(Xc(F,Y?.duration,Y?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function H(V,Y){if(F)return new Promise((p)=>{j?.interpolate(Y?.interpolate==="linear"?_0:H1).scaleBy(Xc(F,Y?.duration,Y?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function E(V){j?.scaleExtent(V)}function D(V){j?.translateExtent(V)}function h(V){let Y=!Er(V)||V<0?0:V;j?.clickDistance(Y)}return{update:w,destroy:J,setViewport:q,setViewportConstrained:N,getViewport:z,scaleTo:Z,scaleBy:H,setScaleExtent:E,setTranslateExtent:D,syncViewport:W,setClickDistance:h}}var Yn;(function(u){u.Line="line",u.Handle="handle"})(Yn||(Yn={}));function LV({width:u,prevWidth:f,height:l,prevHeight:r,affectsX:n,affectsY:i}){let y=u-f,_=l-r,$=[y>0?1:y<0?-1:0,_>0?1:_<0?-1:0];if(y&&n)$[0]=$[0]*-1;if(_&&i)$[1]=$[1]*-1;return $}function sq(u){let f=u.includes("right")||u.includes("left"),l=u.includes("bottom")||u.includes("top"),r=u.includes("left"),n=u.includes("top");return{isHorizontal:f,isVertical:l,affectsX:r,affectsY:n}}function Hn(u,f){return Math.max(0,f-u)}function Bn(u,f){return Math.max(0,u-f)}function M6(u,f,l){return Math.max(0,f-u,u-l)}function aq(u,f){return u?!f:f}function wV(u,f,l,r,n,i,y,_){let{affectsX:$,affectsY:A}=f,{isHorizontal:c,isVertical:j}=f,F=c&&j,{xSnapped:U,ySnapped:Q}=l,{minWidth:L,maxWidth:w,minHeight:J,maxHeight:N}=r,{x:q,y:W,width:z,height:Z,aspectRatio:H}=u,E=Math.floor(c?U-u.pointerX:0),D=Math.floor(j?Q-u.pointerY:0),h=z+($?-E:E),V=Z+(A?-D:D),Y=-i[0]*z,p=-i[1]*Z,O=M6(h,L,w),m=M6(V,J,N);if(y){let T=0,S=0;if($&&E<0)T=Hn(q+E+Y,y[0][0]);else if(!$&&E>0)T=Bn(q+h+Y,y[1][0]);if(A&&D<0)S=Hn(W+D+p,y[0][1]);else if(!A&&D>0)S=Bn(W+V+p,y[1][1]);O=Math.max(O,T),m=Math.max(m,S)}if(_){let T=0,S=0;if($&&E>0)T=Bn(q+E,_[0][0]);else if(!$&&E<0)T=Hn(q+h,_[1][0]);if(A&&D>0)S=Bn(W+D,_[0][1]);else if(!A&&D<0)S=Hn(W+V,_[1][1]);O=Math.max(O,T),m=Math.max(m,S)}if(n){if(c){let T=M6(h/H,J,N)*H;if(O=Math.max(O,T),y){let S=0;if(!$&&!A||$&&!A&&F)S=Bn(W+p+h/H,y[1][1])*H;else S=Hn(W+p+($?E:-E)/H,y[0][1])*H;O=Math.max(O,S)}if(_){let S=0;if(!$&&!A||$&&!A&&F)S=Hn(W+h/H,_[1][1])*H;else S=Bn(W+($?E:-E)/H,_[0][1])*H;O=Math.max(O,S)}}if(j){let T=M6(V*H,L,w)/H;if(m=Math.max(m,T),y){let S=0;if(!$&&!A||A&&!$&&F)S=Bn(q+V*H+Y,y[1][0])/H;else S=Hn(q+(A?D:-D)*H+Y,y[0][0])/H;m=Math.max(m,S)}if(_){let S=0;if(!$&&!A||A&&!$&&F)S=Hn(q+V*H,_[1][0])/H;else S=Bn(q+(A?D:-D)*H,_[0][0])/H;m=Math.max(m,S)}}}if(D=D+(D<0?m:-m),E=E+(E<0?O:-O),n)if(F)if(h>V*H)D=(aq($,A)?-E:E)/H;else E=(aq($,A)?-D:D)*H;else if(c)D=E/H,A=$;else E=D*H,$=A;let X=$?q+E:q,v=A?W+D:W;return{width:z+($?-E:E),height:Z+(A?-D:D),x:i[0]*E*(!$?1:-1)+X,y:i[1]*D*(!A?1:-1)+v}}var zN={width:0,height:0,x:0,y:0},KV={...zN,pointerX:0,pointerY:0,aspectRatio:1};function GV(u){return[[0,0],[u.measured.width,u.measured.height]]}function zV(u,f,l){let r=f.position.x+u.position.x,n=f.position.y+u.position.y,i=u.measured.width??0,y=u.measured.height??0,_=l[0]*i,$=l[1]*y;return[[r-_,n-$],[r+i-_,n+y-$]]}function TN({domNode:u,nodeId:f,getStoreItems:l,onChange:r,onEnd:n}){let i=af(u),y={controlDirection:sq("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function _({controlPosition:A,boundaries:c,keepAspectRatio:j,resizeDirection:F,onResizeStart:U,onResize:Q,onResizeEnd:L,shouldResize:w}){let J={...zN},N={...KV};y={boundaries:c,resizeDirection:F,keepAspectRatio:j,controlDirection:sq(A)};let q=void 0,W=null,z=[],Z=void 0,H=void 0,E=void 0,D=!1,h=u$().on("start",(V)=>{let{nodeLookup:Y,transform:p,snapGrid:O,snapToGrid:m,nodeOrigin:X,paneDomNode:v}=l();if(q=Y.get(f),!q)return;W=v?.getBoundingClientRect()??null;let{xSnapped:T,ySnapped:S}=W$(V.sourceEvent,{transform:p,snapGrid:O,snapToGrid:m,containerBounds:W});if(J={width:q.measured.width??0,height:q.measured.height??0,x:q.position.x??0,y:q.position.y??0},N={...J,pointerX:T,pointerY:S,aspectRatio:J.width/J.height},Z=void 0,q.parentId&&(q.extent==="parent"||q.expandParent))Z=Y.get(q.parentId),H=Z&&q.extent==="parent"?GV(Z):void 0;z=[],E=void 0;for(let[k,I]of Y)if(I.parentId===f){if(z.push({id:k,position:{...I.position},extent:I.extent}),I.extent==="parent"||I.expandParent){let b=zV(I,q,I.origin??X);if(E)E=[[Math.min(b[0][0],E[0][0]),Math.min(b[0][1],E[0][1])],[Math.max(b[1][0],E[1][0]),Math.max(b[1][1],E[1][1])]];else E=b}}U?.(V,{...J})}).on("drag",(V)=>{let{transform:Y,snapGrid:p,snapToGrid:O,nodeOrigin:m}=l(),X=W$(V.sourceEvent,{transform:Y,snapGrid:p,snapToGrid:O,containerBounds:W}),v=[];if(!q)return;let{x:T,y:S,width:k,height:I}=J,b={},o=q.origin??m,{width:s,height:x,x:fu,y:$u}=wV(N,y.controlDirection,X,y.boundaries,y.keepAspectRatio,o,H,E),tu=s!==k,ju=x!==I,Gu=fu!==T&&tu,qu=$u!==S&&ju;if(!Gu&&!qu&&!tu&&!ju)return;if(Gu||qu||o[0]===1||o[1]===1){if(b.x=Gu?fu:J.x,b.y=qu?$u:J.y,J.x=b.x,J.y=b.y,z.length>0){let Wu=fu-T,g=$u-S;for(let Qu of z)Qu.position={x:Qu.position.x-Wu+o[0]*(s-k),y:Qu.position.y-g+o[1]*(x-I)},v.push(Qu)}}if(tu||ju)b.width=tu&&(!y.resizeDirection||y.resizeDirection==="horizontal")?s:J.width,b.height=ju&&(!y.resizeDirection||y.resizeDirection==="vertical")?x:J.height,J.width=b.width,J.height=b.height;if(Z&&q.expandParent){let Wu=o[0]*(b.width??0);if(b.x&&b.x{if(!D)return;L?.(V,{...J}),n?.({...J}),D=!1});i.call(h)}function $(){i.on(".drag",null)}return{update:_,destroy:$}}var mN=Pu(qf(),1),PN=Pu(XN(),1);var YN=(u)=>{let f,l=new Set,r=(c,j)=>{let F=typeof c==="function"?c(f):c;if(!Object.is(F,f)){let U=f;f=(j!=null?j:typeof F!=="object"||F===null)?F:Object.assign({},f,F),l.forEach((Q)=>Q(f,U))}},n=()=>f,$={setState:r,getState:n,getInitialState:()=>A,subscribe:(c)=>{return l.add(c),()=>l.delete(c)},destroy:()=>{l.clear()}},A=f=u(r,n,$);return $},SN=(u)=>u?YN(u):YN;var{useDebugValue:xV}=mN.default,{useSyncExternalStoreWithSelector:hV}=PN.default,bV=(u)=>u;function y9(u,f=bV,l){let r=hV(u.subscribe,u.getState,u.getServerState||u.getInitialState,f,l);return xV(r),r}var pN=(u,f)=>{let l=SN(u),r=(n,i=f)=>y9(l,n,i);return Object.assign(r,l),r},MN=(u,f)=>u?pN(u,f):pN;function zf(u,f){if(Object.is(u,f))return!0;if(typeof u!=="object"||u===null||typeof f!=="object"||f===null)return!1;if(u instanceof Map&&f instanceof Map){if(u.size!==f.size)return!1;for(let[r,n]of u)if(!Object.is(n,f.get(r)))return!1;return!0}if(u instanceof Set&&f instanceof Set){if(u.size!==f.size)return!1;for(let r of u)if(!f.has(r))return!1;return!0}let l=Object.keys(u);if(l.length!==Object.keys(f).length)return!1;for(let r of l)if(!Object.prototype.hasOwnProperty.call(f,r)||!Object.is(u[r],f[r]))return!1;return!0}var vV=Pu(j5(),1),r8=yu.createContext(null),kV=r8.Provider,tW=Fr.error001();function eu(u,f){let l=yu.useContext(r8);if(l===null)throw Error(tW);return y9(l,u,f)}function Zf(){let u=yu.useContext(r8);if(u===null)throw Error(tW);return yu.useMemo(()=>({getState:u.getState,setState:u.setState,subscribe:u.subscribe}),[u])}var CN={display:"none"},IV={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},AW="react-flow__node-desc",cW="react-flow__edge-desc",gV="react-flow__aria-live",sV=(u)=>u.ariaLiveMessage,aV=(u)=>u.ariaLabelConfig;function oV({rfId:u}){let f=eu(sV);return ru.jsx("div",{id:`${gV}-${u}`,"aria-live":"assertive","aria-atomic":"true",style:IV,children:f})}function dV({rfId:u,disableKeyboardA11y:f}){let l=eu(aV);return ru.jsxs(ru.Fragment,{children:[ru.jsx("div",{id:`${AW}-${u}`,style:CN,children:f?l["node.a11yDescription.default"]:l["node.a11yDescription.keyboardDisabled"]}),ru.jsx("div",{id:`${cW}-${u}`,style:CN,children:l["edge.a11yDescription.default"]}),!f&&ru.jsx(oV,{rfId:u})]})}var n8=yu.forwardRef(({position:u="top-left",children:f,className:l,style:r,...n},i)=>{let y=`${u}`.split("-");return ru.jsx("div",{className:Yf(["react-flow__panel",l,...y]),style:r,ref:i,...n,children:f})});n8.displayName="Panel";function eV({proOptions:u,position:f="bottom-right"}){if(u?.hideAttribution)return null;return ru.jsx(n8,{position:f,className:"react-flow__attribution","data-message":"Please only hide this attribution when you are subscribed to React Flow Pro: https://pro.reactflow.dev",children:ru.jsx("a",{href:"https://reactflow.dev",target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}var uD=(u)=>{let f=[],l=[];for(let[,r]of u.nodeLookup)if(r.selected)f.push(r.internals.userNode);for(let[,r]of u.edgeLookup)if(r.selected)l.push(r);return{selectedNodes:f,selectedEdges:l}},u8=(u)=>u.id;function fD(u,f){return zf(u.selectedNodes.map(u8),f.selectedNodes.map(u8))&&zf(u.selectedEdges.map(u8),f.selectedEdges.map(u8))}function lD({onSelectionChange:u}){let f=Zf(),{selectedNodes:l,selectedEdges:r}=eu(uD,fD);return yu.useEffect(()=>{let n={nodes:l,edges:r};u?.(n),f.getState().onSelectionChangeHandlers.forEach((i)=>i(n))},[l,r,u]),null}var rD=(u)=>!!u.onSelectionChangeHandlers;function nD({onSelectionChange:u}){let f=eu(rD);if(u||f)return ru.jsx(lD,{onSelectionChange:u});return null}var t9=typeof window<"u"?yu.useLayoutEffect:yu.useEffect,jW=[0,0],iD={x:0,y:0,zoom:1},yD=["nodes","edges","defaultNodes","defaultEdges","onConnect","onConnectStart","onConnectEnd","onClickConnectStart","onClickConnectEnd","nodesDraggable","autoPanOnNodeFocus","nodesConnectable","nodesFocusable","edgesFocusable","edgesReconnectable","elevateNodesOnSelect","elevateEdgesOnSelect","minZoom","maxZoom","nodeExtent","onNodesChange","onEdgesChange","elementsSelectable","connectionMode","snapGrid","snapToGrid","translateExtent","connectOnClick","defaultEdgeOptions","fitView","fitViewOptions","onNodesDelete","onEdgesDelete","onDelete","onNodeDrag","onNodeDragStart","onNodeDragStop","onSelectionDrag","onSelectionDragStart","onSelectionDragStop","onMoveStart","onMove","onMoveEnd","noPanClassName","nodeOrigin","autoPanOnConnect","autoPanOnNodeDrag","onError","connectionRadius","isValidConnection","selectNodesOnDrag","nodeDragThreshold","connectionDragThreshold","onBeforeDelete","debug","autoPanSpeed","ariaLabelConfig","zIndexMode"],RN=[...yD,"rfId"],_D=(u)=>({setNodes:u.setNodes,setEdges:u.setEdges,setMinZoom:u.setMinZoom,setMaxZoom:u.setMaxZoom,setTranslateExtent:u.setTranslateExtent,setNodeExtent:u.setNodeExtent,reset:u.reset,setDefaultNodesAndEdges:u.setDefaultNodesAndEdges}),xN={translateExtent:ly,nodeOrigin:jW,minZoom:0.5,maxZoom:2,elementsSelectable:!0,noPanClassName:"nopan",rfId:"1"};function $D(u){let{setNodes:f,setEdges:l,setMinZoom:r,setMaxZoom:n,setTranslateExtent:i,setNodeExtent:y,reset:_,setDefaultNodesAndEdges:$}=eu(_D,zf),A=Zf();t9(()=>{return $(u.defaultNodes,u.defaultEdges),()=>{c.current=xN,_()}},[]);let c=yu.useRef(xN);return t9(()=>{for(let j of RN){let F=u[j],U=c.current[j];if(F===U)continue;if(typeof u[j]>"u")continue;if(j==="nodes")f(F);else if(j==="edges")l(F);else if(j==="minZoom")r(F);else if(j==="maxZoom")n(F);else if(j==="translateExtent")i(F);else if(j==="nodeExtent")y(F);else if(j==="ariaLabelConfig")A.setState({ariaLabelConfig:nN(F)});else if(j==="fitView")A.setState({fitViewQueued:F});else if(j==="fitViewOptions")A.setState({fitViewOptions:F});else A.setState({[j]:F})}c.current=u},RN.map((j)=>u[j])),null}function hN(){if(typeof window>"u"||!window.matchMedia)return null;return window.matchMedia("(prefers-color-scheme: dark)")}function tD(u){let[f,l]=yu.useState(u==="system"?null:u);return yu.useEffect(()=>{if(u!=="system"){l(u);return}let r=hN(),n=()=>l(r?.matches?"dark":"light");return n(),r?.addEventListener("change",n),()=>{r?.removeEventListener("change",n)}},[u]),f!==null?f:hN()?.matches?"dark":"light"}var bN=typeof document<"u"?document:null;function z$(u=null,f={target:bN,actInsideInputWithModifier:!0}){let[l,r]=yu.useState(!1),n=yu.useRef(!1),i=yu.useRef(new Set([])),[y,_]=yu.useMemo(()=>{if(u!==null){let A=(Array.isArray(u)?u:[u]).filter((j)=>typeof j==="string").map((j)=>j.replace("+",` +`;function d5({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Bu("section",{className:`panel ${n||""}`},Bu("div",{className:"panel-head"},Bu("div",null,f?Bu("p",{className:"panel-eyebrow"},f):null,Bu(nf,{title:u,loading:i})),l?Bu("div",{className:"panel-actions"},l):null),Bu("div",{className:"panel-body"},r))}function qZ({title:u,data:f,onOpen:l,testId:r}){return Bu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function NZ({title:u,text:f}){return Bu("div",{className:"empty-state"},Bu("strong",null,u),Bu("span",null,f))}function BQ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function VQ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function DQ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function WZ(u){return u.filter((l)=>l?.id==="filebrowser"||String(l?.id||"").startsWith("filebrowser-")).sort((l,r)=>{let n=(i)=>i.providerId==="D518"?0:i.providerId==="D601"?1:i.id==="filebrowser"?2:3;return n(l)-n(r)||String(l.id).localeCompare(String(r.id))})}function LZ(u){if(u?.providerId==="D518")return"D518";return u?.providerId||u?.name||u?.id||"Unknown"}function wZ(u,f,l="/"){let r=l.startsWith("/")?l:`/${l}`;return`${u}/microservices/${encodeURIComponent(f)}/proxy${r}`}function KZ(u,f){return`${u}/microservices/${encodeURIComponent(f)}/health`}async function GZ(u,f=16000){let l=new AbortController,r=setTimeout(()=>l.abort(),f);try{return await Eu(u,{signal:l.signal,failureFields:[!1]})}finally{clearTimeout(r)}}function XQ(u){if(u?.providerId==="main-server")return"host / -> /srv";if(u?.providerId==="D601"||u?.providerId==="D518")return"WSL / + /mnt/c -> /srv";return"provider / -> /srv"}function It(u){return u?.status==="OK"||u?.ok===!0}function zZ({service:u,active:f,health:l,onSelect:r,onRaw:n}){let i=BQ(u),y=VQ(u),_=DQ(u),$=i.container||{},A=It(l?.body);return Bu("button",{type:"button",className:`filebrowser-target-card ${f?"active":""}`,"data-testid":`filebrowser-target-card-${u.id}`,onClick:r},Bu("span",{className:`status-badge ${A?"ok":i.providerStatus==="online"?"running":"warn"}`},A?"Health OK":i.providerStatus||"unknown"),Bu("strong",null,u.name||u.id),Bu("span",null,XQ(u)),Bu("code",null,`${y.nodeBindHost||"--"}:${y.nodePort||"--"}`),Bu("small",null,$.name?`${$.name} / ${$.state||"--"}`:`${_.composeService||"--"}`),Bu("span",{className:"filebrowser-card-raw",onClick:(c)=>{c.stopPropagation(),n(`${u.name} service`,u)}},"JSON"))}function YQ(u){try{return u?.contentDocument||u?.contentWindow?.document||null}catch{return null}}function uA(u){let f=YQ(u);if(f===null||f.head===null)return!1;let l=f.getElementById("unidesk-filebrowser-compact-style");if(l===null)l=f.createElement("style"),l.id="unidesk-filebrowser-compact-style",f.head.appendChild(l);if(l.textContent!==e5)l.textContent=e5;return!0}function TZ(u,f){let l=URL.createObjectURL(u),r=document.createElement("a");r.href=l,r.download=f,document.body.appendChild(r),r.click(),r.remove(),setTimeout(()=>URL.revokeObjectURL(l),2000)}function EZ(u,f){let l=YQ(u);if(l===null||l.documentElement===null)throw Error("无法访问 File Browser iframe 文档");uA(u);let r=Math.max(640,Math.ceil(u.clientWidth||l.documentElement.clientWidth||1280)),n=Math.max(480,Math.ceil(u.clientHeight||l.documentElement.clientHeight||720)),i=l.documentElement.cloneNode(!0);i.querySelectorAll("script, style, link[rel='stylesheet'], link[rel='preload'], link[rel='icon']").forEach((c)=>c.remove()),i.querySelectorAll("img").forEach((c)=>{c.removeAttribute("src"),c.removeAttribute("srcset")});let y=i.querySelector("head");if(y===null)y=l.createElement("head"),i.insertBefore(y,i.firstChild);let _=l.createElement("style");_.textContent=`${e5} +html,body{width:${r}px!important;min-height:${n}px!important;overflow:hidden!important;}`,y.appendChild(_);let $=new XMLSerializer().serializeToString(i),A=`${$}`;TZ(new Blob([A],{type:"image/svg+xml;charset=utf-8"}),f.replace(/\.png$/i,".svg"))}function SQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=WZ(Array.isArray(u)?u:[]),n=new URLSearchParams(window.location.search).get("target")||"",i=n==="filebrowser-d518"?"filebrowser":n,y=r.some((Z)=>Z.id===i)?i:r[0]?.id||"",[_,$]=o5(y),[A,c]=o5({loading:!1,refreshedAt:null,health:{},error:""}),[j,F]=o5({exporting:!1,message:"",error:""}),U=QZ(null),Q=r.find((Z)=>Z.id===_)||r[0]||null,L=BQ(Q),w=VQ(Q),J=DQ(Q),N=Q?A.health[Q.id]:null,q=Q?wZ(l,Q.id,"/"):"about:blank";a5(()=>{if(r.length===0)return;if(!_||!r.some((Z)=>Z.id===_))$(r[0].id)},[r.map((Z)=>Z.id).join(",")]),a5(()=>{let Z=0,H=setInterval(()=>{if(Z+=1,uA(U.current)||Z>=24)clearInterval(H)},500);return()=>clearInterval(H)},[q]),a5(()=>{if(r.length===0)return;let Z=!1;async function H(){c((h)=>({...h,loading:!0,error:""}));let D=await Promise.all(r.map(async(h)=>{try{let V=await GZ(KZ(l,h.id));return[h.id,{ok:!0,body:V}]}catch(V){return[h.id,{ok:!1,error:Zu(V,"File Browser health failed")}]}}));if(Z)return;c({loading:!1,refreshedAt:new Date().toISOString(),health:Object.fromEntries(D),error:""})}H();let E=setInterval(H,30000);return()=>{Z=!0,clearInterval(E)}},[r.map((Z)=>`${Z.id}:${Z.runtime?.providerStatus||""}`).join(","),l]);function W(Z){$(Z);let H=new URL(window.location.href);H.searchParams.set("target",Z),window.history.replaceState({},"",`${H.pathname}${H.search}`)}async function z(){if(j.exporting)return;F({exporting:!0,message:"",error:""});try{let Z=new Date().toISOString().replace(/[-:.TZ]/g,"").slice(0,14);await EZ(U.current,`unidesk-filebrowser-${Q?.id||"target"}-${Z}.png`),F({exporting:!1,message:"截图已导出",error:""})}catch(Z){F({exporting:!1,message:"",error:Zu(Z,"截图导出失败")})}}if(r.length===0)return Bu(NZ,{title:"File Browser 未登记",text:"请在 config.json 的 microservices 中登记 id=filebrowser 或 filebrowser-* 用户服务"});return Bu("div",{className:"filebrowser-page","data-testid":"filebrowser-page"},A.error?Bu(yf,{error:A.error,wide:!0}):null,Bu(d5,{title:"文件管理器",eyebrow:"File Browser / Host Files",loading:A.loading,actions:Bu("div",{className:"panel-actions"},Q?Bu("button",{type:"button",className:"ghost-btn",onClick:z,disabled:j.exporting,"data-testid":"filebrowser-export-screenshot"},j.exporting?"导出中...":"导出截图"):null,Q?Bu("a",{className:"ghost-btn",href:q,target:"_blank",rel:"noreferrer"},"新窗口打开"):null,Q?Bu(qZ,{title:"File Browser 当前目标",data:{service:Q,health:N},onOpen:f,testId:"raw-filebrowser-active"}):null)},Bu("div",{className:"filebrowser-hero"},Bu("div",null,Bu("span",{className:`status-badge ${It(N?.body)?"ok":"warn"}`},It(N?.body)?"Health OK":"Health Pending"),Bu("h3",null,Q?.name||"File Browser"),Bu("p",{className:"muted paragraph"},Q?.description||"通过 UniDesk 登录态代理访问,不开放 File Browser 公网端口。"),j.error?Bu("p",{className:"filebrowser-shot-error"},j.error):null,j.message?Bu("p",{className:"filebrowser-shot-ok"},j.message):null),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Provider"),Bu("strong",null,Q?.providerId||"--"),Bu("code",null,L.providerName||Q?.providerId||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Private Backend"),Bu("strong",null,`${w.nodeBindHost||"--"}:${w.nodePort||"--"}`),Bu("code",null,w.nodeBaseUrl||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Image"),Bu("strong",null,J.dockerfile||"filebrowser/filebrowser:v2.63.3"),Bu("code",null,J.commitId||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Mount"),Bu("strong",null,XQ(Q)),Bu("code",null,Q?.providerId==="main-server"?"/root, /var, /home":"/home, /mnt/c, /mnt/d")))),Bu(d5,{title:"浏览目标",eyebrow:`${r.length} host targets`,loading:A.loading},Bu("div",{className:"filebrowser-target-grid"},r.map((Z)=>Bu(zZ,{key:Z.id,service:Z,active:Z.id===Q?.id,health:A.health[Z.id],onSelect:()=>W(Z.id),onRaw:f})))),Bu(d5,{title:`${LZ(Q)} 文件视图`,eyebrow:N?.body?`Health ${It(N.body)?"OK":"UNKNOWN"} / ${A.refreshedAt?$f(A.refreshedAt):"--"}`:"Embedded WebUI",className:"filebrowser-frame-panel"},Bu("div",{className:"filebrowser-frame-shell"},Bu("div",{className:"filebrowser-frame-toolbar"},Bu("span",null,"BaseURL"),Bu("code",null,`/api/microservices/${Q?.id||"filebrowser"}/proxy`),Bu("span",null,"Root"),Bu("code",null,"/srv"),Bu("span",{className:"filebrowser-compact-note"},"Compact layout injected")),Bu("iframe",{ref:U,key:q,title:`${Q?.name||"File Browser"} WebUI`,src:q,className:"filebrowser-frame","data-testid":"filebrowser-frame",onLoad:(Z)=>uA(Z.currentTarget),sandbox:"allow-downloads allow-forms allow-modals allow-same-origin allow-scripts"}))))}var ot=Pu(Qf(),1);var Ju=ot.default.createElement,{useEffect:ZZ}=ot.default,OZ=ot.default.useState;function gt({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return Ju("span",{className:`status-badge ${l}`},f||u||"unknown")}function Zn({label:u,value:f,hint:l,tone:r}){return Ju("article",{className:`metric-card ${r||""}`},Ju("div",{className:"metric-label"},u),Ju("div",{className:"metric-value"},f),Ju("div",{className:"metric-hint"},l))}function st({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Ju("section",{className:`panel ${n||""}`},Ju("div",{className:"panel-head"},Ju("div",null,f?Ju("p",{className:"panel-eyebrow"},f):null,Ju(nf,{title:u,loading:i})),l?Ju("div",{className:"panel-actions"},l):null),Ju("div",{className:"panel-body"},r))}function at({title:u,data:f,onOpen:l,testId:r}){return Ju("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function fA({title:u,text:f}){return Ju("div",{className:"empty-state"},Ju("strong",null,u),Ju("span",null,f))}function HZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function BZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function VZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function T1(u,f){let l=u&&typeof u==="object"?u[f]:void 0;return Number.isFinite(Number(l))?String(l):"--"}function DZ(u){return(Array.isArray(u?.jobs)?u.jobs:[]).slice(0,40)}function XZ(u){return(Array.isArray(u?.drafts)?u.drafts:[]).slice(0,12)}function pQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((Q)=>Q.id==="findjob")||null,[n,i]=OZ({loading:!1,error:"",health:null,summary:null,jobs:null,drafts:null,refreshedAt:null});async function y(){if(!r)return;i((Q)=>({...Q,loading:!0,error:""}));try{let[Q,L,w,J]=await Promise.all([Eu(`${l}/microservices/findjob/health`),Eu(`${l}/microservices/findjob/proxy/api/summary`),Eu(`${l}/microservices/findjob/proxy/api/jobs?__unideskArrayLimit=jobs:40`),Eu(`${l}/microservices/findjob/proxy/api/drafts`)]);i({loading:!1,error:"",health:Q,summary:L,jobs:w,drafts:J,refreshedAt:new Date})}catch(Q){i((L)=>({...L,loading:!1,error:Zu(Q,"FindJob 加载失败")}))}}if(ZZ(()=>{y()},[r?.id,r?.runtime?.providerStatus]),!r)return Ju(fA,{title:"FindJob 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=findjob"});let _=HZ(r),$=VZ(r),A=BZ(r),c=n.summary||{},j=DZ(n.jobs),F=XZ(n.drafts),U=n.jobs?._unidesk?.arrayLimits?.jobs;return Ju("div",{className:"findjob-page","data-testid":"findjob-page"},Ju(st,{title:"FindJob 工作台",eyebrow:"D601 用户服务",loading:n.loading,actions:Ju("div",{className:"panel-actions"},Ju("button",{type:"button",className:"ghost-btn",onClick:y,disabled:n.loading,"data-testid":"findjob-refresh-button"},n.loading?"刷新中":"刷新"),Ju(at,{title:"FindJob 用户服务",data:r,onOpen:f,testId:"raw-findjob-service"}))},Ju("div",{className:"findjob-hero"},Ju("div",null,Ju("div",{className:"node-version-line"},Ju(gt,{status:_.providerStatus==="online"?"online":"warn"},_.providerStatus||"unknown"),Ju("span",null,r.providerId),Ju("span",null,A.public?"公网暴露":"仅 UniDesk frontend 代理访问")),Ju("p",{className:"muted paragraph"},r.description)),Ju("div",{className:"microservice-ref-card"},Ju("span",null,"Repo"),Ju("strong",null,$.url||"--"),Ju("code",null,$.commitId||"--")),Ju("div",{className:"microservice-ref-card"},Ju("span",null,"D601 Docker"),Ju("strong",null,`${A.nodeBindHost||"--"}:${A.nodePort||"--"}`),Ju("code",null,`${$.composeFile||"--"} / ${$.composeService||"--"}`))),Ju(yf,{error:n.error,wide:!0})),Ju("div",{className:"findjob-grid"},Ju(st,{title:"岗位指标",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Summary",loading:n.loading},Ju("div",{className:"metric-grid"},Ju(Zn,{label:"岗位总量",value:T1(c,"totalJobs"),hint:"tracked jobs",tone:"ok"}),Ju(Zn,{label:"原始岗位",value:T1(c,"rawJobs"),hint:"raw queue"}),Ju(Zn,{label:"已验证",value:T1(c,"verifiedJobs"),hint:"verified set"}),Ju(Zn,{label:"优先处理",value:T1(c,"prioritizedJobs"),hint:"prioritized"}),Ju(Zn,{label:"过期",value:T1(c,"staleJobs"),hint:"stale jobs",tone:"warn"}),Ju(Zn,{label:"无效",value:T1(c,"invalidJobs"),hint:"invalid jobs",tone:"warn"}),Ju(Zn,{label:"上海",value:T1(c,"shanghaiJobs"),hint:"city filter"}),Ju(Zn,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /api/health"})),Ju("div",{className:"panel-actions inline-actions"},Ju(at,{title:"FindJob Summary",data:c,onOpen:f,testId:"raw-findjob-summary"}))),Ju(st,{title:"近期岗位",eyebrow:U?`${U.returnedLength}/${U.originalLength} Preview`:`${j.length} Preview`,loading:n.loading},j.length===0?Ju(fA,{title:"暂无岗位预览",text:"等待 D601 findjob backend 返回 /api/jobs"}):Ju("div",{className:"table-wrap findjob-job-table"},Ju("table",null,Ju("thead",null,Ju("tr",null,Ju("th",null,"优先级"),Ju("th",null,"状态"),Ju("th",null,"单位"),Ju("th",null,"职位"),Ju("th",null,"城市"),Ju("th",null,"阶段"),Ju("th",null,"截止"),Ju("th",null,"证据"))),Ju("tbody",null,j.map((Q)=>Ju("tr",{key:Q.id},Ju("td",null,Ju(gt,{status:String(Q.priority||"").toLowerCase()||"unknown"},Q.priority||"--")),Ju("td",null,Ju(gt,{status:String(Q.status||"").toLowerCase()||"unknown"},Q.status||"--")),Ju("td",null,Q.organization_name||"--",Ju("code",null,Q.id||"--")),Ju("td",null,Q.display_title||Q.title||"--"),Ju("td",null,Q.display_city||Q.city||"--"),Ju("td",null,Q.workflow_stage||"--"),Ju("td",null,Q.deadline||"--"),Ju("td",null,Q.evidence_url?Ju("a",{href:Q.evidence_url,target:"_blank",rel:"noreferrer"},"打开"):Ju("span",{className:"muted"},"无"))))))),Ju("div",{className:"panel-actions inline-actions"},Ju(at,{title:"FindJob Jobs Preview",data:n.jobs,onOpen:f,testId:"raw-findjob-jobs"}))),Ju(st,{title:"草稿与报告",eyebrow:`${F.length} Drafts`,loading:n.loading},F.length===0?Ju(fA,{title:"暂无草稿",text:"D601 findjob backend 未返回 drafts"}):Ju("div",{className:"draft-list"},F.map((Q)=>Ju("article",{key:Q.id,className:"draft-card"},Ju("div",{className:"node-card-head"},Ju("strong",null,Q.id),Ju(gt,{status:Q.status},Q.status||"--")),Ju("div",{className:"docker-meta compact"},Ju("span",null,Q.workflow_stage||"--"),Ju("span",null,`jobs ${Q.counts?.jobs??0}`),Ju("span",null,`reports ${Q.counts?.reports??0}`)),Ju("span",null,Q.latestReportPath||"暂无报告"),Ju("code",null,Nu(Q.updated_at||Q.updatedAt))))),Ju("div",{className:"panel-actions inline-actions"},Ju(at,{title:"FindJob Drafts",data:n.drafts,onOpen:f,testId:"raw-findjob-drafts"})))))}var k_=Pu(Qf(),1);var C=k_.default.createElement,{useEffect:YZ}=k_.default,lA=k_.default.useState;function h_(u){let f=Number(u);return Number.isFinite(f)?`${Math.max(0,Math.min(100,f)).toFixed(1)}%`:"--"}function nA(u){if(u===null||u===void 0||u==="")return"--";let f=Number(u);if(!Number.isFinite(f))return"--";if(f<60)return`${Math.max(0,Math.round(f))}s`;if(f<3600)return`${Math.floor(f/60)}m ${Math.round(f%60)}s`;return`${Math.floor(f/3600)}h ${Math.floor(f%3600/60)}m`}function iA(u,f=2){let l=Number(u);if(!Number.isFinite(l))return u===!1?"false":u===!0?"true":"--";let r=Math.abs(l);if(Number.isInteger(l)||r>=1000)return l.toLocaleString("zh-CN",{maximumFractionDigits:0});if(r>=1)return l.toLocaleString("zh-CN",{maximumFractionDigits:f});return l.toLocaleString("zh-CN",{maximumFractionDigits:Math.max(f,6)})}function v_(u){if(u===null||u===void 0||u==="")return"--";if(typeof u==="boolean")return u?"true":"false";if(typeof u==="number")return iA(u,4);if(Array.isArray(u))return u.map((f)=>v_(f)).join(" x ");if(typeof u==="object")return"已上报";return String(u)}function dt(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=f>=100?0:f>=10?1:2;return`${f.toLocaleString("zh-CN",{maximumFractionDigits:l})} epoch/h`}function et(u){return u.replace(/[^a-zA-Z0-9_-]/g,"-")}function kl(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function b_({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return C("span",{className:`status-badge ${l}`},f||u||"unknown")}function On({label:u,value:f,hint:l,tone:r}){return C("article",{className:`metric-card ${r||""}`},C("div",{className:"metric-label"},u),C("div",{className:"metric-value"},f),C("div",{className:"metric-hint"},l))}function rA({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return C("section",{className:`panel ${n||""}`},C("div",{className:"panel-head"},C("div",null,f?C("p",{className:"panel-eyebrow"},f):null,C(nf,{title:u,loading:i})),l?C("div",{className:"panel-actions"},l):null),C("div",{className:"panel-body"},r))}function bi({title:u,data:f,onOpen:l,testId:r}){return C("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function S0({title:u,text:f}){return C("div",{className:"empty-state"},C("strong",null,u),C("span",null,f))}function SZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function pZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function mZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function PZ(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function MZ(u){return Array.isArray(u?.jobs)?u.jobs.slice(0,240):[]}function CZ(u){return Array.isArray(u?.projects)?u.projects.slice(0,1000):[]}function u6(u){return Array.isArray(u?.projects)?u.projects:[]}function RZ(u,f){if(Array.isArray(f?.gpu))return f.gpu;if(Array.isArray(u?.gpu))return u.gpu;return[]}function jr(u,f){return`${u}/microservices/met-nonlinear/proxy${f}`}function mQ(u){return u.startedAt&&u.finishedAt?nA((Date.parse(u.finishedAt)-Date.parse(u.startedAt))/1000):"--"}function xZ(u){let f=u.progress||{};if(f.etaSeconds!==null&&f.etaSeconds!==void 0&&f.etaSeconds!==""){let y=Number(f.etaSeconds);if(Number.isFinite(y))return Math.max(0,y)}let l=Number(f.currentEpoch),r=Number(f.epochTarget??u.epochTarget),n=Date.parse(u.startedAt||"");if(!Number.isFinite(l)||l<=0||!Number.isFinite(r)||r<=l||!Number.isFinite(n))return null;let i=Math.max(0,(Date.now()-n)/1000);if(i<=0)return null;return Math.max(0,i/l*(r-l))}function PQ(u){let f=u.progress||{},l=Number(f.epochPerHour);if(Number.isFinite(l)&&l>0)return l;let r=Date.parse(u.startedAt||""),n=["succeeded","failed","canceled"].includes(u.status)?Date.parse(u.finishedAt||""):Date.now();if(!Number.isFinite(r)||!Number.isFinite(n)||n<=r)return null;let i=Number(f.currentEpoch??u.epochTarget);if(!Number.isFinite(i)||i<=0)return null;return i/((n-r)/3600000)}function MQ(u){if(u==="staged")return"待启动";if(u==="queued")return"排队中";if(u==="running")return"训练中";if(u==="succeeded")return"已完成";if(u==="failed")return"失败";if(u==="canceled")return"已取消";return u||"unknown"}function CQ(u,f,l){return{name:u,path:f,depth:l,count:0,children:[],project:null}}function hZ(u){let f=CQ("","",-1);for(let r of u){let i=String(r?.projectPath||"").replace(/\\/g,"/").split("/").filter(Boolean);if(i.length===0)continue;let y=f,_=[];for(let[$,A]of i.entries()){_.push(A);let c=_.join("/"),j=y.children.find((F)=>F.path===c);if(!j)j=CQ(A,c,$),y.children.push(j);if($===i.length-1)j.project=r;y=j}}let l=(r)=>{let n=r.children.reduce((i,y)=>i+l(y),0);return r.count=(r.project?1:0)+n,r.children.sort((i,y)=>{if(Boolean(i.project)!==Boolean(y.project))return i.project?1:-1;return i.name.localeCompare(y.name,"zh-CN",{numeric:!0,sensitivity:"base"})}),r.count};return l(f),f}function bZ(u){let f=kl(u.data);return kl(f.project).projectPath?kl(f.project):f}function vZ(u){return kl(kl(u.data).job)}function RQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((P)=>P.id==="met-nonlinear")||null,[n,i]=lA({loading:!1,actionBusy:!1,error:"",health:null,summary:null,queue:null,projects:null,history:null,images:null,refreshedAt:null}),[y,_]=lA({loading:!1,error:"",kind:"",key:"",title:"",data:null}),[$,A]=lA(()=>({activeTab:"projects",selectedProjects:{},expandedProjectDirs:{},sourceProject:"",forkCount:1,forkEpochs:200,forkPrefix:`ui_fork_${Date.now()}`,maxConcurrency:3,targetGpuName:"2080 Ti",actionMessage:""}));function c(P){A((e)=>({...e,...P}))}async function j(P=$.activeTab){if(!r)return;i((e)=>({...e,loading:!0,error:""}));try{let e=[["health",Eu(`${l}/microservices/met-nonlinear/health`)],["summary",Eu(jr(l,"/api/summary"))]];if(P==="projects")e.push(["projectsRoot",Eu(jr(l,"/api/projects?root=projects&limit=500"))]),e.push(["exProjectsRoot",Eu(jr(l,"/api/projects?root=ex_projects&limit=500"))]);if(P==="current"||P==="completed"||P==="failed")e.push(["queue",Eu(jr(l,"/api/queue"))]);if(P==="completed"||P==="failed")e.push(["history",Eu(jr(l,"/api/history"))]);if(P==="gpu")e.push(["images",Eu(jr(l,"/api/images"))]);let uu=Object.fromEntries(await Promise.all(e.map(async([s,Qu])=>[s,await Qu]))),wu={loading:!1,actionBusy:!1,error:"",health:uu.health,summary:uu.summary,refreshedAt:new Date};if(uu.projectsRoot||uu.exProjectsRoot){let{projectsRoot:s,exProjectsRoot:Qu}=uu;wu.projects={ok:s?.ok!==!1&&Qu?.ok!==!1,roots:[{root:"projects",count:u6(s).length},{root:"ex_projects",count:u6(Qu).length}],projects:[...u6(s),...u6(Qu)]}}if(uu.queue)wu.queue=uu.queue;if(uu.history)wu.history=uu.history;if(uu.images)wu.images=uu.images;i((s)=>({...s,...wu}))}catch(e){i((uu)=>({...uu,loading:!1,actionBusy:!1,error:Zu(e,"MET Nonlinear 加载失败")}))}}async function F(P,e){i((uu)=>({...uu,actionBusy:!0,error:""})),c({actionMessage:`${P}...`});try{let uu=await e();c({actionMessage:uu||`${P}完成`}),await j()}catch(uu){i((wu)=>({...wu,actionBusy:!1,error:Zu(uu,`${P}失败`)}))}}async function U(){await F("保存并发设置",async()=>{await Eu(jr(l,"/api/queue/settings"),{method:"PUT",body:JSON.stringify({maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName})})})}function Q(){return Object.entries($.selectedProjects).filter(([,P])=>P).map(([P])=>P)}async function L(){let P=Q();if(P.length===0)throw Error("请先选择至少一个 project");await F("加入待启动队列",async()=>{await Eu(jr(l,"/api/queue"),{method:"POST",body:JSON.stringify({projectPaths:P,maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName,start:!1})}),c({activeTab:"current",selectedProjects:{}})})}async function w(){let P=$.sourceProject||p[0]?.projectPath;if(!P)throw Error("请先选择源 project");await F("Fork Project",async()=>{let e=await Eu(jr(l,"/api/projects/fork"),{method:"POST",body:JSON.stringify({sourceProject:P,count:Number($.forkCount),epochs:Number($.forkEpochs),prefix:$.forkPrefix})}),uu=Array.isArray(e.projectPaths)?e.projectPaths:[],wu=uu.reduce((s,Qu)=>{return s[Qu]=!0,s},{...$.selectedProjects});return c({selectedProjects:wu}),`已 fork ${uu.length} 个 project,并已自动勾选;请确认后点击加入待启动队列。`})}async function J(){await F("启动队列",async()=>{await Eu(jr(l,"/api/queue/start"),{method:"POST",body:JSON.stringify({maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName})}),c({activeTab:"current"})})}async function N(P){await F("取消任务",async()=>{await Eu(jr(l,`/api/jobs/${encodeURIComponent(P.id)}/cancel`),{method:"POST",body:JSON.stringify({})})})}async function q(P){let e=String(P?.projectPath||"");if(!e)return;_({loading:!0,error:"",kind:"project",key:e,title:e,data:null});try{let uu=await Eu(jr(l,`/api/projects/config?path=${encodeURIComponent(e)}`));_({loading:!1,error:"",kind:"project",key:e,title:e,data:uu})}catch(uu){_({loading:!1,error:Zu(uu,"Project 详情加载失败"),kind:"project",key:e,title:e,data:null})}}async function W(P){let e=String(P?.id||"");if(!e)return;_({loading:!0,error:"",kind:"job",key:e,title:P.projectPath||e,data:null});try{let uu=await Eu(jr(l,`/api/jobs/${encodeURIComponent(e)}`));_({loading:!1,error:"",kind:"job",key:e,title:uu?.job?.projectPath||P.projectPath||e,data:uu})}catch(uu){_({loading:!1,error:Zu(uu,"Job 详情加载失败"),kind:"job",key:e,title:P.projectPath||e,data:null})}}if(YZ(()=>{j($.activeTab)},[r?.id,r?.runtime?.providerStatus,$.activeTab]),!r)return C(S0,{title:"MET Nonlinear 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=met-nonlinear"});let z=SZ(r),Z=mZ(r),H=pZ(r),E=PZ(n.queue?.queue||n.summary?.queue),D=RZ(n.health,n.queue),h=n.health?.targetGpu||n.summary?.targetGpu||D.find((P)=>String(P.name||"").includes("2080")),V=n.images?.mlImage||n.health?.image||{},Y=MZ(n.queue),p=CZ(n.projects),O=hZ(p),m=$.sourceProject||p[0]?.projectPath||"",X=Y.filter((P)=>["staged","queued","running"].includes(P.status)),v=Y.filter((P)=>P.status==="succeeded"),T=Y.filter((P)=>["failed","canceled"].includes(P.status)),S=Array.isArray(n.history?.jobs)?n.history.jobs.slice(0,120):[],k=[{id:"projects",label:"项目库",count:p.length},{id:"current",label:"当前队列",count:X.length||Number(E.staged||0)+Number(E.queued||0)+Number(E.running||0)},{id:"completed",label:"已完成",count:v.length||Number(E.succeeded||0)},{id:"failed",label:"失败诊断",count:T.length||Number(E.failed||0)+Number(E.canceled||0)},{id:"gpu",label:"GPU/镜像",count:D.length}];function I(P,e){if(P.length===0)return C(S0,{title:e==="current"?"当前队列为空":"暂无记录",text:e==="current"?"从项目库选择或 fork project 后先加入待启动队列,再启动队列。":"终态任务会显示耗时、exit code 和失败诊断。"});return C("div",{className:"table-wrap met-job-table"},C("table",null,C("thead",null,C("tr",null,C("th",null,"状态"),C("th",null,"Project"),C("th",null,"Epoch"),C("th",null,"速度"),C("th",null,"ETA/耗时"),C("th",null,"GPU"),C("th",null,"Exit"),C("th",null,"更新时间"),C("th",null,"操作"))),C("tbody",null,P.map((uu)=>{let wu=uu.progress||{},s=["staged","queued","running"].includes(uu.status),Qu=y.kind==="job"&&y.key===uu.id;return C("tr",{key:uu.id,className:`met-click-row ${Qu?"active":""}`,onClick:()=>W(uu),"data-testid":`met-job-row-${et(uu.id)}`},C("td",null,C(b_,{status:uu.status},MQ(uu.status))),C("td",null,C("button",{type:"button",className:"met-inline-link",onClick:(zu)=>{zu.stopPropagation(),W(uu)}},uu.projectPath),C("code",null,uu.id)),C("td",null,C("span",null,`${wu.currentEpoch??"--"} / ${wu.epochTarget??uu.epochTarget??"--"}`),C("div",{className:"met-progress"},C("span",{style:{width:h_(wu.progressPercent)}}))),C("td",null,C("strong",null,dt(PQ(uu)))),C("td",null,uu.status==="succeeded"||uu.status==="failed"||uu.status==="canceled"?mQ(uu):uu.status==="running"?`ETA ${nA(xZ(uu))}`:"--"),C("td",null,uu.gpuName||"--"),C("td",null,uu.exitCode??"--"),C("td",null,Nu(uu.updatedAt)),C("td",null,s?C("button",{type:"button",className:"ghost-btn mini",onClick:(zu)=>{zu.stopPropagation(),N(uu)},disabled:n.actionBusy},"取消"):null,C(bi,{title:`MET Job ${uu.id}`,data:uu,onOpen:f,testId:`raw-met-job-${uu.id}`})))}))))}function b(){return C("div",{className:"met-queue-summary","data-testid":"met-current-summary"},C(b_,{status:"staged"},`待启动 ${E.staged??0}`),C(b_,{status:"queued"},`排队中 ${E.queued??0}`),C(b_,{status:"running"},`训练中 ${E.running??0}`),C("span",null,`最大并发 ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??$.maxConcurrency}`),C("span",null,`目标 GPU ${n.summary?.queue?.targetGpuName??n.queue?.queue?.targetGpuName??$.targetGpuName}`))}function o(P,e){let uu=$.expandedProjectDirs[P];return uu===void 0?e<2:Boolean(uu)}function g(P,e){let uu=o(P,e);c({expandedProjectDirs:{...$.expandedProjectDirs,[P]:!uu}})}function x(P){let e=8+Math.max(0,P.depth)*16;if(Boolean(P.project)){let s=P.project,Qu=Boolean($.selectedProjects[s.projectPath]),zu=y.kind==="project"&&y.key===s.projectPath;return C("div",{key:P.path,className:`met-tree-row project ${Qu?"selected":""} ${zu?"active":""}`,style:{paddingLeft:e},onClick:()=>q(s),"data-testid":`met-project-node-${et(s.projectPath)}`},C("div",{className:"met-tree-name"},C("input",{type:"checkbox",checked:Qu,onClick:(Ou)=>Ou.stopPropagation(),onChange:(Ou)=>c({selectedProjects:{...$.selectedProjects,[s.projectPath]:Ou.target.checked}}),"data-testid":`met-project-checkbox-${et(s.projectPath)}`}),C("button",{type:"button",className:"met-inline-link project-path",onClick:(Ou)=>{Ou.stopPropagation(),q(s)}},P.name)),C("span",null,s.useModel||"--"),C("span",null,s.epochTrain??"--"),C("span",null,h_(s.progress?.progressPercent)),C("span",null,dt(s.progress?.epochPerHour)))}let wu=o(P.path,P.depth);return C(k_.default.Fragment,{key:P.path},C("div",{className:"met-tree-row folder",style:{paddingLeft:e},"data-testid":`met-project-folder-${et(P.path)}`},C("button",{type:"button",className:"met-tree-toggle",onClick:()=>g(P.path,P.depth),"aria-label":wu?`折叠 ${P.path}`:`展开 ${P.path}`},wu?"-":"+"),C("strong",null,P.name),C("span",{className:"met-tree-count"},`${P.count} projects`)),wu?P.children.map((s)=>x(s)):null)}function fu(P){return C("div",{className:"met-detail-kv"},P.map((e)=>C("div",{key:e.label,className:"met-detail-kv-item"},C("span",null,e.label),C("strong",null,v_(e.value)),e.hint?C("small",null,e.hint):null)))}function $u(P,e){return C("div",{className:"met-detail-section"},C("h3",null,P),fu(e))}function tu(P){if(!Array.isArray(P)||P.length===0)return C(S0,{title:"模型层未上报",text:"等待 data/model_info.json 或 compute_analysis.json 生成。"});return C("div",{className:"table-wrap met-layer-table"},C("table",null,C("thead",null,C("tr",null,C("th",null,"Layer"),C("th",null,"Type"),C("th",null,"Params"),C("th",null,"Trainable"),C("th",null,"Compute"))),C("tbody",null,P.slice(0,18).map((e,uu)=>C("tr",{key:`${e.name||"layer"}-${uu}`},C("td",null,e.name||`#${uu+1}`),C("td",null,e.type||"--"),C("td",null,iA(e.num_params)),C("td",null,e.trainable===void 0?"--":String(Boolean(e.trainable))),C("td",null,iA(e.compute?.total??e.estimated_cost?.weighted_units?.total)))))))}function ju(P){let e=Array.isArray(P)?P:[];if(e.length===0)return C(S0,{title:"data/ 暂无文件",text:"训练或评估完成后会生成 training_state、metrics、model_info 等文件。"});return C("div",{className:"met-file-chip-grid"},e.slice(0,48).map((uu)=>C("span",{key:uu},uu)),e.length>48?C("span",null,`+${e.length-48}`):null)}function Gu(P){let e=String(P||"").replace(/\x1b\[[0-9;]*[A-Za-z]/g,"").split(/\r?\n/).map((uu)=>uu.trim()).filter(Boolean).slice(-12);if(e.length===0)return C(S0,{title:"暂无日志尾部",text:"该任务未上报 logTail 或日志已轮转。"});return C("div",{className:"met-log-lines"},e.map((uu,wu)=>C("div",{key:`${wu}-${uu.slice(0,16)}`},uu)))}function qu(){if(y.loading)return C("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},C("div",{className:"panel-head compact"},C("div",null,C("p",{className:"panel-eyebrow"},"Detail Loading"),C(nf,{title:"详情加载中",loading:!0}))),C(S0,{title:"详情加载中",text:y.title||"正在读取 D601 data/ 和 config.json"}));if(y.error)return C("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},C(yf,{error:y.error,wide:!0}));if(!y.data)return C("section",{className:"met-detail-panel muted","data-testid":"met-detail-panel"},C(S0,{title:"选择一个项目或任务查看详情",text:"项目库、当前队列、已完成和失败诊断中的行都可以点击;默认只展示结构化字段,原始 JSON 需显式点击按钮。"}));let P=bZ(y),e=vZ(y),uu=kl(P.config),wu=kl(P.progress||e.progress),s=kl(P.data),Qu=kl(P.metrics||s.metrics||wu.trainingInfo?.evaluation_metrics),zu=kl(s.trainingInfo||wu.trainingInfo),Ou=kl(s.trainingState),bu=kl(P.model||s.model),eu=Array.isArray(bu.modelSummary)&&bu.modelSummary.length>0?bu.modelSummary:bu.computeLayers,pu=kl(zu.evaluation_metrics),Ff=y.kind==="job"?"训练任务详情":"Project 详情";return C("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},C("div",{className:"panel-head compact"},C("div",null,C("p",{className:"panel-eyebrow"},y.kind==="job"?"Job + Project Detail":"Project Library Detail"),C(nf,{title:Ff}),C("code",null,P.projectPath||e.projectPath||y.title)),C("div",{className:"panel-actions"},C(bi,{title:`MET ${Ff}`,data:y.data,onOpen:f,testId:"raw-met-detail"}))),y.kind==="job"?$u("任务状态",[{label:"Job ID",value:e.id},{label:"状态",value:MQ(e.status)},{label:"GPU",value:e.gpuName},{label:"Exit Code",value:e.exitCode},{label:"耗时",value:mQ(e)},{label:"训练速度",value:dt(PQ({...e,progress:wu}))}]):null,$u("config.json",[{label:"use_model",value:uu.use_model},{label:"epoch_train",value:uu.epoch_train},{label:"step_per_epoch",value:uu.step_per_epoch},{label:"learning_rate",value:uu.learning_rate},{label:"using_gpu",value:uu.using_gpu},{label:"use_points",value:uu.use_points},{label:"sample_rate",value:uu.sample_rate},{label:"time_clipped_s",value:uu.time_clipped_s},{label:"H_UNITS",value:uu.H_UNITS},{label:"INNER_KAN_UNITS",value:uu.INNER_KAN_UNITS},{label:"INNER_KAN_LAYERS",value:uu.INNER_KAN_LAYERS},{label:"GRID_SIZE",value:uu.GRID_SIZE},{label:"SPLINE_ORDER",value:uu.SPLINE_ORDER},{label:"USE_FAST_MODEL",value:uu.USE_FAST_MODEL},{label:"IIR_TRAINABLE",value:uu.IIR_TRAINABLE}]),$u("data/ 训练状态",[{label:"Epoch",value:`${wu.currentEpoch??Ou.current_epoch??Ou.completed_epoch??"--"} / ${wu.epochTarget??uu.epoch_train??"--"}`},{label:"Progress",value:h_(wu.progressPercent)},{label:"Last Loss",value:wu.lastLoss??Ou.loss},{label:"Last Val Loss",value:wu.lastValLoss??Ou.val_loss},{label:"Min Loss",value:zu.min_loss??Ou.min_loss},{label:"Min Val Loss",value:zu.min_val_loss??Ou.min_val_loss},{label:"Log Lines",value:wu.logLineCount},{label:"ETA",value:nA(wu.etaSeconds??Ou.remaining_time)},{label:"训练速度",value:dt(wu.epochPerHour??Ou.smoothed_speed)},{label:"Training Alive",value:Ou.training_alive}]),$u("模型参数",[{label:"Model Type",value:bu.modelType??uu.use_model},{label:"Total Params",value:bu.totalParams,hint:bu.totalParams===null||bu.totalParams===void 0?"未上报":"data/model_info.json"},{label:"Trainable",value:bu.trainableParams},{label:"Non-trainable",value:bu.nonTrainableParams},{label:"Compute Cost",value:bu.computeCost},{label:"Estimate Status",value:bu.estimateStatus},{label:"Unsupported Layers",value:bu.unsupportedLayerCount}]),$u("指标",[{label:"train_loss",value:Qu.train_loss??pu.train_loss},{label:"val_loss",value:Qu.val_loss??pu.val_loss},{label:"train_mae",value:Qu.train_mae??pu.train_mae},{label:"val_mae",value:Qu.val_mae??pu.val_mae},{label:"train_afmae",value:Qu.train_afmae??pu.train_afmae},{label:"val_afmae",value:Qu.val_afmae??pu.val_afmae},{label:"freq_drift_hz",value:Qu.freq_drift_hz},{label:"sens_drift_percent",value:Qu.sens_drift_percent},{label:"linearity_percent",value:Qu.linearity_percent},{label:"weights_source",value:Qu.weights_source??pu.weights_source},{label:"lr min/mean/max",value:`${v_(zu.learning_rate_min)} / ${v_(zu.learning_rate_mean)} / ${v_(zu.learning_rate_max)}`}]),C("div",{className:"met-detail-section"},C("h3",null,"模型层"),tu(eu)),C("div",{className:"met-detail-section"},C("h3",null,"data/ 文件"),ju(s.files)),y.kind==="job"?C("div",{className:"met-detail-section"},C("h3",null,"日志尾部"),Gu(kl(y.data).logTail)):null)}return C("div",{className:"met-page","data-testid":"met-nonlinear-page"},C(rA,{title:"MET Nonlinear 训练编排",eyebrow:"D601 GPU 用户服务",loading:n.loading||n.actionBusy,actions:C("div",{className:"panel-actions"},C("button",{type:"button",className:"ghost-btn",onClick:j,disabled:n.loading,"data-testid":"met-refresh-button"},n.loading?"刷新中":"刷新"),C(bi,{title:"MET Nonlinear 用户服务",data:r,onOpen:f,testId:"raw-met-service"}))},C("div",{className:"findjob-hero"},C("div",null,C("div",{className:"node-version-line"},C(b_,{status:z.providerStatus==="online"?"online":"warn"},z.providerStatus||"unknown"),C("span",null,r.providerId),C("span",null,H.public?"公网暴露":"仅 UniDesk frontend 代理访问")),C("p",{className:"muted paragraph"},r.description)),C("div",{className:"microservice-ref-card"},C("span",null,"Repo"),C("strong",null,Z.url||"--"),C("code",null,Z.commitId||"--")),C("div",{className:"microservice-ref-card"},C("span",null,"D601 Docker"),C("strong",null,`${H.nodeBindHost||"--"}:${H.nodePort||"--"}`),C("code",null,`${Z.composeFile||"--"} / ${Z.containerName||"--"}`))),C(yf,{error:n.error,wide:!0}),$.actionMessage?C("div",{className:"met-action-log","data-testid":"met-action-message"},$.actionMessage):null),C("div",{className:"met-grid"},C(rA,{title:"核心状态",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Queue + GPU",loading:n.loading},C("div",{className:"metric-grid"},C(On,{label:"Staged",value:E.staged??0,hint:"加入队列未开始",tone:Number(E.staged||0)>0?"warn":""}),C(On,{label:"Queued",value:E.queued??0,hint:"排队等待调度",tone:Number(E.queued||0)>0?"warn":""}),C(On,{label:"Running",value:E.running??0,hint:`max ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??"--"}`,tone:Number(E.running||0)>0?"ok":""}),C(On,{label:"Succeeded",value:E.succeeded??0,hint:"已完成"}),C(On,{label:"Failed",value:E.failed??0,hint:"需要诊断",tone:Number(E.failed||0)>0?"warn":""}),C(On,{label:"2080Ti Free",value:h?h_(Number(h.freeRatio)*100):"--",hint:h?`${h.memoryFreeMiB}/${h.memoryTotalMiB} MiB`:"等待 GPU 上报"}),C(On,{label:"ML Image",value:V.present?"READY":"MISSING",hint:V.image||"met-nonlinear-ml:tf26",tone:V.present?"ok":"warn"}),C(On,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /health"}))),C(rA,{title:"队列控制",eyebrow:"Downloader-like staging",loading:n.actionBusy},C("div",{className:"met-control-strip"},C("label",null,"最大并发",C("input",{type:"number",min:1,max:16,value:$.maxConcurrency,"data-testid":"met-max-concurrency-input",onChange:(P)=>c({maxConcurrency:P.target.value})})),C("label",null,"目标 GPU",C("input",{value:$.targetGpuName,"data-testid":"met-target-gpu-input",onChange:(P)=>c({targetGpuName:P.target.value})})),C("button",{type:"button",className:"ghost-btn",onClick:U,disabled:n.actionBusy,"data-testid":"met-save-settings-button"},"保存设置"),C("button",{type:"button",className:"primary-btn",onClick:J,disabled:n.actionBusy||Number(E.staged||0)===0,"data-testid":"met-start-queue-button"},"启动队列")),C("p",{className:"muted paragraph"},"Project 先进入待启动队列,不会立即训练;点击启动队列后才切换为排队中,并由 D601 scheduler 按最大并发和 2080Ti 显存策略调度。")),C("section",{className:"panel met-workspace"},C("div",{className:"met-tabs",role:"tablist"},k.map((P)=>C("button",{key:P.id,type:"button",className:$.activeTab===P.id?"active":"",onClick:()=>c({activeTab:P.id}),"data-testid":`met-tab-${P.id}`},`${P.label} ${P.count}`))),C("div",{className:"panel-body"},$.activeTab==="projects"?C("div",{className:"met-form-grid","data-testid":"met-projects-pane"},C("div",{className:"met-fork-card"},C("h3",null,"Fork Project"),C("label",null,"源 Project",C("select",{value:m,"data-testid":"met-source-project-select",onChange:(P)=>c({sourceProject:P.target.value})},p.map((P)=>C("option",{key:P.projectPath,value:P.projectPath},`${P.projectPath} · ${P.useModel||"model?"}`)))),C("label",null,"Fork 数量",C("input",{type:"number",min:1,max:100,value:$.forkCount,"data-testid":"met-fork-count-input",onChange:(P)=>c({forkCount:P.target.value})})),C("label",null,"训练轮数",C("input",{type:"number",min:1,max:1e5,value:$.forkEpochs,"data-testid":"met-fork-epochs-input",onChange:(P)=>c({forkEpochs:P.target.value})})),C("label",null,"目标前缀",C("input",{value:$.forkPrefix,"data-testid":"met-fork-prefix-input",onChange:(P)=>c({forkPrefix:P.target.value})})),C("button",{type:"button",className:"primary-btn",onClick:w,disabled:n.actionBusy||!m,"data-testid":"met-fork-button"},"Fork Project"),C("p",{className:"muted paragraph"},"Fork 只创建新 Project 并自动勾选,不会直接训练;需要在右侧确认后加入待启动队列。")),C("div",{className:"met-project-list"},C("div",{className:"panel-head compact"},C("div",null,C("p",{className:"panel-eyebrow"},`Existing Projects · ${(n.projects?.roots||[]).map((P)=>`${P.root} ${P.count}`).join(" / ")}`),C(nf,{title:"选择已有 Project",loading:n.loading||n.actionBusy})),C("button",{type:"button",className:"ghost-btn",onClick:L,disabled:n.actionBusy||Q().length===0,"data-testid":"met-stage-selected-button"},`加入待启动队列 (${Q().length})`)),p.length===0?C(S0,{title:"暂无 project",text:"等待 D601 返回 /api/projects"}):C("div",{className:"met-project-table","data-testid":"met-project-tree"},C("div",{className:"met-tree-header"},C("span",null,"文件树 Project"),C("span",null,"Model"),C("span",null,"Epochs"),C("span",null,"Progress"),C("span",null,"速度")),O.children.map((P)=>x(P)))),qu()):null,$.activeTab==="current"?C("div",{"data-testid":"met-current-pane"},b(),I(X,"current"),qu(),C("div",{className:"panel-actions inline-actions"},C(bi,{title:"MET Queue",data:n.queue,onOpen:f,testId:"raw-met-queue"}))):null,$.activeTab==="completed"?C("div",{"data-testid":"met-completed-pane"},I(v.length>0?v:S.filter((P)=>P.status==="succeeded"),"completed"),qu()):null,$.activeTab==="failed"?C("div",{"data-testid":"met-failed-pane"},I(T.length>0?T:S.filter((P)=>["failed","canceled"].includes(P.status)),"failed"),qu(),C("div",{className:"panel-actions inline-actions"},C(bi,{title:"MET History",data:n.history,onOpen:f,testId:"raw-met-history"}))):null,$.activeTab==="gpu"?C("div",{className:"met-gpu-pane","data-testid":"met-gpu-pane"},D.length===0?C(S0,{title:"暂无 GPU 上报",text:"等待 D601 met-nonlinear-ts 或 ML image 提供 nvidia-smi 数据"}):C("div",{className:"table-wrap"},C("table",null,C("thead",null,C("tr",null,C("th",null,"Index"),C("th",null,"Name"),C("th",null,"Free"),C("th",null,"Policy"))),C("tbody",null,D.map((P)=>C("tr",{key:P.index},C("td",null,P.index),C("td",null,P.name),C("td",null,`${P.memoryFreeMiB} / ${P.memoryTotalMiB} MiB`,C("div",{className:"met-progress"},C("span",{style:{width:h_(Number(P.freeRatio)*100)}}))),C("td",null,String(P.name||"").includes("2080")?"target 2080Ti, <20% 限制并发":"non-target")))))),C("div",{className:"panel-actions inline-actions"},C(bi,{title:"MET Images",data:n.images,onOpen:f,testId:"raw-met-images"}))):null))))}var l6=[{id:"ops",label:"运行总览",code:"OPS",tabs:[{id:"status",label:"态势总览"},{id:"performance",label:"性能面板"},{id:"events",label:"事件摘要"},{id:"logs",label:"服务日志"}]},{id:"nodes",label:"资源节点",code:"NODE",tabs:[{id:"list",label:"节点清单"},{id:"monitor",label:"资源监控"},{id:"docker",label:"Docker 状态"},{id:"gateway",label:"网关版本"},{id:"labels",label:"资源标签"},{id:"heartbeats",label:"心跳状态"}]},{id:"tasks",label:"任务调度",code:"TASK",tabs:[{id:"dispatch",label:"下发任务"},{id:"scheduled",label:"定时任务"},{id:"pending",label:"待处理任务"},{id:"history",label:"任务历史"},{id:"results",label:"执行结果"}]},{id:"apps",label:"用户服务",code:"APP",routeSegment:"app",tabs:[{id:"catalog",label:"服务目录"},{id:"todo-note",label:"Todo Note"},{id:"findjob",label:"FindJob"},{id:"pipeline",label:"Pipeline"},{id:"met-nonlinear",label:"MET Nonlinear"},{id:"claudeqq",label:"ClaudeQQ"},{id:"baidu-netdisk",label:"Baidu Netdisk"},{id:"filebrowser",label:"File Browser"},{id:"oa-event-flow",label:"OA Event Flow"},{id:"code-queue",label:"Code Queue"},{id:"project-manager",label:"Project Manager"}]},{id:"config",label:"系统配置",code:"CFG",tabs:[{id:"topology",label:"连接拓扑"},{id:"auth",label:"认证策略"},{id:"security",label:"安全边界"}]}],I_=Object.fromEntries(l6.map((u)=>[u.id,u.tabs[0]?.id??""]));function kZ(u){let f=String(u||"").trim();if(!f)return"";try{return decodeURIComponent(f)}catch{return f}}function f6(u){let f=String(u||"/"),[l]=f.split(/[?#]/u,1);if(l==="/")return"/";let n=`/${l.split("/").map(kZ).filter(Boolean).join("/")}`;return n.endsWith("/")?n:`${n}/`}function IZ(u){let f=2166136261;for(let l of u)f^=l.charCodeAt(0),f=Math.imul(f,16777619);return Math.abs(f>>>0).toString(36)}function yA(u){return String(u||"").normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"")}function xQ(u){return String(u||"").trim().toLowerCase().replace(/[\s/\\?#%]+/gu,"-").replace(/-+/gu,"-").replace(/^-+|-+$/gu,"")}function hQ(u){let f=yA(u.routeSegment||"")||xQ(u.routeSegment||"");if(f)return f;let l=yA(u.id||"");if(l)return l;let r=yA(u.label||"")||xQ(u.label||"");if(r)return r;return`route-${IZ(JSON.stringify(u))}`}function _A(u,f){return`${u}:${f}`}function bQ(u){let f=u.map(($)=>{let A=hQ($);return{...$,routeSegment:A,tabs:$.tabs.map((c)=>({...c,routeSegment:hQ(c)}))}}),l={},r={},n={},i=f.map(($)=>{let A=$.tabs[0]?.id??"";n[$.id]=A;let c=$.tabs.map((U)=>{let Q=`/${$.routeSegment}/${U.routeSegment}/`,L=[Q],w={moduleId:$.id,tabId:U.id};for(let J of L)l[f6(J)]=w;return r[_A($.id,U.id)]=Q,{...U,canonicalPath:Q,aliases:L}}),j=`/${$.routeSegment}/`,F={moduleId:$.id,tabId:A};return l[f6(j)]=F,{...$,routeSegment:$.routeSegment,canonicalPath:j,tabs:c}}),y=i[0],_={moduleId:y?.id||"",tabId:y?.tabs[0]?.id||""};return l["/"]=_,{modules:i,moduleById:Object.fromEntries(i.map(($)=>[$.id,$])),defaultActiveTabs:n,routeMap:l,canonicalPathByTarget:r,fallbackTarget:_}}function $A(u,f){return u.routeMap[f6(f)]||u.fallbackTarget}function r6(u,f,l){return u.canonicalPathByTarget[_A(f,l)]||u.canonicalPathByTarget[_A(u.fallbackTarget.moduleId,u.fallbackTarget.tabId)]||"/"}function vQ(u,f){let l=u.routeMap[f6(f)];if(!l)return null;return r6(u,l.moduleId,l.tabId)}var _6=Pu(Qf(),1);var iu=_6.default.createElement,{useEffect:kQ,useMemo:gZ}=_6.default,tA=_6.default.useState;function y6({status:u,children:f,title:l}){let r=String(u||"unknown").toLowerCase();return iu("span",{className:`status-badge ${r}`,title:l},f||u||"unknown")}function g_({label:u,value:f,hint:l,tone:r}){return iu("article",{className:`metric-card ${r||""}`},iu("div",{className:"metric-label"},u),iu("div",{className:"metric-value"},f),iu("div",{className:"metric-hint"},l))}function n6({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return iu("section",{className:`panel ${n||""}`},iu("div",{className:"panel-head"},iu("div",null,f?iu("p",{className:"panel-eyebrow"},f):null,iu(nf,{title:u,loading:i})),l?iu("div",{className:"panel-actions"},l):null),iu("div",{className:"panel-body"},r))}function s_({title:u,data:f,onOpen:l,testId:r}){return iu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l?.(u,f)},"查看原始JSON")}function AA({title:u,text:f}){return iu("div",{className:"empty-state"},iu("strong",null,u),iu("span",null,f))}function sZ(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function p0(u){return Array.isArray(u)?u:[]}function Il(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}function IQ(u,f=140){if(u===null||u===void 0)return"--";let l=typeof u==="string"?u:JSON.stringify(u),r=String(l||"").replace(/\s+/gu," ").trim();return r.length>f?`${r.slice(0,f-1)}...`:r||"--"}function aZ(u){return p0(u?.tags).map((f)=>String(f||"").trim()).filter(Boolean)}function E1(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):0}function oZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function dZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function eZ(u){return String(u||"").split(/[\s,]+/u).map((f)=>f.trim()).filter(Boolean).join(",")}function i6(u,f){return`${u}/microservices/oa-event-flow/proxy${f}`}function uO(u){if(u.includes("error")||u.includes("failed"))return"failed";if(u.includes("stats"))return"ok";if(u.includes("step")||u.includes("updated"))return"running";return"queued"}function fO(u){let f=String(u?.subjectKind||"trace"),l=String(u?.subjectId||u?.scopeId||"");return l?`${f}:${l}`:String(u?.scopeId||"--")}function lO({tags:u}){let f=aZ({tags:u}).slice(0,6);return iu("div",{className:"oa-tag-rail"},f.length===0?iu("span",{className:"muted"},"--"):f.map((l)=>iu("code",{key:l},l)))}function rO({events:u,onRaw:f}){let l=[...p0(u)].reverse();return l.length===0?iu(AA,{title:"事件表暂无记录",text:"等待 Code Queue 或 Pipeline 按 tag 发布 OA 事件"}):iu("div",{className:"table-wrap oa-event-table-wrap"},iu("table",{className:"oa-event-table","data-testid":"oa-event-flow-event-table"},iu("thead",null,iu("tr",null,iu("th",null,"Seq"),iu("th",null,"Type"),iu("th",null,"Source"),iu("th",null,"Aggregate"),iu("th",null,"Tags"),iu("th",null,"Payload"),iu("th",null,"Created"),iu("th",null,"Raw"))),iu("tbody",null,l.map((r)=>{let n=String(r?.type||"event"),i=`${String(r?.aggregateType||"--")}:${String(r?.aggregateId||"--")}`;return iu("tr",{key:r?.eventId||r?.sequence},iu("td",null,iu("code",null,Il(r?.sequence))),iu("td",null,iu(y6,{status:uO(n)},n)),iu("td",null,iu("strong",null,r?.sourceId||"--"),iu("code",null,r?.sourceKind||"--")),iu("td",null,iu("code",null,i)),iu("td",null,iu(lO,{tags:r?.tags})),iu("td",null,iu("span",{className:"oa-payload-preview"},IQ(r?.payload,180))),iu("td",null,Nu(r?.createdAt)),iu("td",null,iu(s_,{title:`OA Event ${r?.sequence||""}`,data:r,onOpen:f,testId:`raw-oa-event-${r?.sequence||"unknown"}`})))}))))}function nO({stats:u,onRaw:f}){let l=p0(u);return l.length===0?iu(AA,{title:"统计中心暂无投影",text:"trace-stats-snapshot / trace-step-created 进入事件流后会更新这里"}):iu("div",{className:"table-wrap oa-stats-table-wrap"},iu("table",{className:"oa-stats-table","data-testid":"oa-event-flow-stats"},iu("thead",null,iu("tr",null,iu("th",null,"Scope"),iu("th",null,"Service"),iu("th",null,"STEP"),iu("th",null,"Read"),iu("th",null,"Edit"),iu("th",null,"Run"),iu("th",null,"Error"),iu("th",null,"Output Seq"),iu("th",null,"Revision"),iu("th",null,"Updated"),iu("th",null,"Raw"))),iu("tbody",null,l.map((r)=>iu("tr",{key:r?.scopeId||`${r?.serviceId}-${r?.subjectId}`},iu("td",null,iu("strong",null,fO(r)),iu("code",null,r?.scopeId||"--")),iu("td",null,iu(y6,{status:String(r?.serviceId||"unknown")==="code-queue"?"running":"queued"},r?.serviceId||"--")),iu("td",null,iu("strong",null,Il(E1(r?.stepCount??r?.llmStepCount)))),iu("td",null,Il(E1(r?.readCount))),iu("td",null,Il(E1(r?.editCount))),iu("td",null,Il(E1(r?.runCount))),iu("td",null,Il(E1(r?.errorCount))),iu("td",null,iu("code",null,Il(E1(r?.outputMaxSeq)))),iu("td",null,Il(E1(r?.statsRevision))),iu("td",null,Nu(r?.updatedAt)),iu("td",null,iu(s_,{title:`OA Trace Stats ${r?.scopeId||""}`,data:r,onOpen:f,testId:`raw-oa-stats-${String(r?.scopeId||"unknown").replace(/[^a-zA-Z0-9_-]/gu,"_")}`})))))))}function gQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((z)=>z.id==="oa-event-flow")||null,[n,i]=tA("service:code-queue"),[y,_]=tA({loading:!1,error:"",health:null,diagnostics:null,events:[],stats:[],refreshedAt:null}),[$,A]=tA({status:"idle",message:"未连接",lastEventAt:""}),c=gZ(()=>eZ(n),[n]);async function j(){if(!r)return;_((z)=>({...z,loading:!0,error:""}));try{let z=c?`tags=${encodeURIComponent(c)}&`:"",[Z,H,E,D]=await Promise.all([Eu(`${l}/microservices/oa-event-flow/health`,{failureFields:[]}),Eu(i6(l,"/api/diagnostics")),Eu(i6(l,`/api/events?${z}limit=100`)),Eu(i6(l,`/api/stats/trace?${z}limit=100`))]);_({loading:!1,error:"",health:Z,diagnostics:H,events:p0(E?.events),stats:p0(D?.stats),refreshedAt:new Date})}catch(z){_((Z)=>({...Z,loading:!1,error:Zu(z,"OA Event Flow 加载失败")}))}}if(kQ(()=>{j()},[r?.id,r?.runtime?.providerStatus,c]),kQ(()=>{if(!r||typeof EventSource>"u")return;let z=c?`?tags=${encodeURIComponent(c)}`:"",Z=new EventSource(`${i6(l,"/api/events/stream")}${z}`,{withCredentials:!0});A({status:"running",message:"SSE connecting",lastEventAt:""});let H=(h)=>{A({status:"online",message:IQ(h.data,120),lastEventAt:new Date().toISOString()})},E=(h)=>{try{let V=JSON.parse(String(h.data||"{}"));A({status:"online",message:String(V?.type||h.type||"event"),lastEventAt:new Date().toISOString()}),_((Y)=>{let p=[...p0(Y.events).filter((m)=>String(m?.eventId||"")!==String(V?.eventId||"")),V].sort((m,X)=>Number(m?.sequence||0)-Number(X?.sequence||0)).slice(-100),O=V?.type==="trace-stats-updated"&&sZ(V?.payload?.stats)?[V.payload.stats,...p0(Y.stats).filter((m)=>String(m?.scopeId||"")!==String(V.payload.stats.scopeId||""))].slice(0,100):Y.stats;return{...Y,events:p,stats:O}})}catch(V){A({status:"warn",message:Zu(V,"SSE 事件解析失败"),lastEventAt:new Date().toISOString()})}},D=()=>{A((h)=>({...h,status:"warn",message:"SSE reconnecting"}))};return Z.addEventListener("hello",H),Z.addEventListener("task-updated",E),Z.addEventListener("queue-updated",E),Z.addEventListener("trace-step-created",E),Z.addEventListener("trace-stats-snapshot",E),Z.addEventListener("trace-stats-updated",E),Z.addEventListener("trace-error",E),Z.onerror=D,()=>Z.close()},[r?.id,l,c]),!r)return iu(AA,{title:"OA Event Flow 未登记",text:"请在 config.json 的 microservices 中登记 id=oa-event-flow"});let F=oZ(r),U=dZ(r),Q=y.diagnostics||{},L=y.health||{},w=Q.eventCount??L.eventCount,J=Q.traceStatsCount??L.traceStatsCount,N=Q.latestSequence??L.latestSequence,q=Q.pipelineBridge||L.pipelineBridge||{},W=p0(Q.eventTypes).slice(0,8);return iu("div",{className:"oa-event-flow-page","data-testid":"oa-event-flow-page"},iu(n6,{title:"OA Event Flow 控制台",eyebrow:"Unified OA Event Bus + Stats Projection",loading:y.loading,actions:iu("div",{className:"panel-actions"},iu("button",{type:"button",className:"ghost-btn",onClick:j,disabled:y.loading,"data-testid":"oa-event-flow-refresh"},y.loading?"刷新中":"刷新"),iu(s_,{title:"OA Event Flow Service",data:r,onOpen:f,testId:"raw-oa-event-flow-service"}))},iu("div",{className:"oa-flow-hero"},iu("div",null,iu("div",{className:"node-version-line"},iu(y6,{status:L?.ok||F.providerStatus==="online"?"online":"warn"},L?.ok?"HEALTH OK":F.providerStatus||"unknown"),iu(y6,{status:$.status},$.status.toUpperCase()),iu("span",null,U.public?"公网暴露":"仅 UniDesk frontend 代理访问")),iu("p",{className:"muted paragraph"},"独立事件流微服务统一承载 Code Queue 与 Pipeline 的事件发布、tag 订阅、事件表审计和 Trace/STEP 统计投影。")),iu("div",{className:"oa-flow-signal"},iu("span",null,"stream"),iu("strong",null,$.message||"--"),iu("code",null,$.lastEventAt?$f(new Date($.lastEventAt)):"waiting"))),iu(yf,{error:y.error,wide:!0})),iu("div",{className:"oa-flow-metrics"},iu(g_,{label:"事件总量",value:Il(w),hint:`latest seq ${Il(N)}`,tone:"ok"}),iu(g_,{label:"Trace Stats",value:Il(J),hint:"oa_trace_stats 投影"}),iu(g_,{label:"SSE Clients",value:Il(L?.sseClientCount??p0(Q.sseClients).length),hint:$.message||"tag subscription"}),iu(g_,{label:"Pipeline Bridge",value:q?.enabled?Il(q?.insertedCount):"OFF",hint:q?.lastError||q?.lastFinishedAt||`${q?.mode||"snapshot"} service:pipeline`}),iu(g_,{label:"DB",value:L?.databaseReady||Q.databaseReady?"READY":"WAIT",hint:L?.databaseLastError||Q.databaseLastError||"PostgreSQL persisted"})),iu(n6,{title:"标签订阅",eyebrow:y.refreshedAt?`Updated ${$f(y.refreshedAt)}`:"Tag Pub/Sub"},iu("div",{className:"oa-filter-bar"},iu("label",null,iu("span",null,"tags"),iu("input",{value:n,onChange:(z)=>i(z.target.value),placeholder:"service:code-queue, trace","data-testid":"oa-event-flow-tag-filter"})),iu("div",{className:"oa-filter-presets"},iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("service:code-queue")},"Code Queue"),iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("service:pipeline")},"Pipeline"),iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("trace")},"Trace"),iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("")},"All")),iu("code",null,c||"all events")),iu("div",{className:"oa-type-strip"},W.length===0?iu("span",{className:"muted"},"等待事件类型统计"):W.map((z)=>iu("span",{key:z.type,className:"data-chip"},`${z.type} ${Il(z.count)}`)))),iu("div",{className:"oa-flow-grid"},iu(n6,{title:"事件表",eyebrow:"oa_events persisted log",className:"oa-flow-wide",loading:y.loading,actions:iu(s_,{title:"OA Event Query",data:{events:y.events,diagnostics:Q},onOpen:f,testId:"raw-oa-events"})},iu(rO,{events:y.events,onRaw:f})),iu(n6,{title:"统计中心",eyebrow:"oa_trace_stats read model",className:"oa-flow-wide",loading:y.loading,actions:iu(s_,{title:"OA Trace Stats",data:y.stats,onOpen:f,testId:"raw-oa-trace-stats"})},iu(nO,{stats:y.stats,onRaw:f}))))}var xn=Pu(Qf(),1);var ru=Pu(dQ(),1),yu=Pu(Qf(),1);function Yf(u){if(typeof u==="string"||typeof u==="number")return""+u;let f="";if(Array.isArray(u)){for(let l=0,r;l{}};function uq(){for(var u=0,f=arguments.length,l={},r;u=0)r=l.slice(n+1),l=l.slice(0,n);if(l&&!f.hasOwnProperty(l))throw Error("unknown type: "+l);return{type:l,name:r}})}t6.prototype=uq.prototype={constructor:t6,on:function(u,f){var l=this._,r=jO(u+"",l),n,i=-1,y=r.length;if(arguments.length<2){while(++i0)for(var l=Array(n),r=0,n,i;r=0&&(f=u.slice(0,l))!=="xmlns")u=u.slice(l+1);return cA.hasOwnProperty(f)?{space:cA[f],local:u}:u}function jA(u){let f;while(f=u.sourceEvent)u=f;return u}function Kl(u,f){if(u=jA(u),f===void 0)f=u.currentTarget;if(f){var l=f.ownerSVGElement||f;if(l.createSVGPoint){var r=l.createSVGPoint();return r.x=u.clientX,r.y=u.clientY,r=r.matrixTransform(f.getScreenCTM().inverse()),[r.x,r.y]}if(f.getBoundingClientRect){var n=f.getBoundingClientRect();return[u.clientX-n.left-f.clientLeft,u.clientY-n.top-f.clientTop]}}return[u.pageX,u.pageY]}function JO(){}function Hn(u){return u==null?JO:function(){return this.querySelector(u)}}function FA(u){if(typeof u!=="function")u=Hn(u);for(var f=this._groups,l=f.length,r=Array(l),n=0;n=q)q=N+1;while(!(z=w[q])&&++q=0;)if(y=r[n]){if(i&&y.compareDocumentPosition(i)^4)i.parentNode.insertBefore(y,i);i=y}return this}function EA(u){if(!u)u=ZO;function f(j,F){return j&&F?u(j.__data__,F.__data__):!j-!F}for(var l=this._groups,r=l.length,n=Array(r),i=0;if?1:u>=f?0:NaN}function ZA(){var u=arguments[0];return arguments[0]=this,u.apply(null,arguments),this}function OA(){return Array.from(this)}function HA(){for(var u=this._groups,f=0,l=u.length;f1?this.each((f==null?YO:typeof f==="function"?pO:SO)(u,f,l==null?"":l)):Bn(this.node(),u)}function Bn(u,f){return u.style.getPropertyValue(f)||d_(u).getComputedStyle(u,null).getPropertyValue(f)}function mO(u){return function(){delete this[u]}}function PO(u,f){return function(){this[u]=f}}function MO(u,f){return function(){var l=f.apply(this,arguments);if(l==null)delete this[u];else this[u]=l}}function SA(u,f){return arguments.length>1?this.each((f==null?mO:typeof f==="function"?MO:PO)(u,f)):this.node()[u]}function fq(u){return u.trim().split(/^|\s+/)}function pA(u){return u.classList||new lq(u)}function lq(u){this._node=u,this._names=fq(u.getAttribute("class")||"")}lq.prototype={add:function(u){var f=this._names.indexOf(u);if(f<0)this._names.push(u),this._node.setAttribute("class",this._names.join(" "))},remove:function(u){var f=this._names.indexOf(u);if(f>=0)this._names.splice(f,1),this._node.setAttribute("class",this._names.join(" "))},contains:function(u){return this._names.indexOf(u)>=0}};function rq(u,f){var l=pA(u),r=-1,n=f.length;while(++r=0)l=f.slice(r+1),f=f.slice(0,r);return{type:f,name:l}})}function iH(u){return function(){var f=this.__on;if(!f)return;for(var l=0,r=-1,n=f.length,i;l()=>u;function l$(u,{sourceEvent:f,subject:l,target:r,identifier:n,active:i,x:y,y:_,dx:$,dy:A,dispatch:c}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:f,enumerable:!0,configurable:!0},subject:{value:l,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:n,enumerable:!0,configurable:!0},active:{value:i,enumerable:!0,configurable:!0},x:{value:y,enumerable:!0,configurable:!0},y:{value:_,enumerable:!0,configurable:!0},dx:{value:$,enumerable:!0,configurable:!0},dy:{value:A,enumerable:!0,configurable:!0},_:{value:c}})}l$.prototype.on=function(){var u=this._.on.apply(this._,arguments);return u===this._?this:u};function qH(u){return!u.ctrlKey&&!u.button}function NH(){return this.parentNode}function WH(u,f){return f==null?{x:u.x,y:u.y}:f}function LH(){return navigator.maxTouchPoints||"ontouchstart"in this}function r$(){var u=qH,f=NH,l=WH,r=LH,n={},i=Z1("start","drag","end"),y=0,_,$,A,c,j=0;function F(W){W.on("mousedown.drag",U).filter(r).on("touchstart.drag",w).on("touchmove.drag",J,_q).on("touchend.drag touchcancel.drag",N).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function U(W,z){if(c||!u.call(this,W,z))return;var Z=q(this,f.call(this,W,z),W,z,"mouse");if(!Z)return;sf(W.view).on("mousemove.drag",Q,O1).on("mouseup.drag",L,O1),Ii(W.view),j6(W),A=!1,_=W.clientX,$=W.clientY,Z("start",W)}function Q(W){if(P0(W),!A){var z=W.clientX-_,Z=W.clientY-$;A=z*z+Z*Z>j}n.mouse("drag",W)}function L(W){sf(W.view).on("mousemove.drag mouseup.drag",null),u$(W.view,A),P0(W),n.mouse("end",W)}function w(W,z){if(!u.call(this,W,z))return;var Z=W.changedTouches,H=f.call(this,W,z),E=Z.length,D,h;for(D=0;D>8&15|f>>4&240,f>>4&15|f&240,(f&15)<<4|f&15,1):l===8?F6(f>>24&255,f>>16&255,f>>8&255,(f&255)/255):l===4?F6(f>>12&15|f>>8&240,f>>8&15|f>>4&240,f>>4&15|f&240,((f&15)<<4|f&15)/255):null):(f=KH.exec(u))?new gl(f[1],f[2],f[3],1):(f=GH.exec(u))?new gl(f[1]*255/100,f[2]*255/100,f[3]*255/100,1):(f=zH.exec(u))?F6(f[1],f[2],f[3],f[4]):(f=TH.exec(u))?F6(f[1]*255/100,f[2]*255/100,f[3]*255/100,f[4]):(f=EH.exec(u))?Jq(f[1],f[2]/100,f[3]/100,1):(f=ZH.exec(u))?Jq(f[1],f[2]/100,f[3]/100,f[4]):$q.hasOwnProperty(u)?cq($q[u]):u==="transparent"?new gl(NaN,NaN,NaN,0):null}function cq(u){return new gl(u>>16&255,u>>8&255,u&255,1)}function F6(u,f,l,r){if(r<=0)u=f=l=NaN;return new gl(u,f,l,r)}function BH(u){if(!(u instanceof _$))u=vr(u);if(!u)return new gl;return u=u.rgb(),new gl(u.r,u.g,u.b,u.opacity)}function si(u,f,l,r){return arguments.length===1?BH(u):new gl(u,f,l,r==null?1:r)}function gl(u,f,l,r){this.r=+u,this.g=+f,this.b=+l,this.opacity=+r}n$(gl,si,oA(_$,{brighter(u){return u=u==null?U6:Math.pow(U6,u),new gl(this.r*u,this.g*u,this.b*u,this.opacity)},darker(u){return u=u==null?i$:Math.pow(i$,u),new gl(this.r*u,this.g*u,this.b*u,this.opacity)},rgb(){return this},clamp(){return new gl(B1(this.r),B1(this.g),B1(this.b),Q6(this.opacity))},displayable(){return-0.5<=this.r&&this.r<255.5&&(-0.5<=this.g&&this.g<255.5)&&(-0.5<=this.b&&this.b<255.5)&&(0<=this.opacity&&this.opacity<=1)},hex:jq,formatHex:jq,formatHex8:VH,formatRgb:Fq,toString:Fq}));function jq(){return`#${H1(this.r)}${H1(this.g)}${H1(this.b)}`}function VH(){return`#${H1(this.r)}${H1(this.g)}${H1(this.b)}${H1((isNaN(this.opacity)?1:this.opacity)*255)}`}function Fq(){let u=Q6(this.opacity);return`${u===1?"rgb(":"rgba("}${B1(this.r)}, ${B1(this.g)}, ${B1(this.b)}${u===1?")":`, ${u})`}`}function Q6(u){return isNaN(u)?1:Math.max(0,Math.min(1,u))}function B1(u){return Math.max(0,Math.min(255,Math.round(u)||0))}function H1(u){return u=B1(u),(u<16?"0":"")+u.toString(16)}function Jq(u,f,l,r){if(r<=0)u=f=l=NaN;else if(l<=0||l>=1)u=f=NaN;else if(f<=0)u=NaN;return new br(u,f,l,r)}function Qq(u){if(u instanceof br)return new br(u.h,u.s,u.l,u.opacity);if(!(u instanceof _$))u=vr(u);if(!u)return new br;if(u instanceof br)return u;u=u.rgb();var f=u.r/255,l=u.g/255,r=u.b/255,n=Math.min(f,l,r),i=Math.max(f,l,r),y=NaN,_=i-n,$=(i+n)/2;if(_){if(f===i)y=(l-r)/_+(l0&&$<1?0:y;return new br(y,_,$,u.opacity)}function qq(u,f,l,r){return arguments.length===1?Qq(u):new br(u,f,l,r==null?1:r)}function br(u,f,l,r){this.h=+u,this.s=+f,this.l=+l,this.opacity=+r}n$(br,qq,oA(_$,{brighter(u){return u=u==null?U6:Math.pow(U6,u),new br(this.h,this.s,this.l*u,this.opacity)},darker(u){return u=u==null?i$:Math.pow(i$,u),new br(this.h,this.s,this.l*u,this.opacity)},rgb(){var u=this.h%360+(this.h<0)*360,f=isNaN(u)||isNaN(this.s)?0:this.s,l=this.l,r=l+(l<0.5?l:1-l)*f,n=2*l-r;return new gl(dA(u>=240?u-240:u+120,n,r),dA(u,n,r),dA(u<120?u+240:u-120,n,r),this.opacity)},clamp(){return new br(Uq(this.h),J6(this.s),J6(this.l),Q6(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&(0<=this.l&&this.l<=1)&&(0<=this.opacity&&this.opacity<=1)},formatHsl(){let u=Q6(this.opacity);return`${u===1?"hsl(":"hsla("}${Uq(this.h)}, ${J6(this.s)*100}%, ${J6(this.l)*100}%${u===1?")":`, ${u})`}`}}));function Uq(u){return u=(u||0)%360,u<0?u+360:u}function J6(u){return Math.max(0,Math.min(1,u||0))}function dA(u,f,l){return(u<60?f+(l-f)*u/60:u<180?l:u<240?f+(l-f)*(240-u)/60:f)*255}function eA(u,f,l,r,n){var i=u*u,y=i*u;return((1-3*u+3*i-y)*f+(4-6*i+3*y)*l+(1+3*u+3*i-3*y)*r+y*n)/6}function uc(u){var f=u.length-1;return function(l){var r=l<=0?l=0:l>=1?(l=1,f-1):Math.floor(l*f),n=u[r],i=u[r+1],y=r>0?u[r-1]:2*n-i,_=r()=>u;function XH(u,f){return function(l){return u+l*f}}function YH(u,f,l){return u=Math.pow(u,l),f=Math.pow(f,l)-u,l=1/l,function(r){return Math.pow(u+r*f,l)}}function Nq(u){return(u=+u)===1?N6:function(f,l){return l-f?YH(f,l,u):$$(isNaN(f)?l:f)}}function N6(u,f){var l=f-u;return l?XH(u,l):$$(isNaN(u)?f:u)}var V1=function u(f){var l=Nq(f);function r(n,i){var y=l((n=si(n)).r,(i=si(i)).r),_=l(n.g,i.g),$=l(n.b,i.b),A=N6(n.opacity,i.opacity);return function(c){return n.r=y(c),n.g=_(c),n.b=$(c),n.opacity=A(c),n+""}}return r.gamma=u,r}(1);function Wq(u){return function(f){var l=f.length,r=Array(l),n=Array(l),i=Array(l),y,_;for(y=0;yl)if(i=f.slice(l,i),_[y])_[y]+=i;else _[++y]=i;if((r=r[0])===(n=n[0]))if(_[y])_[y]+=n;else _[++y]=n;else _[++y]=null,$.push({i:y,x:Gl(r,n)});l=ic.lastIndex}if(l180)c+=360;else if(c-A>180)A+=360;F.push({i:j.push(n(j)+"rotate(",null,r)-2,x:Gl(A,c)})}else if(c)j.push(n(j)+"rotate("+c+r)}function _(A,c,j,F){if(A!==c)F.push({i:j.push(n(j)+"skewX(",null,r)-2,x:Gl(A,c)});else if(c)j.push(n(j)+"skewX("+c+r)}function $(A,c,j,F,U,Q){if(A!==j||c!==F){var L=U.push(n(U)+"scale(",null,",",null,")");Q.push({i:L-4,x:Gl(A,j)},{i:L-2,x:Gl(c,F)})}else if(j!==1||F!==1)U.push(n(U)+"scale("+j+","+F+")")}return function(A,c){var j=[],F=[];return A=u(A),c=u(c),i(A.translateX,A.translateY,c.translateX,c.translateY,j,F),y(A.rotate,c.rotate,j,F),_(A.skewX,c.skewX,j,F),$(A.scaleX,A.scaleY,c.scaleX,c.scaleY,j,F),A=c=null,function(U){var Q=-1,L=F.length,w;while(++Q=0)u._call.call(void 0,f);u=u._next}--oi}function Bq(){X1=(G6=j$.now())+z6,oi=A$=0;try{Xq()}finally{oi=0,lB(),X1=0}}function fB(){var u=j$.now(),f=u-G6;if(f>Vq)z6-=f,G6=u}function lB(){var u,f=K6,l,r=1/0;while(f)if(f._call){if(r>f._time)r=f._time;u=f,f=f._next}else l=f._next,f._next=null,f=u?u._next=l:K6=l;c$=u,tc(r)}function tc(u){if(oi)return;if(A$)A$=clearTimeout(A$);var f=u-X1;if(f>24){if(u<1/0)A$=setTimeout(Bq,u-j$.now()-z6);if(t$)t$=clearInterval(t$)}else{if(!t$)G6=j$.now(),t$=setInterval(fB,Vq);oi=1,Dq(Bq)}}function U$(u,f,l){var r=new F$;return f=f==null?0:+f,r.restart((n)=>{r.stop(),u(n+f)},f,l),r}var nB=Z1("start","end","cancel","interrupt"),iB=[],pq=0,Yq=1,Z6=2,E6=3,Sq=4,O6=5,Q$=6;function M0(u,f,l,r,n,i){var y=u.__transition;if(!y)u.__transition={};else if(l in y)return;yB(u,l,{name:f,index:r,group:n,on:nB,tween:iB,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:pq})}function q$(u,f){var l=af(u,f);if(l.state>pq)throw Error("too late; already scheduled");return l}function jl(u,f){var l=af(u,f);if(l.state>E6)throw Error("too late; already running");return l}function af(u,f){var l=u.__transition;if(!l||!(l=l[f]))throw Error("transition not found");return l}function yB(u,f,l){var r=u.__transition,n;r[f]=l,l.timer=T6(i,0,l.time);function i(A){if(l.state=Yq,l.timer.restart(y,l.delay,l.time),l.delay<=A)y(A-l.delay)}function y(A){var c,j,F,U;if(l.state!==Yq)return $();for(c in r){if(U=r[c],U.name!==l.name)continue;if(U.state===E6)return U$(y);if(U.state===Sq)U.state=Q$,U.timer.stop(),U.on.call("interrupt",u,u.__data__,U.index,U.group),delete r[c];else if(+cZ6&&r.state=0)f=f.slice(0,l);return!f||f==="start"})}function EB(u,f,l){var r,n,i=TB(f)?q$:jl;return function(){var y=i(this,u),_=y.on;if(_!==r)(n=(r=_).copy()).on(f,l);y.on=n}}function Lc(u,f){var l=this._id;return arguments.length<2?af(this.node(),l).on.on(u):this.each(EB(l,u,f))}function ZB(u){return function(){var f=this.parentNode;for(var l in this.__transition)if(+l!==u)return;if(f)f.removeChild(this)}}function wc(){return this.on("end.remove",ZB(this._id))}function Kc(u){var f=this._name,l=this._id;if(typeof u!=="function")u=Hn(u);for(var r=this._groups,n=r.length,i=Array(n),y=0;y()=>u;function Dc(u,{sourceEvent:f,target:l,transform:r,dispatch:n}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:f,enumerable:!0,configurable:!0},target:{value:l,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:n}})}function kr(u,f,l){this.k=u,this.x=f,this.y=l}kr.prototype={constructor:kr,scale:function(u){return u===1?this:new kr(this.k*u,this.x,this.y)},translate:function(u,f){return u===0&f===0?this:new kr(this.k,this.x+this.k*u,this.y+this.k*f)},apply:function(u){return[u[0]*this.k+this.x,u[1]*this.k+this.y]},applyX:function(u){return u*this.k+this.x},applyY:function(u){return u*this.k+this.y},invert:function(u){return[(u[0]-this.x)/this.k,(u[1]-this.y)/this.k]},invertX:function(u){return(u-this.x)/this.k},invertY:function(u){return(u-this.y)/this.k},rescaleX:function(u){return u.copy().domain(u.range().map(this.invertX,this).map(u.invert,u))},rescaleY:function(u){return u.copy().domain(u.range().map(this.invertY,this).map(u.invert,u))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Y1=new kr(1,0,0);L$.prototype=kr.prototype;function L$(u){while(!u.__zoom)if(!(u=u.parentNode))return Y1;return u.__zoom}function M6(u){u.stopImmediatePropagation()}function S1(u){u.preventDefault(),u.stopImmediatePropagation()}function hB(u){return(!u.ctrlKey||u.type==="wheel")&&!u.button}function bB(){var u=this;if(u instanceof SVGElement){if(u=u.ownerSVGElement||u,u.hasAttribute("viewBox"))return u=u.viewBox.baseVal,[[u.x,u.y],[u.x+u.width,u.y+u.height]];return[[0,0],[u.width.baseVal.value,u.height.baseVal.value]]}return[[0,0],[u.clientWidth,u.clientHeight]]}function Mq(){return this.__zoom||Y1}function vB(u){return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*(u.ctrlKey?10:1)}function kB(){return navigator.maxTouchPoints||"ontouchstart"in this}function IB(u,f,l){var r=u.invertX(f[0][0])-l[0][0],n=u.invertX(f[1][0])-l[1][0],i=u.invertY(f[0][1])-l[0][1],y=u.invertY(f[1][1])-l[1][1];return u.translate(n>r?(r+n)/2:Math.min(0,r)||Math.max(0,n),y>i?(i+y)/2:Math.min(0,i)||Math.max(0,y))}function w$(){var u=hB,f=bB,l=IB,r=vB,n=kB,i=[0,1/0],y=[[-1/0,-1/0],[1/0,1/0]],_=250,$=D1,A=Z1("start","zoom","end"),c,j,F,U=500,Q=150,L=0,w=10;function J(O){O.property("__zoom",Mq).on("wheel.zoom",E,{passive:!1}).on("mousedown.zoom",D).on("dblclick.zoom",h).filter(n).on("touchstart.zoom",V).on("touchmove.zoom",Y).on("touchend.zoom touchcancel.zoom",p).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}J.transform=function(O,m,X,v){var T=O.selection?O.selection():O;if(T.property("__zoom",Mq),O!==T)z(O,m,X,v);else T.interrupt().each(function(){Z(this,arguments).event(v).start().zoom(null,typeof m==="function"?m.apply(this,arguments):m).end()})},J.scaleBy=function(O,m,X,v){J.scaleTo(O,function(){var T=this.__zoom.k,S=typeof m==="function"?m.apply(this,arguments):m;return T*S},X,v)},J.scaleTo=function(O,m,X,v){J.transform(O,function(){var T=f.apply(this,arguments),S=this.__zoom,k=X==null?W(T):typeof X==="function"?X.apply(this,arguments):X,I=S.invert(k),b=typeof m==="function"?m.apply(this,arguments):m;return l(q(N(S,b),k,I),T,y)},X,v)},J.translateBy=function(O,m,X,v){J.transform(O,function(){return l(this.__zoom.translate(typeof m==="function"?m.apply(this,arguments):m,typeof X==="function"?X.apply(this,arguments):X),f.apply(this,arguments),y)},null,v)},J.translateTo=function(O,m,X,v,T){J.transform(O,function(){var S=f.apply(this,arguments),k=this.__zoom,I=v==null?W(S):typeof v==="function"?v.apply(this,arguments):v;return l(Y1.translate(I[0],I[1]).scale(k.k).translate(typeof m==="function"?-m.apply(this,arguments):-m,typeof X==="function"?-X.apply(this,arguments):-X),S,y)},v,T)};function N(O,m){return m=Math.max(i[0],Math.min(i[1],m)),m===O.k?O:new kr(m,O.x,O.y)}function q(O,m,X){var v=m[0]-X[0]*O.k,T=m[1]-X[1]*O.k;return v===O.x&&T===O.y?O:new kr(O.k,v,T)}function W(O){return[(+O[0][0]+ +O[1][0])/2,(+O[0][1]+ +O[1][1])/2]}function z(O,m,X,v){O.on("start.zoom",function(){Z(this,arguments).event(v).start()}).on("interrupt.zoom end.zoom",function(){Z(this,arguments).event(v).end()}).tween("zoom",function(){var T=this,S=arguments,k=Z(T,S).event(v),I=f.apply(T,S),b=X==null?W(I):typeof X==="function"?X.apply(T,S):X,o=Math.max(I[1][0]-I[0][0],I[1][1]-I[0][1]),g=T.__zoom,x=typeof m==="function"?m.apply(T,S):m,fu=$(g.invert(b).concat(o/g.k),x.invert(b).concat(o/x.k));return function($u){if($u===1)$u=x;else{var tu=fu($u),ju=o/tu[2];$u=new kr(ju,b[0]-tu[0]*ju,b[1]-tu[1]*ju)}k.zoom(null,$u)}})}function Z(O,m,X){return!X&&O.__zooming||new H(O,m)}function H(O,m){this.that=O,this.args=m,this.active=0,this.sourceEvent=null,this.extent=f.apply(O,m),this.taps=0}H.prototype={event:function(O){if(O)this.sourceEvent=O;return this},start:function(){if(++this.active===1)this.that.__zooming=this,this.emit("start");return this},zoom:function(O,m){if(this.mouse&&O!=="mouse")this.mouse[1]=m.invert(this.mouse[0]);if(this.touch0&&O!=="touch")this.touch0[1]=m.invert(this.touch0[0]);if(this.touch1&&O!=="touch")this.touch1[1]=m.invert(this.touch1[0]);return this.that.__zoom=m,this.emit("zoom"),this},end:function(){if(--this.active===0)delete this.that.__zooming,this.emit("end");return this},emit:function(O){var m=sf(this.that).datum();A.call(O,this.that,new Dc(O,{sourceEvent:this.sourceEvent,target:J,type:O,transform:this.that.__zoom,dispatch:A}),m)}};function E(O,...m){if(!u.apply(this,arguments))return;var X=Z(this,m).event(O),v=this.__zoom,T=Math.max(i[0],Math.min(i[1],v.k*Math.pow(2,r.apply(this,arguments)))),S=Kl(O);if(X.wheel){if(X.mouse[0][0]!==S[0]||X.mouse[0][1]!==S[1])X.mouse[1]=v.invert(X.mouse[0]=S);clearTimeout(X.wheel)}else if(v.k===T)return;else X.mouse=[S,v.invert(S)],Vn(this),X.start();S1(O),X.wheel=setTimeout(k,Q),X.zoom("mouse",l(q(N(v,T),X.mouse[0],X.mouse[1]),X.extent,y));function k(){X.wheel=null,X.end()}}function D(O,...m){if(F||!u.apply(this,arguments))return;var X=O.currentTarget,v=Z(this,m,!0).event(O),T=sf(O.view).on("mousemove.zoom",b,!0).on("mouseup.zoom",o,!0),S=Kl(O,X),k=O.clientX,I=O.clientY;Ii(O.view),M6(O),v.mouse=[S,this.__zoom.invert(S)],Vn(this),v.start();function b(g){if(S1(g),!v.moved){var x=g.clientX-k,fu=g.clientY-I;v.moved=x*x+fu*fu>L}v.event(g).zoom("mouse",l(q(v.that.__zoom,v.mouse[0]=Kl(g,X),v.mouse[1]),v.extent,y))}function o(g){T.on("mousemove.zoom mouseup.zoom",null),u$(g.view,v.moved),S1(g),v.event(g).end()}}function h(O,...m){if(!u.apply(this,arguments))return;var X=this.__zoom,v=Kl(O.changedTouches?O.changedTouches[0]:O,this),T=X.invert(v),S=X.k*(O.shiftKey?0.5:2),k=l(q(N(X,S),v,T),f.apply(this,m),y);if(S1(O),_>0)sf(this).transition().duration(_).call(z,k,v,O);else sf(this).call(J.transform,k,v,O)}function V(O,...m){if(!u.apply(this,arguments))return;var X=O.touches,v=X.length,T=Z(this,m,O.changedTouches.length===v).event(O),S,k,I,b;M6(O);for(k=0;k"[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001",error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:(u)=>`Node type "${u}" not found. Using fallback type "default".`,error004:()=>"The React Flow parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:(u)=>`The old edge with id=${u} does not exist.`,error009:(u)=>`Marker type "${u}" doesn't exist.`,error008:(u,{id:f,sourceHandle:l,targetHandle:r})=>`Couldn't create edge for ${u} handle id: "${u==="source"?l:r}", edge id: ${f}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:(u)=>`Edge type "${u}" not found. Using fallback type "default".`,error012:(u)=>`Node with id "${u}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(u="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${u}/dist/style.css' or base.css to make sure everything is working properly.`,error014:()=>"useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.",error015:()=>"It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs."},ry=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],mc=["Enter"," ","Escape"],Pc={"node.a11yDescription.default":"Press enter or space to select a node. Press delete to remove it and escape to cancel.","node.a11yDescription.keyboardDisabled":"Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.","node.a11yDescription.ariaLiveMessage":({direction:u,x:f,y:l})=>`Moved selected node ${u}. New position, x: ${f}, y: ${l}`,"edge.a11yDescription.default":"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.","controls.ariaLabel":"Control Panel","controls.zoomIn.ariaLabel":"Zoom In","controls.zoomOut.ariaLabel":"Zoom Out","controls.fitView.ariaLabel":"Fit View","controls.interactive.ariaLabel":"Toggle Interactivity","minimap.ariaLabel":"Mini Map","handle.ariaLabel":"Handle"},Yn;(function(u){u.Strict="strict",u.Loose="loose"})(Yn||(Yn={}));var R0;(function(u){u.Free="free",u.Vertical="vertical",u.Horizontal="horizontal"})(R0||(R0={}));var p1;(function(u){u.Partial="partial",u.Full="full"})(p1||(p1={}));var Mc={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null},t0;(function(u){u.Bezier="default",u.Straight="straight",u.Step="step",u.SmoothStep="smoothstep",u.SimpleBezier="simplebezier"})(t0||(t0={}));var Sn;(function(u){u.Arrow="arrow",u.ArrowClosed="arrowclosed"})(Sn||(Sn={}));var Lu;(function(u){u.Left="left",u.Top="top",u.Right="right",u.Bottom="bottom"})(Lu||(Lu={}));var Cq={[Lu.Left]:Lu.Right,[Lu.Right]:Lu.Left,[Lu.Top]:Lu.Bottom,[Lu.Bottom]:Lu.Top};function Cc(u){return u===null?null:u?"valid":"invalid"}var Rc=(u)=>("id"in u)&&("source"in u)&&("target"in u),eq=(u)=>("id"in u)&&("position"in u)&&!("source"in u)&&!("target"in u),xc=(u)=>("id"in u)&&("internals"in u)&&!("source"in u)&&!("target"in u);var z$=(u,f=[0,0])=>{let{width:l,height:r}=A0(u),n=u.origin??f,i=l*n[0],y=r*n[1];return{x:u.position.x-i,y:u.position.y-y}},hc=(u,f={nodeOrigin:[0,0]})=>{if(u.length===0)return{x:0,y:0,width:0,height:0};let l=u.reduce((r,n)=>{let i=typeof n==="string",y=!f.nodeLookup&&!i?n:void 0;if(f.nodeLookup)y=i?f.nodeLookup.get(n):!xc(n)?f.nodeLookup.get(n.id):n;let _=y?x6(y,f.nodeOrigin):{x:0,y:0,x2:0,y2:0};return b6(r,_)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return v6(l)},ny=(u,f={})=>{let l={x:1/0,y:1/0,x2:-1/0,y2:-1/0},r=!1;return u.forEach((n)=>{if(f.filter===void 0||f.filter(n))l=b6(l,x6(n)),r=!0}),r?v6(l):{x:0,y:0,width:0,height:0}},h6=(u,f,[l,r,n]=[0,0,1],i=!1,y=!1)=>{let _={..._y(f,[l,r,n]),width:f.width/n,height:f.height/n},$=[];for(let A of u.values()){let{measured:c,selectable:j=!0,hidden:F=!1}=A;if(y&&!j||F)continue;let U=c.width??A.width??A.initialWidth??null,Q=c.height??A.height??A.initialHeight??null,L=iy(_,P1(A)),w=(U??0)*(Q??0),J=i&&L>0;if(!A.internals.handleBounds||J||L>=w||A.dragging)$.push(A)}return $},uN=(u,f)=>{let l=new Set;return u.forEach((r)=>{l.add(r.id)}),f.filter((r)=>l.has(r.source)||l.has(r.target))};function gB(u,f){let l=new Map,r=f?.nodes?new Set(f.nodes.map((n)=>n.id)):null;return u.forEach((n)=>{if(n.measured.width&&n.measured.height&&(f?.includeHiddenNodes||!n.hidden)&&(!r||r.has(n.id)))l.set(n.id,n)}),l}async function fN({nodes:u,width:f,height:l,panZoom:r,minZoom:n,maxZoom:i},y){if(u.size===0)return Promise.resolve(!0);let _=gB(u,y),$=ny(_),A=T$($,f,l,y?.minZoom??n,y?.maxZoom??i,y?.padding??0.1);return await r.setViewport(A,{duration:y?.duration,ease:y?.ease,interpolate:y?.interpolate}),Promise.resolve(!0)}function bc({nodeId:u,nextPosition:f,nodeLookup:l,nodeOrigin:r=[0,0],nodeExtent:n,onError:i}){let y=l.get(u),_=y.parentId?l.get(y.parentId):void 0,{x:$,y:A}=_?_.internals.positionAbsolute:{x:0,y:0},c=y.origin??r,j=y.extent||n;if(y.extent==="parent"&&!y.expandParent)if(!_)i?.("005",Fr.error005());else{let U=_.measured.width,Q=_.measured.height;if(U&&Q)j=[[$,A],[$+U,A+Q]]}else if(_&&ly(y.extent))j=[[y.extent[0][0]+$,y.extent[0][1]+A],[y.extent[1][0]+$,y.extent[1][1]+A]];let F=ly(j)?m1(f,j,y.measured):f;if(y.measured.width===void 0||y.measured.height===void 0)i?.("015",Fr.error015());return{position:{x:F.x-$+(y.measured.width??0)*c[0],y:F.y-A+(y.measured.height??0)*c[1]},positionAbsolute:F}}async function lN({nodesToRemove:u=[],edgesToRemove:f=[],nodes:l,edges:r,onBeforeDelete:n}){let i=new Set(u.map((F)=>F.id)),y=[];for(let F of l){if(F.deletable===!1)continue;let U=i.has(F.id),Q=!U&&F.parentId&&y.find((L)=>L.id===F.parentId);if(U||Q)y.push(F)}let _=new Set(f.map((F)=>F.id)),$=r.filter((F)=>F.deletable!==!1),c=uN(y,$);for(let F of $)if(_.has(F.id)&&!c.find((Q)=>Q.id===F.id))c.push(F);if(!n)return{edges:c,nodes:y};let j=await n({nodes:y,edges:c});if(typeof j==="boolean")return j?{edges:c,nodes:y}:{edges:[],nodes:[]};return j}var fy=(u,f=0,l=1)=>Math.min(Math.max(u,f),l),m1=(u={x:0,y:0},f,l)=>({x:fy(u.x,f[0][0],f[1][0]-(l?.width??0)),y:fy(u.y,f[0][1],f[1][1]-(l?.height??0))});function rN(u,f,l){let{width:r,height:n}=A0(l),{x:i,y}=l.internals.positionAbsolute;return m1(u,[[i,y],[i+r,y+n]],f)}var Rq=(u,f,l)=>{if(ul)return-fy(Math.abs(u-l),1,f)/f;return 0},nN=(u,f,l=15,r=40)=>{let n=Rq(u.x,r,f.width-r)*l,i=Rq(u.y,r,f.height-r)*l;return[n,i]},b6=(u,f)=>({x:Math.min(u.x,f.x),y:Math.min(u.y,f.y),x2:Math.max(u.x2,f.x2),y2:Math.max(u.y2,f.y2)}),pc=({x:u,y:f,width:l,height:r})=>({x:u,y:f,x2:u+l,y2:f+r}),v6=({x:u,y:f,x2:l,y2:r})=>({x:u,y:f,width:l-u,height:r-f}),P1=(u,f=[0,0])=>{let{x:l,y:r}=xc(u)?u.internals.positionAbsolute:z$(u,f);return{x:l,y:r,width:u.measured?.width??u.width??u.initialWidth??0,height:u.measured?.height??u.height??u.initialHeight??0}},x6=(u,f=[0,0])=>{let{x:l,y:r}=xc(u)?u.internals.positionAbsolute:z$(u,f);return{x:l,y:r,x2:l+(u.measured?.width??u.width??u.initialWidth??0),y2:r+(u.measured?.height??u.height??u.initialHeight??0)}},vc=(u,f)=>v6(b6(pc(u),pc(f))),iy=(u,f)=>{let l=Math.max(0,Math.min(u.x+u.width,f.x+f.width)-Math.max(u.x,f.x)),r=Math.max(0,Math.min(u.y+u.height,f.y+f.height)-Math.max(u.y,f.y));return Math.ceil(l*r)},kc=(u)=>Er(u.width)&&Er(u.height)&&Er(u.x)&&Er(u.y),Er=(u)=>!isNaN(u)&&isFinite(u),Ic=(u,f)=>{},yy=(u,f=[1,1])=>{return{x:f[0]*Math.round(u.x/f[0]),y:f[1]*Math.round(u.y/f[1])}},_y=({x:u,y:f},[l,r,n],i=!1,y=[1,1])=>{let _={x:(u-l)/n,y:(f-r)/n};return i?yy(_,y):_},G$=({x:u,y:f},[l,r,n])=>{return{x:u*n+l,y:f*n+r}};function ei(u,f){if(typeof u==="number")return Math.floor((f-f/(1+u))*0.5);if(typeof u==="string"&&u.endsWith("px")){let l=parseFloat(u);if(!Number.isNaN(l))return Math.floor(l)}if(typeof u==="string"&&u.endsWith("%")){let l=parseFloat(u);if(!Number.isNaN(l))return Math.floor(f*l*0.01)}return console.error(`[React Flow] The padding value "${u}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function sB(u,f,l){if(typeof u==="string"||typeof u==="number"){let r=ei(u,l),n=ei(u,f);return{top:r,right:n,bottom:r,left:n,x:n*2,y:r*2}}if(typeof u==="object"){let r=ei(u.top??u.y??0,l),n=ei(u.bottom??u.y??0,l),i=ei(u.left??u.x??0,f),y=ei(u.right??u.x??0,f);return{top:r,right:y,bottom:n,left:i,x:i+y,y:r+n}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function aB(u,f,l,r,n,i){let{x:y,y:_}=G$(u,[f,l,r]),{x:$,y:A}=G$({x:u.x+u.width,y:u.y+u.height},[f,l,r]),c=n-$,j=i-A;return{left:Math.floor(y),top:Math.floor(_),right:Math.floor(c),bottom:Math.floor(j)}}var T$=(u,f,l,r,n,i)=>{let y=sB(i,f,l),_=(f-y.x)/u.width,$=(l-y.y)/u.height,A=Math.min(_,$),c=fy(A,r,n),j=u.x+u.width/2,F=u.y+u.height/2,U=f/2-j*c,Q=l/2-F*c,L=aB(u,U,Q,c,f,l),w={left:Math.min(L.left-y.left,0),top:Math.min(L.top-y.top,0),right:Math.min(L.right-y.right,0),bottom:Math.min(L.bottom-y.bottom,0)};return{x:U-w.left+w.right,y:Q-w.top+w.bottom,zoom:c}},$y=()=>typeof navigator<"u"&&navigator?.userAgent?.indexOf("Mac")>=0;function ly(u){return u!==void 0&&u!==null&&u!=="parent"}function A0(u){return{width:u.measured?.width??u.width??u.initialWidth??0,height:u.measured?.height??u.height??u.initialHeight??0}}function gc(u){return(u.measured?.width??u.width??u.initialWidth)!==void 0&&(u.measured?.height??u.height??u.initialHeight)!==void 0}function sc(u,f={width:0,height:0},l,r,n){let i={...u},y=r.get(l);if(y){let _=y.origin||n;i.x+=y.internals.positionAbsolute.x-(f.width??0)*_[0],i.y+=y.internals.positionAbsolute.y-(f.height??0)*_[1]}return i}function ac(u,f){if(u.size!==f.size)return!1;for(let l of u)if(!f.has(l))return!1;return!0}function iN(){let u,f;return{promise:new Promise((r,n)=>{u=r,f=n}),resolve:u,reject:f}}function yN(u){return{...Pc,...u||{}}}function K$(u,{snapGrid:f=[0,0],snapToGrid:l=!1,transform:r,containerBounds:n}){let{x:i,y}=Zr(u),_=_y({x:i-(n?.left??0),y:y-(n?.top??0)},r),{x:$,y:A}=l?yy(_,f):_;return{xSnapped:$,ySnapped:A,..._}}var k6=(u)=>({width:u.offsetWidth,height:u.offsetHeight}),oc=(u)=>u?.getRootNode?.()||window?.document,oB=["INPUT","SELECT","TEXTAREA"];function dc(u){let f=u.composedPath?.()?.[0]||u.target;if(f?.nodeType!==1)return!1;return oB.includes(f.nodeName)||f.hasAttribute("contenteditable")||!!f.closest(".nokey")}var ec=(u)=>("clientX"in u),Zr=(u,f)=>{let l=ec(u),r=l?u.clientX:u.touches?.[0].clientX,n=l?u.clientY:u.touches?.[0].clientY;return{x:r-(f?.left??0),y:n-(f?.top??0)}},xq=(u,f,l,r,n)=>{let i=f.querySelectorAll(`.${u}`);if(!i||!i.length)return null;return Array.from(i).map((y)=>{let _=y.getBoundingClientRect();return{id:y.getAttribute("data-handleid"),type:u,nodeId:n,position:y.getAttribute("data-handlepos"),x:(_.left-l.left)/r,y:(_.top-l.top)/r,...k6(y)}})};function I6({sourceX:u,sourceY:f,targetX:l,targetY:r,sourceControlX:n,sourceControlY:i,targetControlX:y,targetControlY:_}){let $=u*0.125+n*0.375+y*0.375+l*0.125,A=f*0.125+i*0.375+_*0.375+r*0.125,c=Math.abs($-u),j=Math.abs(A-f);return[$,A,c,j]}function C6(u,f){if(u>=0)return 0.5*u;return f*25*Math.sqrt(-u)}function hq({pos:u,x1:f,y1:l,x2:r,y2:n,c:i}){switch(u){case Lu.Left:return[f-C6(f-r,i),l];case Lu.Right:return[f+C6(r-f,i),l];case Lu.Top:return[f,l-C6(l-n,i)];case Lu.Bottom:return[f,l+C6(n-l,i)]}}function g6({sourceX:u,sourceY:f,sourcePosition:l=Lu.Bottom,targetX:r,targetY:n,targetPosition:i=Lu.Top,curvature:y=0.25}){let[_,$]=hq({pos:l,x1:u,y1:f,x2:r,y2:n,c:y}),[A,c]=hq({pos:i,x1:r,y1:n,x2:u,y2:f,c:y}),[j,F,U,Q]=I6({sourceX:u,sourceY:f,targetX:r,targetY:n,sourceControlX:_,sourceControlY:$,targetControlX:A,targetControlY:c});return[`M${u},${f} C${_},${$} ${A},${c} ${r},${n}`,j,F,U,Q]}function u9({sourceX:u,sourceY:f,targetX:l,targetY:r}){let n=Math.abs(l-u)/2,i=l0}var dB=({source:u,sourceHandle:f,target:l,targetHandle:r})=>`xy-edge__${u}${f||""}-${l}${r||""}`,eB=(u,f)=>{return f.some((l)=>l.source===u.source&&l.target===u.target&&(l.sourceHandle===u.sourceHandle||!l.sourceHandle&&!u.sourceHandle)&&(l.targetHandle===u.targetHandle||!l.targetHandle&&!u.targetHandle))},f9=(u,f,l={})=>{if(!u.source||!u.target)return Ic("006",Fr.error006()),f;let r=l.getEdgeId||dB,n;if(Rc(u))n={...u};else n={...u,id:r(u)};if(eB(n,f))return f;if(n.sourceHandle===null)delete n.sourceHandle;if(n.targetHandle===null)delete n.targetHandle;return f.concat(n)};function s6({sourceX:u,sourceY:f,targetX:l,targetY:r}){let[n,i,y,_]=u9({sourceX:u,sourceY:f,targetX:l,targetY:r});return[`M ${u},${f}L ${l},${r}`,n,i,y,_]}var bq={[Lu.Left]:{x:-1,y:0},[Lu.Right]:{x:1,y:0},[Lu.Top]:{x:0,y:-1},[Lu.Bottom]:{x:0,y:1}},uV=({source:u,sourcePosition:f=Lu.Bottom,target:l})=>{if(f===Lu.Left||f===Lu.Right)return u.xMath.sqrt(Math.pow(f.x-u.x,2)+Math.pow(f.y-u.y,2));function fV({source:u,sourcePosition:f=Lu.Bottom,target:l,targetPosition:r=Lu.Top,center:n,offset:i,stepPosition:y}){let _=bq[f],$=bq[r],A={x:u.x+_.x*i,y:u.y+_.y*i},c={x:l.x+$.x*i,y:l.y+$.y*i},j=uV({source:A,sourcePosition:f,target:c}),F=j.x!==0?"x":"y",U=j[F],Q=[],L,w,J={x:0,y:0},N={x:0,y:0},[,,q,W]=u9({sourceX:u.x,sourceY:u.y,targetX:l.x,targetY:l.y});if(_[F]*$[F]===-1){if(F==="x")L=n.x??A.x+(c.x-A.x)*y,w=n.y??(A.y+c.y)/2;else L=n.x??(A.x+c.x)/2,w=n.y??A.y+(c.y-A.y)*y;let E=[{x:L,y:A.y},{x:L,y:c.y}],D=[{x:A.x,y:w},{x:c.x,y:w}];if(_[F]===U)Q=F==="x"?E:D;else Q=F==="x"?D:E}else{let E=[{x:A.x,y:c.y}],D=[{x:c.x,y:A.y}];if(F==="x")Q=_.x===U?D:E;else Q=_.y===U?E:D;if(f===r){let O=Math.abs(u[F]-l[F]);if(O<=i){let m=Math.min(i-1,i-O);if(_[F]===U)J[F]=(A[F]>u[F]?-1:1)*m;else N[F]=(c[F]>l[F]?-1:1)*m}}if(f!==r){let O=F==="x"?"y":"x",m=_[F]===$[O],X=A[O]>c[O],v=A[O]=p)L=(h.x+V.x)/2,w=Q[0].y;else L=Q[0].x,w=(h.y+V.y)/2}let z={x:A.x+J.x,y:A.y+J.y},Z={x:c.x+N.x,y:c.y+N.y};return[[u,...z.x!==Q[0].x||z.y!==Q[0].y?[z]:[],...Q,...Z.x!==Q[Q.length-1].x||Z.y!==Q[Q.length-1].y?[Z]:[],l],L,w,q,W]}function lV(u,f,l,r){let n=Math.min(vq(u,f)/2,vq(f,l)/2,r),{x:i,y}=f;if(u.x===i&&i===l.x||u.y===y&&y===l.y)return`L${i} ${y}`;if(u.y===y){let A=u.xl.id===f))||null}function a6(u,f){if(!u)return"";if(typeof u==="string")return u;return`${f?`${f}__`:""}${Object.keys(u).sort().map((r)=>`${r}=${u[r]}`).join("&")}`}function AN(u,{id:f,defaultColor:l,defaultMarkerStart:r,defaultMarkerEnd:n}){let i=new Set;return u.reduce((y,_)=>{return[_.markerStart||r,_.markerEnd||n].forEach(($)=>{if($&&typeof $==="object"){let A=a6($,f);if(!i.has(A))y.push({id:A,color:$.color||l,...$}),i.add(A)}}),y},[]).sort((y,_)=>y.id.localeCompare(_.id))}var cN=1000,rV=10,l9={nodeOrigin:[0,0],nodeExtent:ry,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},nV={...l9,checkEquality:!0};function r9(u,f){let l={...u};for(let r in f)if(f[r]!==void 0)l[r]=f[r];return l}function jN(u,f,l){let r=r9(l9,l);for(let n of u.values())if(n.parentId)i9(n,u,f,r);else{let i=z$(n,r.nodeOrigin),y=ly(n.extent)?n.extent:r.nodeExtent,_=m1(i,y,A0(n));n.internals.positionAbsolute=_}}function iV(u,f){if(!u.handles)return!u.measured?void 0:f?.internals.handleBounds;let l=[],r=[];for(let n of u.handles){let i={id:n.id,width:n.width??1,height:n.height??1,nodeId:u.id,x:n.x,y:n.y,position:n.position,type:n.type};if(n.type==="source")l.push(i);else if(n.type==="target")r.push(i)}return{source:l,target:r}}function n9(u){return u==="manual"}function o6(u,f,l,r={}){let n=r9(nV,r),i={i:0},y=new Map(f),_=n?.elevateNodesOnSelect&&!n9(n.zIndexMode)?cN:0,$=u.length>0,A=!1;f.clear(),l.clear();for(let c of u){let j=y.get(c.id);if(n.checkEquality&&c===j?.internals.userNode)f.set(c.id,j);else{let F=z$(c,n.nodeOrigin),U=ly(c.extent)?c.extent:n.nodeExtent,Q=m1(F,U,A0(c));j={...n.defaults,...c,measured:{width:c.measured?.width,height:c.measured?.height},internals:{positionAbsolute:Q,handleBounds:iV(c,j),z:FN(c,_,n.zIndexMode),userNode:c}},f.set(c.id,j)}if((j.measured===void 0||j.measured.width===void 0||j.measured.height===void 0)&&!j.hidden)$=!1;if(c.parentId)i9(j,f,l,r,i);A||=c.selected??!1}return{nodesInitialized:$,hasSelectedNodes:A}}function yV(u,f){if(!u.parentId)return;let l=f.get(u.parentId);if(l)l.set(u.id,u);else f.set(u.parentId,new Map([[u.id,u]]))}function i9(u,f,l,r,n){let{elevateNodesOnSelect:i,nodeOrigin:y,nodeExtent:_,zIndexMode:$}=r9(l9,r),A=u.parentId,c=f.get(A);if(!c){console.warn(`Parent node ${A} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}if(yV(u,l),n&&!c.parentId&&c.internals.rootParentIndex===void 0&&$==="auto")c.internals.rootParentIndex=++n.i,c.internals.z=c.internals.z+n.i*rV;if(n&&c.internals.rootParentIndex!==void 0)n.i=c.internals.rootParentIndex;let j=i&&!n9($)?cN:0,{x:F,y:U,z:Q}=_V(u,c,y,_,j,$),{positionAbsolute:L}=u.internals,w=F!==L.x||U!==L.y;if(w||Q!==u.internals.z)f.set(u.id,{...u,internals:{...u.internals,positionAbsolute:w?{x:F,y:U}:L,z:Q}})}function FN(u,f,l){let r=Er(u.zIndex)?u.zIndex:0;if(n9(l))return r;return r+(u.selected?f:0)}function _V(u,f,l,r,n,i){let{x:y,y:_}=f.internals.positionAbsolute,$=A0(u),A=z$(u,l),c=ly(u.extent)?m1(A,u.extent,$):A,j=m1({x:y+c.x,y:_+c.y},r,$);if(u.extent==="parent")j=rN(j,$,f);let F=FN(u,n,i),U=f.internals.z??0;return{x:j.x,y:j.y,z:U>=F?U+1:F}}function d6(u,f,l,r=[0,0]){let n=[],i=new Map;for(let y of u){let _=f.get(y.parentId);if(!_)continue;let $=i.get(y.parentId)?.expandedRect??P1(_),A=vc($,y.rect);i.set(y.parentId,{expandedRect:A,parent:_})}if(i.size>0)i.forEach(({expandedRect:y,parent:_},$)=>{let A=_.internals.positionAbsolute,c=A0(_),j=_.origin??r,F=y.x0||U>0||w||J)n.push({id:$,type:"position",position:{x:_.position.x-F+w,y:_.position.y-U+J}}),l.get($)?.forEach((N)=>{if(!u.some((q)=>q.id===N.id))n.push({id:N.id,type:"position",position:{x:N.position.x+F,y:N.position.y+U}})});if(c.width0){let U=d6(F,f,l,n);A.push(...U)}return{changes:A,updatedInternals:$}}async function UN({delta:u,panZoom:f,transform:l,translateExtent:r,width:n,height:i}){if(!f||!u.x&&!u.y)return Promise.resolve(!1);let y=await f.setViewportConstrained({x:l[0]+u.x,y:l[1]+u.y,zoom:l[2]},[[0,0],[n,i]],r),_=!!y&&(y.x!==l[0]||y.y!==l[1]||y.k!==l[2]);return Promise.resolve(_)}function sq(u,f,l,r,n,i){let y=n,_=r.get(y)||new Map;r.set(y,_.set(l,f)),y=`${n}-${u}`;let $=r.get(y)||new Map;if(r.set(y,$.set(l,f)),i){y=`${n}-${u}-${i}`;let A=r.get(y)||new Map;r.set(y,A.set(l,f))}}function y9(u,f,l){u.clear(),f.clear();for(let r of l){let{source:n,target:i,sourceHandle:y=null,targetHandle:_=null}=r,$={edgeId:r.id,source:n,target:i,sourceHandle:y,targetHandle:_},A=`${n}-${y}--${i}-${_}`,c=`${i}-${_}--${n}-${y}`;sq("source",$,c,u,n,y),sq("target",$,A,u,i,_),f.set(r.id,r)}}function QN(u,f){if(!u.parentId)return!1;let l=f.get(u.parentId);if(!l)return!1;if(l.selected)return!0;return QN(l,f)}function aq(u,f,l){let r=u;do{if(r?.matches?.(f))return!0;if(r===l)return!1;r=r?.parentElement}while(r);return!1}function $V(u,f,l,r){let n=new Map;for(let[i,y]of u)if((y.selected||y.id===r)&&(!y.parentId||!QN(y,u))&&(y.draggable||f&&typeof y.draggable>"u")){let _=u.get(i);if(_)n.set(i,{id:i,position:_.position||{x:0,y:0},distance:{x:l.x-_.internals.positionAbsolute.x,y:l.y-_.internals.positionAbsolute.y},extent:_.extent,parentId:_.parentId,origin:_.origin,expandParent:_.expandParent,internals:{positionAbsolute:_.internals.positionAbsolute||{x:0,y:0}},measured:{width:_.measured.width??0,height:_.measured.height??0}})}return n}function Xc({nodeId:u,dragItems:f,nodeLookup:l,dragging:r=!0}){let n=[];for(let[y,_]of f){let $=l.get(y)?.internals.userNode;if($)n.push({...$,position:_.position,dragging:r})}if(!u)return[n[0],n];let i=l.get(u)?.internals.userNode;return[!i?n[0]:{...i,position:f.get(u)?.position||i.position,dragging:r},n]}function tV({dragItems:u,snapGrid:f,x:l,y:r}){let n=u.values().next().value;if(!n)return null;let i={x:l-n.distance.x,y:r-n.distance.y},y=yy(i,f);return{x:y.x-i.x,y:y.y-i.y}}function qN({onNodeMouseDown:u,getStoreItems:f,onDragStart:l,onDrag:r,onDragStop:n}){let i={x:null,y:null},y=0,_=new Map,$=!1,A={x:0,y:0},c=null,j=!1,F=null,U=!1,Q=!1,L=null;function w({noDragClassName:N,handleSelector:q,domNode:W,isSelectable:z,nodeId:Z,nodeClickDistance:H=0}){F=sf(W);function E({x:Y,y:p}){let{nodeLookup:O,nodeExtent:m,snapGrid:X,snapToGrid:v,nodeOrigin:T,onNodeDrag:S,onSelectionDrag:k,onError:I,updateNodePositions:b}=f();i={x:Y,y:p};let o=!1,g=_.size>1,x=g&&m?pc(ny(_)):null,fu=g&&v?tV({dragItems:_,snapGrid:X,x:Y,y:p}):null;for(let[$u,tu]of _){if(!O.has($u))continue;let ju={x:Y-tu.distance.x,y:p-tu.distance.y};if(v)ju=fu?{x:Math.round(ju.x+fu.x),y:Math.round(ju.y+fu.y)}:yy(ju,X);let Gu=null;if(g&&m&&!tu.extent&&x){let{positionAbsolute:e}=tu.internals,uu=e.x-x.x+m[0][0],wu=e.x+tu.measured.width-x.x2+m[1][0],s=e.y-x.y+m[0][1],Qu=e.y+tu.measured.height-x.y2+m[1][1];Gu=[[uu,s],[wu,Qu]]}let{position:qu,positionAbsolute:P}=bc({nodeId:$u,nextPosition:ju,nodeLookup:O,nodeExtent:Gu?Gu:m,nodeOrigin:T,onError:I});o=o||tu.position.x!==qu.x||tu.position.y!==qu.y,tu.position=qu,tu.internals.positionAbsolute=P}if(Q=Q||o,!o)return;if(b(_,!0),L&&(r||S||!Z&&k)){let[$u,tu]=Xc({nodeId:Z,dragItems:_,nodeLookup:O});if(r?.(L,_,$u,tu),S?.(L,$u,tu),!Z)k?.(L,tu)}}async function D(){if(!c)return;let{transform:Y,panBy:p,autoPanSpeed:O,autoPanOnNodeDrag:m}=f();if(!m){$=!1,cancelAnimationFrame(y);return}let[X,v]=nN(A,c,O);if(X!==0||v!==0){if(i.x=(i.x??0)-X/Y[2],i.y=(i.y??0)-v/Y[2],await p({x:X,y:v}))E(i)}y=requestAnimationFrame(D)}function h(Y){let{nodeLookup:p,multiSelectionActive:O,nodesDraggable:m,transform:X,snapGrid:v,snapToGrid:T,selectNodesOnDrag:S,onNodeDragStart:k,onSelectionDragStart:I,unselectNodesAndEdges:b}=f();if(j=!0,(!S||!z)&&!O&&Z){if(!p.get(Z)?.selected)b()}if(z&&S&&Z)u?.(Z);let o=K$(Y.sourceEvent,{transform:X,snapGrid:v,snapToGrid:T,containerBounds:c});if(i=o,_=$V(p,m,o,Z),_.size>0&&(l||k||!Z&&I)){let[g,x]=Xc({nodeId:Z,dragItems:_,nodeLookup:p});if(l?.(Y.sourceEvent,_,g,x),k?.(Y.sourceEvent,g,x),!Z)I?.(Y.sourceEvent,x)}}let V=r$().clickDistance(H).on("start",(Y)=>{let{domNode:p,nodeDragThreshold:O,transform:m,snapGrid:X,snapToGrid:v}=f();if(c=p?.getBoundingClientRect()||null,U=!1,Q=!1,L=Y.sourceEvent,O===0)h(Y);i=K$(Y.sourceEvent,{transform:m,snapGrid:X,snapToGrid:v,containerBounds:c}),A=Zr(Y.sourceEvent,c)}).on("drag",(Y)=>{let{autoPanOnNodeDrag:p,transform:O,snapGrid:m,snapToGrid:X,nodeDragThreshold:v,nodeLookup:T}=f(),S=K$(Y.sourceEvent,{transform:O,snapGrid:m,snapToGrid:X,containerBounds:c});if(L=Y.sourceEvent,Y.sourceEvent.type==="touchmove"&&Y.sourceEvent.touches.length>1||Z&&!T.has(Z))U=!0;if(U)return;if(!$&&p&&j)$=!0,D();if(!j){let k=Zr(Y.sourceEvent,c),I=k.x-A.x,b=k.y-A.y;if(Math.sqrt(I*I+b*b)>v)h(Y)}if((i.x!==S.xSnapped||i.y!==S.ySnapped)&&_&&j)A=Zr(Y.sourceEvent,c),E(S)}).on("end",(Y)=>{if(!j||U)return;if($=!1,j=!1,cancelAnimationFrame(y),_.size>0){let{nodeLookup:p,updateNodePositions:O,onNodeDragStop:m,onSelectionDragStop:X}=f();if(Q)O(_,!1),Q=!1;if(n||m||!Z&&X){let[v,T]=Xc({nodeId:Z,dragItems:_,nodeLookup:p,dragging:!1});if(n?.(Y.sourceEvent,_,v,T),m?.(Y.sourceEvent,v,T),!Z)X?.(Y.sourceEvent,T)}}}).filter((Y)=>{let p=Y.target;return!Y.button&&(!N||!aq(p,`.${N}`,W))&&(!q||aq(p,q,W))});F.call(V)}function J(){F?.on(".drag",null)}return{update:w,destroy:J}}function AV(u,f,l){let r=[],n={x:u.x-l,y:u.y-l,width:l*2,height:l*2};for(let i of f.values())if(iy(n,P1(i))>0)r.push(i);return r}var cV=250;function jV(u,f,l,r){let n=[],i=1/0,y=AV(u,l,f+cV);for(let _ of y){let $=[..._.internals.handleBounds?.source??[],..._.internals.handleBounds?.target??[]];for(let A of $){if(r.nodeId===A.nodeId&&r.type===A.type&&r.id===A.id)continue;let{x:c,y:j}=pn(_,A,A.position,!0),F=Math.sqrt(Math.pow(c-u.x,2)+Math.pow(j-u.y,2));if(F>f)continue;if(F1){let _=r.type==="source"?"target":"source";return n.find(($)=>$.type===_)??n[0]}return n[0]}function NN(u,f,l,r,n,i=!1){let y=r.get(u);if(!y)return null;let _=n==="strict"?y.internals.handleBounds?.[f]:[...y.internals.handleBounds?.source??[],...y.internals.handleBounds?.target??[]],$=(l?_?.find((A)=>A.id===l):_?.[0])??null;return $&&i?{...$,...pn(y,$,$.position,!0)}:$}function WN(u,f){if(u)return u;else if(f?.classList.contains("target"))return"target";else if(f?.classList.contains("source"))return"source";return null}function FV(u,f){let l=null;if(f)l=!0;else if(u&&!f)l=!1;return l}var LN=()=>!0;function JV(u,{connectionMode:f,connectionRadius:l,handleId:r,nodeId:n,edgeUpdaterType:i,isTarget:y,domNode:_,nodeLookup:$,lib:A,autoPanOnConnect:c,flowId:j,panBy:F,cancelConnection:U,onConnectStart:Q,onConnect:L,onConnectEnd:w,isValidConnection:J=LN,onReconnectEnd:N,updateConnection:q,getTransform:W,getFromHandle:z,autoPanSpeed:Z,dragThreshold:H=1,handleDomNode:E}){let D=oc(u.target),h=0,V,{x:Y,y:p}=Zr(u),O=WN(i,E),m=_?.getBoundingClientRect(),X=!1;if(!m||!O)return;let v=NN(n,O,r,$,f);if(!v)return;let T=Zr(u,m),S=!1,k=null,I=!1,b=null;function o(){if(!c||!m)return;let[qu,P]=nN(T,m,Z);F({x:qu,y:P}),h=requestAnimationFrame(o)}let g={...v,nodeId:n,type:O,position:v.position},x=$.get(n),$u={inProgress:!0,isValid:null,from:pn(x,g,Lu.Left,!0),fromHandle:g,fromPosition:g.position,fromNode:x,to:T,toHandle:null,toPosition:Cq[g.position],toNode:null,pointer:T};function tu(){X=!0,q($u),Q?.(u,{nodeId:n,handleId:r,handleType:O})}if(H===0)tu();function ju(qu){if(!X){let{x:Qu,y:zu}=Zr(qu),Ou=Qu-Y,bu=zu-p;if(!(Ou*Ou+bu*bu>H*H))return;tu()}if(!z()||!g){Gu(qu);return}let P=W();if(T=Zr(qu,m),V=jV(_y(T,P,!1,[1,1]),l,$,g),!S)o(),S=!0;let e=wN(qu,{handle:V,connectionMode:f,fromNodeId:n,fromHandleId:r,fromType:y?"target":"source",isValidConnection:J,doc:D,lib:A,flowId:j,nodeLookup:$});b=e.handleDomNode,k=e.connection,I=FV(!!V,e.isValid);let uu=$.get(n),wu=uu?pn(uu,g,Lu.Left,!0):$u.from,s={...$u,from:wu,isValid:I,to:e.toHandle&&I?G$({x:e.toHandle.x,y:e.toHandle.y},P):T,toHandle:e.toHandle,toPosition:I&&e.toHandle?e.toHandle.position:Cq[g.position],toNode:e.toHandle?$.get(e.toHandle.nodeId):null,pointer:T};q(s),$u=s}function Gu(qu){if("touches"in qu&&qu.touches.length>0)return;if(X){if((V||b)&&k&&I)L?.(k);let{inProgress:P,...e}=$u,uu={...e,toPosition:$u.toHandle?$u.toPosition:null};if(w?.(qu,uu),i)N?.(qu,uu)}U(),cancelAnimationFrame(h),S=!1,I=!1,k=null,b=null,D.removeEventListener("mousemove",ju),D.removeEventListener("mouseup",Gu),D.removeEventListener("touchmove",ju),D.removeEventListener("touchend",Gu)}D.addEventListener("mousemove",ju),D.addEventListener("mouseup",Gu),D.addEventListener("touchmove",ju),D.addEventListener("touchend",Gu)}function wN(u,{handle:f,connectionMode:l,fromNodeId:r,fromHandleId:n,fromType:i,doc:y,lib:_,flowId:$,isValidConnection:A=LN,nodeLookup:c}){let j=i==="target",F=f?y.querySelector(`.${_}-flow__handle[data-id="${$}-${f?.nodeId}-${f?.id}-${f?.type}"]`):null,{x:U,y:Q}=Zr(u),L=y.elementFromPoint(U,Q),w=L?.classList.contains(`${_}-flow__handle`)?L:F,J={handleDomNode:w,isValid:!1,connection:null,toHandle:null};if(w){let N=WN(void 0,w),q=w.getAttribute("data-nodeid"),W=w.getAttribute("data-handleid"),z=w.classList.contains("connectable"),Z=w.classList.contains("connectableend");if(!q||!N)return J;let H={source:j?q:r,sourceHandle:j?W:n,target:j?r:q,targetHandle:j?n:W};J.connection=H;let D=z&&Z&&(l===Yn.Strict?j&&N==="source"||!j&&N==="target":q!==r||W!==n);J.isValid=D&&A(H),J.toHandle=NN(q,N,W,c,l,!0)}return J}var e6={onPointerDown:JV,isValid:wN};function KN({domNode:u,panZoom:f,getTransform:l,getViewScale:r}){let n=sf(u);function i({translateExtent:_,width:$,height:A,zoomStep:c=1,pannable:j=!0,zoomable:F=!0,inversePan:U=!1}){let Q=(q)=>{if(q.sourceEvent.type!=="wheel"||!f)return;let W=l(),z=q.sourceEvent.ctrlKey&&$y()?10:1,Z=-q.sourceEvent.deltaY*(q.sourceEvent.deltaMode===1?0.05:q.sourceEvent.deltaMode?1:0.002)*c,H=W[2]*Math.pow(2,Z*z);f.scaleTo(H)},L=[0,0],w=(q)=>{if(q.sourceEvent.type==="mousedown"||q.sourceEvent.type==="touchstart")L=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY]},J=(q)=>{let W=l();if(q.sourceEvent.type!=="mousemove"&&q.sourceEvent.type!=="touchmove"||!f)return;let z=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY],Z=[z[0]-L[0],z[1]-L[1]];L=z;let H=r()*Math.max(W[2],Math.log(W[2]))*(U?-1:1),E={x:W[0]-Z[0]*H,y:W[1]-Z[1]*H},D=[[0,0],[$,A]];f.setViewportConstrained({x:E.x,y:E.y,zoom:W[2]},D,_)},N=w$().on("start",w).on("zoom",j?J:null).on("zoom.wheel",F?Q:null);n.call(N,{})}function y(){n.on("zoom",null)}return{update:i,destroy:y,pointer:Kl}}var u8=(u)=>({x:u.x,y:u.y,zoom:u.k}),Yc=({x:u,y:f,zoom:l})=>Y1.translate(u,f).scale(l),uy=(u,f)=>u.target.closest(`.${f}`),GN=(u,f)=>f===2&&Array.isArray(u)&&u.includes(2),UV=(u)=>((u*=2)<=1?u*u*u:(u-=2)*u*u+2)/2,Sc=(u,f=0,l=UV,r=()=>{})=>{let n=typeof f==="number"&&f>0;if(!n)r();return n?u.transition().duration(f).ease(l).on("end",r):u},zN=(u)=>{let f=u.ctrlKey&&$y()?10:1;return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*f};function QV({zoomPanValues:u,noWheelClassName:f,d3Selection:l,d3Zoom:r,panOnScrollMode:n,panOnScrollSpeed:i,zoomOnPinch:y,onPanZoomStart:_,onPanZoom:$,onPanZoomEnd:A}){return(c)=>{if(uy(c,f)){if(c.ctrlKey)c.preventDefault();return!1}c.preventDefault(),c.stopImmediatePropagation();let j=l.property("__zoom").k||1;if(c.ctrlKey&&y){let w=Kl(c),J=zN(c),N=j*Math.pow(2,J);r.scaleTo(l,N,w,c);return}let F=c.deltaMode===1?20:1,U=n===R0.Vertical?0:c.deltaX*F,Q=n===R0.Horizontal?0:c.deltaY*F;if(!$y()&&c.shiftKey&&n!==R0.Vertical)U=c.deltaY*F,Q=0;r.translateBy(l,-(U/j)*i,-(Q/j)*i,{internal:!0});let L=u8(l.property("__zoom"));if(clearTimeout(u.panScrollTimeout),!u.isPanScrolling)u.isPanScrolling=!0,_?.(c,L);else $?.(c,L),u.panScrollTimeout=setTimeout(()=>{A?.(c,L),u.isPanScrolling=!1},150)}}function qV({noWheelClassName:u,preventScrolling:f,d3ZoomHandler:l}){return function(r,n){let i=r.type==="wheel",y=!f&&i&&!r.ctrlKey,_=uy(r,u);if(r.ctrlKey&&i&&_)r.preventDefault();if(y||_)return null;r.preventDefault(),l.call(this,r,n)}}function NV({zoomPanValues:u,onDraggingChange:f,onPanZoomStart:l}){return(r)=>{if(r.sourceEvent?.internal)return;let n=u8(r.transform);if(u.mouseButton=r.sourceEvent?.button||0,u.isZoomingOrPanning=!0,u.prevViewport=n,r.sourceEvent?.type==="mousedown")f(!0);if(l)l?.(r.sourceEvent,n)}}function WV({zoomPanValues:u,panOnDrag:f,onPaneContextMenu:l,onTransformChange:r,onPanZoom:n}){return(i)=>{if(u.usedRightMouseButton=!!(l&&GN(f,u.mouseButton??0)),!i.sourceEvent?.sync)r([i.transform.x,i.transform.y,i.transform.k]);if(n&&!i.sourceEvent?.internal)n?.(i.sourceEvent,u8(i.transform))}}function LV({zoomPanValues:u,panOnDrag:f,panOnScroll:l,onDraggingChange:r,onPanZoomEnd:n,onPaneContextMenu:i}){return(y)=>{if(y.sourceEvent?.internal)return;if(u.isZoomingOrPanning=!1,i&&GN(f,u.mouseButton??0)&&!u.usedRightMouseButton&&y.sourceEvent)i(y.sourceEvent);if(u.usedRightMouseButton=!1,r(!1),n){let _=u8(y.transform);u.prevViewport=_,clearTimeout(u.timerId),u.timerId=setTimeout(()=>{n?.(y.sourceEvent,_)},l?150:0)}}}function wV({zoomActivationKeyPressed:u,zoomOnScroll:f,zoomOnPinch:l,panOnDrag:r,panOnScroll:n,zoomOnDoubleClick:i,userSelectionActive:y,noWheelClassName:_,noPanClassName:$,lib:A,connectionInProgress:c}){return(j)=>{let F=u||f,U=l&&j.ctrlKey,Q=j.type==="wheel";if(j.button===1&&j.type==="mousedown"&&(uy(j,`${A}-flow__node`)||uy(j,`${A}-flow__edge`)))return!0;if(!r&&!F&&!n&&!i&&!l)return!1;if(y)return!1;if(c&&!Q)return!1;if(uy(j,_)&&Q)return!1;if(uy(j,$)&&(!Q||n&&Q&&!u))return!1;if(!l&&j.ctrlKey&&Q)return!1;if(!l&&j.type==="touchstart"&&j.touches?.length>1)return j.preventDefault(),!1;if(!F&&!n&&!U&&Q)return!1;if(!r&&(j.type==="mousedown"||j.type==="touchstart"))return!1;if(Array.isArray(r)&&!r.includes(j.button)&&j.type==="mousedown")return!1;let L=Array.isArray(r)&&r.includes(j.button)||!j.button||j.button<=1;return(!j.ctrlKey||Q)&&L}}function TN({domNode:u,minZoom:f,maxZoom:l,translateExtent:r,viewport:n,onPanZoom:i,onPanZoomStart:y,onPanZoomEnd:_,onDraggingChange:$}){let A={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},c=u.getBoundingClientRect(),j=w$().scaleExtent([f,l]).translateExtent(r),F=sf(u).call(j);N({x:n.x,y:n.y,zoom:fy(n.zoom,f,l)},[[0,0],[c.width,c.height]],r);let U=F.on("wheel.zoom"),Q=F.on("dblclick.zoom");j.wheelDelta(zN);function L(V,Y){if(F)return new Promise((p)=>{j?.interpolate(Y?.interpolate==="linear"?$0:D1).transform(Sc(F,Y?.duration,Y?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function w({noWheelClassName:V,noPanClassName:Y,onPaneContextMenu:p,userSelectionActive:O,panOnScroll:m,panOnDrag:X,panOnScrollMode:v,panOnScrollSpeed:T,preventScrolling:S,zoomOnPinch:k,zoomOnScroll:I,zoomOnDoubleClick:b,zoomActivationKeyPressed:o,lib:g,onTransformChange:x,connectionInProgress:fu,paneClickDistance:$u,selectionOnDrag:tu}){if(O&&!A.isZoomingOrPanning)J();let ju=m&&!o&&!O;j.clickDistance(tu?1/0:!Er($u)||$u<0?0:$u);let Gu=ju?QV({zoomPanValues:A,noWheelClassName:V,d3Selection:F,d3Zoom:j,panOnScrollMode:v,panOnScrollSpeed:T,zoomOnPinch:k,onPanZoomStart:y,onPanZoom:i,onPanZoomEnd:_}):qV({noWheelClassName:V,preventScrolling:S,d3ZoomHandler:U});if(F.on("wheel.zoom",Gu,{passive:!1}),!O){let P=NV({zoomPanValues:A,onDraggingChange:$,onPanZoomStart:y});j.on("start",P);let e=WV({zoomPanValues:A,panOnDrag:X,onPaneContextMenu:!!p,onPanZoom:i,onTransformChange:x});j.on("zoom",e);let uu=LV({zoomPanValues:A,panOnDrag:X,panOnScroll:m,onPaneContextMenu:p,onPanZoomEnd:_,onDraggingChange:$});j.on("end",uu)}let qu=wV({zoomActivationKeyPressed:o,panOnDrag:X,zoomOnScroll:I,panOnScroll:m,zoomOnDoubleClick:b,zoomOnPinch:k,userSelectionActive:O,noPanClassName:Y,noWheelClassName:V,lib:g,connectionInProgress:fu});if(j.filter(qu),b)F.on("dblclick.zoom",Q);else F.on("dblclick.zoom",null)}function J(){j.on("zoom",null)}async function N(V,Y,p){let O=Yc(V),m=j?.constrain()(O,Y,p);if(m)await L(m);return new Promise((X)=>X(m))}async function q(V,Y){let p=Yc(V);return await L(p,Y),new Promise((O)=>O(p))}function W(V){if(F){let Y=Yc(V),p=F.property("__zoom");if(p.k!==V.zoom||p.x!==V.x||p.y!==V.y)j?.transform(F,Y,null,{sync:!0})}}function z(){let V=F?L$(F.node()):{x:0,y:0,k:1};return{x:V.x,y:V.y,zoom:V.k}}function Z(V,Y){if(F)return new Promise((p)=>{j?.interpolate(Y?.interpolate==="linear"?$0:D1).scaleTo(Sc(F,Y?.duration,Y?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function H(V,Y){if(F)return new Promise((p)=>{j?.interpolate(Y?.interpolate==="linear"?$0:D1).scaleBy(Sc(F,Y?.duration,Y?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function E(V){j?.scaleExtent(V)}function D(V){j?.translateExtent(V)}function h(V){let Y=!Er(V)||V<0?0:V;j?.clickDistance(Y)}return{update:w,destroy:J,setViewport:q,setViewportConstrained:N,getViewport:z,scaleTo:Z,scaleBy:H,setScaleExtent:E,setTranslateExtent:D,syncViewport:W,setClickDistance:h}}var mn;(function(u){u.Line="line",u.Handle="handle"})(mn||(mn={}));function KV({width:u,prevWidth:f,height:l,prevHeight:r,affectsX:n,affectsY:i}){let y=u-f,_=l-r,$=[y>0?1:y<0?-1:0,_>0?1:_<0?-1:0];if(y&&n)$[0]=$[0]*-1;if(_&&i)$[1]=$[1]*-1;return $}function oq(u){let f=u.includes("right")||u.includes("left"),l=u.includes("bottom")||u.includes("top"),r=u.includes("left"),n=u.includes("top");return{isHorizontal:f,isVertical:l,affectsX:r,affectsY:n}}function Dn(u,f){return Math.max(0,f-u)}function Xn(u,f){return Math.max(0,u-f)}function R6(u,f,l){return Math.max(0,f-u,u-l)}function dq(u,f){return u?!f:f}function GV(u,f,l,r,n,i,y,_){let{affectsX:$,affectsY:A}=f,{isHorizontal:c,isVertical:j}=f,F=c&&j,{xSnapped:U,ySnapped:Q}=l,{minWidth:L,maxWidth:w,minHeight:J,maxHeight:N}=r,{x:q,y:W,width:z,height:Z,aspectRatio:H}=u,E=Math.floor(c?U-u.pointerX:0),D=Math.floor(j?Q-u.pointerY:0),h=z+($?-E:E),V=Z+(A?-D:D),Y=-i[0]*z,p=-i[1]*Z,O=R6(h,L,w),m=R6(V,J,N);if(y){let T=0,S=0;if($&&E<0)T=Dn(q+E+Y,y[0][0]);else if(!$&&E>0)T=Xn(q+h+Y,y[1][0]);if(A&&D<0)S=Dn(W+D+p,y[0][1]);else if(!A&&D>0)S=Xn(W+V+p,y[1][1]);O=Math.max(O,T),m=Math.max(m,S)}if(_){let T=0,S=0;if($&&E>0)T=Xn(q+E,_[0][0]);else if(!$&&E<0)T=Dn(q+h,_[1][0]);if(A&&D>0)S=Xn(W+D,_[0][1]);else if(!A&&D<0)S=Dn(W+V,_[1][1]);O=Math.max(O,T),m=Math.max(m,S)}if(n){if(c){let T=R6(h/H,J,N)*H;if(O=Math.max(O,T),y){let S=0;if(!$&&!A||$&&!A&&F)S=Xn(W+p+h/H,y[1][1])*H;else S=Dn(W+p+($?E:-E)/H,y[0][1])*H;O=Math.max(O,S)}if(_){let S=0;if(!$&&!A||$&&!A&&F)S=Dn(W+h/H,_[1][1])*H;else S=Xn(W+($?E:-E)/H,_[0][1])*H;O=Math.max(O,S)}}if(j){let T=R6(V*H,L,w)/H;if(m=Math.max(m,T),y){let S=0;if(!$&&!A||A&&!$&&F)S=Xn(q+V*H+Y,y[1][0])/H;else S=Dn(q+(A?D:-D)*H+Y,y[0][0])/H;m=Math.max(m,S)}if(_){let S=0;if(!$&&!A||A&&!$&&F)S=Dn(q+V*H,_[1][0])/H;else S=Xn(q+(A?D:-D)*H,_[0][0])/H;m=Math.max(m,S)}}}if(D=D+(D<0?m:-m),E=E+(E<0?O:-O),n)if(F)if(h>V*H)D=(dq($,A)?-E:E)/H;else E=(dq($,A)?-D:D)*H;else if(c)D=E/H,A=$;else E=D*H,$=A;let X=$?q+E:q,v=A?W+D:W;return{width:z+($?-E:E),height:Z+(A?-D:D),x:i[0]*E*(!$?1:-1)+X,y:i[1]*D*(!A?1:-1)+v}}var EN={width:0,height:0,x:0,y:0},zV={...EN,pointerX:0,pointerY:0,aspectRatio:1};function TV(u){return[[0,0],[u.measured.width,u.measured.height]]}function EV(u,f,l){let r=f.position.x+u.position.x,n=f.position.y+u.position.y,i=u.measured.width??0,y=u.measured.height??0,_=l[0]*i,$=l[1]*y;return[[r-_,n-$],[r+i-_,n+y-$]]}function ZN({domNode:u,nodeId:f,getStoreItems:l,onChange:r,onEnd:n}){let i=sf(u),y={controlDirection:oq("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function _({controlPosition:A,boundaries:c,keepAspectRatio:j,resizeDirection:F,onResizeStart:U,onResize:Q,onResizeEnd:L,shouldResize:w}){let J={...EN},N={...zV};y={boundaries:c,resizeDirection:F,keepAspectRatio:j,controlDirection:oq(A)};let q=void 0,W=null,z=[],Z=void 0,H=void 0,E=void 0,D=!1,h=r$().on("start",(V)=>{let{nodeLookup:Y,transform:p,snapGrid:O,snapToGrid:m,nodeOrigin:X,paneDomNode:v}=l();if(q=Y.get(f),!q)return;W=v?.getBoundingClientRect()??null;let{xSnapped:T,ySnapped:S}=K$(V.sourceEvent,{transform:p,snapGrid:O,snapToGrid:m,containerBounds:W});if(J={width:q.measured.width??0,height:q.measured.height??0,x:q.position.x??0,y:q.position.y??0},N={...J,pointerX:T,pointerY:S,aspectRatio:J.width/J.height},Z=void 0,q.parentId&&(q.extent==="parent"||q.expandParent))Z=Y.get(q.parentId),H=Z&&q.extent==="parent"?TV(Z):void 0;z=[],E=void 0;for(let[k,I]of Y)if(I.parentId===f){if(z.push({id:k,position:{...I.position},extent:I.extent}),I.extent==="parent"||I.expandParent){let b=EV(I,q,I.origin??X);if(E)E=[[Math.min(b[0][0],E[0][0]),Math.min(b[0][1],E[0][1])],[Math.max(b[1][0],E[1][0]),Math.max(b[1][1],E[1][1])]];else E=b}}U?.(V,{...J})}).on("drag",(V)=>{let{transform:Y,snapGrid:p,snapToGrid:O,nodeOrigin:m}=l(),X=K$(V.sourceEvent,{transform:Y,snapGrid:p,snapToGrid:O,containerBounds:W}),v=[];if(!q)return;let{x:T,y:S,width:k,height:I}=J,b={},o=q.origin??m,{width:g,height:x,x:fu,y:$u}=GV(N,y.controlDirection,X,y.boundaries,y.keepAspectRatio,o,H,E),tu=g!==k,ju=x!==I,Gu=fu!==T&&tu,qu=$u!==S&&ju;if(!Gu&&!qu&&!tu&&!ju)return;if(Gu||qu||o[0]===1||o[1]===1){if(b.x=Gu?fu:J.x,b.y=qu?$u:J.y,J.x=b.x,J.y=b.y,z.length>0){let wu=fu-T,s=$u-S;for(let Qu of z)Qu.position={x:Qu.position.x-wu+o[0]*(g-k),y:Qu.position.y-s+o[1]*(x-I)},v.push(Qu)}}if(tu||ju)b.width=tu&&(!y.resizeDirection||y.resizeDirection==="horizontal")?g:J.width,b.height=ju&&(!y.resizeDirection||y.resizeDirection==="vertical")?x:J.height,J.width=b.width,J.height=b.height;if(Z&&q.expandParent){let wu=o[0]*(b.width??0);if(b.x&&b.x{if(!D)return;L?.(V,{...J}),n?.({...J}),D=!1});i.call(h)}function $(){i.on(".drag",null)}return{update:_,destroy:$}}var MN=Pu(Qf(),1),CN=Pu(SN(),1);var pN=(u)=>{let f,l=new Set,r=(c,j)=>{let F=typeof c==="function"?c(f):c;if(!Object.is(F,f)){let U=f;f=(j!=null?j:typeof F!=="object"||F===null)?F:Object.assign({},f,F),l.forEach((Q)=>Q(f,U))}},n=()=>f,$={setState:r,getState:n,getInitialState:()=>A,subscribe:(c)=>{return l.add(c),()=>l.delete(c)},destroy:()=>{l.clear()}},A=f=u(r,n,$);return $},mN=(u)=>u?pN(u):pN;var{useDebugValue:bV}=MN.default,{useSyncExternalStoreWithSelector:vV}=CN.default,kV=(u)=>u;function $9(u,f=kV,l){let r=vV(u.subscribe,u.getState,u.getServerState||u.getInitialState,f,l);return bV(r),r}var PN=(u,f)=>{let l=mN(u),r=(n,i=f)=>$9(l,n,i);return Object.assign(r,l),r},RN=(u,f)=>u?PN(u,f):PN;function Gf(u,f){if(Object.is(u,f))return!0;if(typeof u!=="object"||u===null||typeof f!=="object"||f===null)return!1;if(u instanceof Map&&f instanceof Map){if(u.size!==f.size)return!1;for(let[r,n]of u)if(!Object.is(n,f.get(r)))return!1;return!0}if(u instanceof Set&&f instanceof Set){if(u.size!==f.size)return!1;for(let r of u)if(!f.has(r))return!1;return!0}let l=Object.keys(u);if(l.length!==Object.keys(f).length)return!1;for(let r of l)if(!Object.prototype.hasOwnProperty.call(f,r)||!Object.is(u[r],f[r]))return!1;return!0}var IV=Pu(U5(),1),i8=yu.createContext(null),gV=i8.Provider,cW=Fr.error001();function ff(u,f){let l=yu.useContext(i8);if(l===null)throw Error(cW);return $9(l,u,f)}function Ef(){let u=yu.useContext(i8);if(u===null)throw Error(cW);return yu.useMemo(()=>({getState:u.getState,setState:u.setState,subscribe:u.subscribe}),[u])}var xN={display:"none"},sV={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},jW="react-flow__node-desc",FW="react-flow__edge-desc",aV="react-flow__aria-live",oV=(u)=>u.ariaLiveMessage,dV=(u)=>u.ariaLabelConfig;function eV({rfId:u}){let f=ff(oV);return ru.jsx("div",{id:`${aV}-${u}`,"aria-live":"assertive","aria-atomic":"true",style:sV,children:f})}function uD({rfId:u,disableKeyboardA11y:f}){let l=ff(dV);return ru.jsxs(ru.Fragment,{children:[ru.jsx("div",{id:`${jW}-${u}`,style:xN,children:f?l["node.a11yDescription.default"]:l["node.a11yDescription.keyboardDisabled"]}),ru.jsx("div",{id:`${FW}-${u}`,style:xN,children:l["edge.a11yDescription.default"]}),!f&&ru.jsx(eV,{rfId:u})]})}var y8=yu.forwardRef(({position:u="top-left",children:f,className:l,style:r,...n},i)=>{let y=`${u}`.split("-");return ru.jsx("div",{className:Yf(["react-flow__panel",l,...y]),style:r,ref:i,...n,children:f})});y8.displayName="Panel";function fD({proOptions:u,position:f="bottom-right"}){if(u?.hideAttribution)return null;return ru.jsx(y8,{position:f,className:"react-flow__attribution","data-message":"Please only hide this attribution when you are subscribed to React Flow Pro: https://pro.reactflow.dev",children:ru.jsx("a",{href:"https://reactflow.dev",target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}var lD=(u)=>{let f=[],l=[];for(let[,r]of u.nodeLookup)if(r.selected)f.push(r.internals.userNode);for(let[,r]of u.edgeLookup)if(r.selected)l.push(r);return{selectedNodes:f,selectedEdges:l}},l8=(u)=>u.id;function rD(u,f){return Gf(u.selectedNodes.map(l8),f.selectedNodes.map(l8))&&Gf(u.selectedEdges.map(l8),f.selectedEdges.map(l8))}function nD({onSelectionChange:u}){let f=Ef(),{selectedNodes:l,selectedEdges:r}=ff(lD,rD);return yu.useEffect(()=>{let n={nodes:l,edges:r};u?.(n),f.getState().onSelectionChangeHandlers.forEach((i)=>i(n))},[l,r,u]),null}var iD=(u)=>!!u.onSelectionChangeHandlers;function yD({onSelectionChange:u}){let f=ff(iD);if(u||f)return ru.jsx(nD,{onSelectionChange:u});return null}var c9=typeof window<"u"?yu.useLayoutEffect:yu.useEffect,JW=[0,0],_D={x:0,y:0,zoom:1},$D=["nodes","edges","defaultNodes","defaultEdges","onConnect","onConnectStart","onConnectEnd","onClickConnectStart","onClickConnectEnd","nodesDraggable","autoPanOnNodeFocus","nodesConnectable","nodesFocusable","edgesFocusable","edgesReconnectable","elevateNodesOnSelect","elevateEdgesOnSelect","minZoom","maxZoom","nodeExtent","onNodesChange","onEdgesChange","elementsSelectable","connectionMode","snapGrid","snapToGrid","translateExtent","connectOnClick","defaultEdgeOptions","fitView","fitViewOptions","onNodesDelete","onEdgesDelete","onDelete","onNodeDrag","onNodeDragStart","onNodeDragStop","onSelectionDrag","onSelectionDragStart","onSelectionDragStop","onMoveStart","onMove","onMoveEnd","noPanClassName","nodeOrigin","autoPanOnConnect","autoPanOnNodeDrag","onError","connectionRadius","isValidConnection","selectNodesOnDrag","nodeDragThreshold","connectionDragThreshold","onBeforeDelete","debug","autoPanSpeed","ariaLabelConfig","zIndexMode"],hN=[...$D,"rfId"],tD=(u)=>({setNodes:u.setNodes,setEdges:u.setEdges,setMinZoom:u.setMinZoom,setMaxZoom:u.setMaxZoom,setTranslateExtent:u.setTranslateExtent,setNodeExtent:u.setNodeExtent,reset:u.reset,setDefaultNodesAndEdges:u.setDefaultNodesAndEdges}),bN={translateExtent:ry,nodeOrigin:JW,minZoom:0.5,maxZoom:2,elementsSelectable:!0,noPanClassName:"nopan",rfId:"1"};function AD(u){let{setNodes:f,setEdges:l,setMinZoom:r,setMaxZoom:n,setTranslateExtent:i,setNodeExtent:y,reset:_,setDefaultNodesAndEdges:$}=ff(tD,Gf),A=Ef();c9(()=>{return $(u.defaultNodes,u.defaultEdges),()=>{c.current=bN,_()}},[]);let c=yu.useRef(bN);return c9(()=>{for(let j of hN){let F=u[j],U=c.current[j];if(F===U)continue;if(typeof u[j]>"u")continue;if(j==="nodes")f(F);else if(j==="edges")l(F);else if(j==="minZoom")r(F);else if(j==="maxZoom")n(F);else if(j==="translateExtent")i(F);else if(j==="nodeExtent")y(F);else if(j==="ariaLabelConfig")A.setState({ariaLabelConfig:yN(F)});else if(j==="fitView")A.setState({fitViewQueued:F});else if(j==="fitViewOptions")A.setState({fitViewOptions:F});else A.setState({[j]:F})}c.current=u},hN.map((j)=>u[j])),null}function vN(){if(typeof window>"u"||!window.matchMedia)return null;return window.matchMedia("(prefers-color-scheme: dark)")}function cD(u){let[f,l]=yu.useState(u==="system"?null:u);return yu.useEffect(()=>{if(u!=="system"){l(u);return}let r=vN(),n=()=>l(r?.matches?"dark":"light");return n(),r?.addEventListener("change",n),()=>{r?.removeEventListener("change",n)}},[u]),f!==null?f:vN()?.matches?"dark":"light"}var kN=typeof document<"u"?document:null;function Z$(u=null,f={target:kN,actInsideInputWithModifier:!0}){let[l,r]=yu.useState(!1),n=yu.useRef(!1),i=yu.useRef(new Set([])),[y,_]=yu.useMemo(()=>{if(u!==null){let A=(Array.isArray(u)?u:[u]).filter((j)=>typeof j==="string").map((j)=>j.replace("+",` `).replace(` `,` +`).split(` -`)),c=A.reduce((j,F)=>j.concat(...F),[]);return[A,c]}return[[],[]]},[u]);return yu.useEffect(()=>{let $=f?.target??bN,A=f?.actInsideInputWithModifier??!0;if(u!==null){let c=(U)=>{if(n.current=U.ctrlKey||U.metaKey||U.shiftKey||U.altKey,(!n.current||n.current&&!A)&&ac(U))return!1;let L=kN(U.code,_);if(i.current.add(U[L]),vN(y,i.current,!1)){let w=U.composedPath?.()?.[0]||U.target,J=w?.nodeName==="BUTTON"||w?.nodeName==="A";if(f.preventDefault!==!1&&(n.current||!J))U.preventDefault();r(!0)}},j=(U)=>{let Q=kN(U.code,_);if(vN(y,i.current,!0))r(!1),i.current.clear();else i.current.delete(U[Q]);if(U.key==="Meta")i.current.clear();n.current=!1},F=()=>{i.current.clear(),r(!1)};return $?.addEventListener("keydown",c),$?.addEventListener("keyup",j),window.addEventListener("blur",F),window.addEventListener("contextmenu",F),()=>{$?.removeEventListener("keydown",c),$?.removeEventListener("keyup",j),window.removeEventListener("blur",F),window.removeEventListener("contextmenu",F)}}},[u,r]),l}function vN(u,f,l){return u.filter((r)=>l||r.length===f.size).some((r)=>r.every((n)=>f.has(n)))}function kN(u,f){return f.includes(u)?"code":"key"}var AD=()=>{let u=Zf();return yu.useMemo(()=>{return{zoomIn:(f)=>{let{panZoom:l}=u.getState();return l?l.scaleBy(1.2,f):Promise.resolve(!1)},zoomOut:(f)=>{let{panZoom:l}=u.getState();return l?l.scaleBy(0.8333333333333334,f):Promise.resolve(!1)},zoomTo:(f,l)=>{let{panZoom:r}=u.getState();return r?r.scaleTo(f,l):Promise.resolve(!1)},getZoom:()=>u.getState().transform[2],setViewport:async(f,l)=>{let{transform:[r,n,i],panZoom:y}=u.getState();if(!y)return Promise.resolve(!1);return await y.setViewport({x:f.x??r,y:f.y??n,zoom:f.zoom??i},l),Promise.resolve(!0)},getViewport:()=>{let[f,l,r]=u.getState().transform;return{x:f,y:l,zoom:r}},setCenter:async(f,l,r)=>{return u.getState().setCenter(f,l,r)},fitBounds:async(f,l)=>{let{width:r,height:n,minZoom:i,maxZoom:y,panZoom:_}=u.getState(),$=K$(f,r,n,i,y,l?.padding??0.1);if(!_)return Promise.resolve(!1);return await _.setViewport($,{duration:l?.duration,ease:l?.ease,interpolate:l?.interpolate}),Promise.resolve(!0)},screenToFlowPosition:(f,l={})=>{let{transform:r,snapGrid:n,snapToGrid:i,domNode:y}=u.getState();if(!y)return f;let{x:_,y:$}=y.getBoundingClientRect(),A={x:f.x-_,y:f.y-$},c=l.snapGrid??n,j=l.snapToGrid??i;return yy(A,r,j,c)},flowToScreenPosition:(f)=>{let{transform:l,domNode:r}=u.getState();if(!r)return f;let{x:n,y:i}=r.getBoundingClientRect(),y=L$(f,l);return{x:y.x+n,y:y.y+i}}}},[])};function FW(u,f){let l=[],r=new Map,n=[];for(let i of u)if(i.type==="add"){n.push(i);continue}else if(i.type==="remove"||i.type==="replace")r.set(i.id,[i]);else{let y=r.get(i.id);if(y)y.push(i);else r.set(i.id,[i])}for(let i of f){let y=r.get(i.id);if(!y){l.push(i);continue}if(y[0].type==="remove")continue;if(y[0].type==="replace"){l.push({...y[0].item});continue}let _={...i};for(let $ of y)cD($,_);l.push(_)}if(n.length)n.forEach((i)=>{if(i.index!==void 0)l.splice(i.index,0,{...i.item});else l.push({...i.item})});return l}function cD(u,f){switch(u.type){case"select":{f.selected=u.selected;break}case"position":{if(typeof u.position<"u")f.position=u.position;if(typeof u.dragging<"u")f.dragging=u.dragging;break}case"dimensions":{if(typeof u.dimensions<"u"){if(f.measured={...u.dimensions},u.setAttributes){if(u.setAttributes===!0||u.setAttributes==="width")f.width=u.dimensions.width;if(u.setAttributes===!0||u.setAttributes==="height")f.height=u.dimensions.height}}if(typeof u.resizing==="boolean")f.resizing=u.resizing;break}}}function jD(u,f){return FW(u,f)}function FD(u,f){return FW(u,f)}function p1(u,f){return{id:u,type:"select",selected:f}}function ty(u,f=new Set,l=!1){let r=[];for(let[n,i]of u){let y=f.has(n);if(!(i.selected===void 0&&!y)&&i.selected!==y){if(l)i.selected=y;r.push(p1(i.id,y))}}return r}function IN({items:u=[],lookup:f}){let l=[],r=new Map(u.map((n)=>[n.id,n]));for(let[n,i]of u.entries()){let y=f.get(i.id),_=y?.internals?.userNode??y;if(_!==void 0&&_!==i)l.push({id:i.id,item:i,type:"replace"});if(_===void 0)l.push({item:i,type:"add",index:n})}for(let[n]of f)if(r.get(n)===void 0)l.push({id:n,type:"remove"});return l}function gN(u){return{id:u.id,type:"remove"}}var sN=(u)=>oq(u),JD=(u)=>Mc(u);function JW(u){return yu.forwardRef(u)}function aN(u){let[f,l]=yu.useState(BigInt(0)),[r]=yu.useState(()=>UD(()=>l((n)=>n+BigInt(1))));return t9(()=>{let n=r.get();if(n.length)u(n),r.reset()},[f]),r}function UD(u){let f=[];return{get:()=>f,reset:()=>{f=[]},push:(l)=>{f.push(l),u()}}}var UW=yu.createContext(null);function QD({children:u}){let f=Zf(),l=yu.useCallback((_)=>{let{nodes:$=[],setNodes:A,hasDefaultNodes:c,onNodesChange:j,nodeLookup:F,fitViewQueued:U,onNodesChangeMiddlewareMap:Q}=f.getState(),L=$;for(let J of _)L=typeof J==="function"?J(L):J;let w=IN({items:L,lookup:F});for(let J of Q.values())w=J(w);if(c)A(L);if(w.length>0)j?.(w);else if(U)window.requestAnimationFrame(()=>{let{fitViewQueued:J,nodes:N,setNodes:q}=f.getState();if(J)q(N)})},[]),r=aN(l),n=yu.useCallback((_)=>{let{edges:$=[],setEdges:A,hasDefaultEdges:c,onEdgesChange:j,edgeLookup:F}=f.getState(),U=$;for(let Q of _)U=typeof Q==="function"?Q(U):Q;if(c)A(U);else if(j)j(IN({items:U,lookup:F}))},[]),i=aN(n),y=yu.useMemo(()=>({nodeQueue:r,edgeQueue:i}),[]);return ru.jsx(UW.Provider,{value:y,children:u})}function qD(){let u=yu.useContext(UW);if(!u)throw Error("useBatchContext must be used within a BatchProvider");return u}var ND=(u)=>!!u.panZoom;function c9(){let u=AD(),f=Zf(),l=qD(),r=eu(ND),n=yu.useMemo(()=>{let i=(j)=>f.getState().nodeLookup.get(j),y=(j)=>{l.nodeQueue.push(j)},_=(j)=>{l.edgeQueue.push(j)},$=(j)=>{let{nodeLookup:F,nodeOrigin:U}=f.getState(),Q=sN(j)?j:F.get(j.id),L=Q.parentId?Ic(Q.position,Q.measured,Q.parentId,F,U):Q.position,w={...Q,position:L,width:Q.measured?.width??Q.width,height:Q.measured?.height??Q.height};return S1(w)},A=(j,F,U={replace:!1})=>{y((Q)=>Q.map((L)=>{if(L.id===j){let w=typeof F==="function"?F(L):F;return U.replace&&sN(w)?w:{...L,...w}}return L}))},c=(j,F,U={replace:!1})=>{_((Q)=>Q.map((L)=>{if(L.id===j){let w=typeof F==="function"?F(L):F;return U.replace&&JD(w)?w:{...L,...w}}return L}))};return{getNodes:()=>f.getState().nodes.map((j)=>({...j})),getNode:(j)=>i(j)?.internals.userNode,getInternalNode:i,getEdges:()=>{let{edges:j=[]}=f.getState();return j.map((F)=>({...F}))},getEdge:(j)=>f.getState().edgeLookup.get(j),setNodes:y,setEdges:_,addNodes:(j)=>{let F=Array.isArray(j)?j:[j];l.nodeQueue.push((U)=>[...U,...F])},addEdges:(j)=>{let F=Array.isArray(j)?j:[j];l.edgeQueue.push((U)=>[...U,...F])},toObject:()=>{let{nodes:j=[],edges:F=[],transform:U}=f.getState(),[Q,L,w]=U;return{nodes:j.map((J)=>({...J})),edges:F.map((J)=>({...J})),viewport:{x:Q,y:L,zoom:w}}},deleteElements:async({nodes:j=[],edges:F=[]})=>{let{nodes:U,edges:Q,onNodesDelete:L,onEdgesDelete:w,triggerNodeChanges:J,triggerEdgeChanges:N,onDelete:q,onBeforeDelete:W}=f.getState(),{nodes:z,edges:Z}=await uN({nodesToRemove:j,edgesToRemove:F,nodes:U,edges:Q,onBeforeDelete:W}),H=Z.length>0,E=z.length>0;if(H){let D=Z.map(gN);w?.(Z),N(D)}if(E){let D=z.map(gN);L?.(z),J(D)}if(E||H)q?.({nodes:z,edges:Z});return{deletedNodes:z,deletedEdges:Z}},getIntersectingNodes:(j,F=!0,U)=>{let Q=bc(j),L=Q?j:$(j),w=U!==void 0;if(!L)return[];return(U||f.getState().nodes).filter((J)=>{let N=f.getState().nodeLookup.get(J.id);if(N&&!Q&&(J.id===j.id||!N.internals.positionAbsolute))return!1;let q=S1(w?J:N),W=ny(q,L);return F&&W>0||W>=q.width*q.height||W>=L.width*L.height})},isNodeIntersecting:(j,F,U=!0)=>{let L=bc(j)?j:$(j);if(!L)return!1;let w=ny(L,F);return U&&w>0||w>=F.width*F.height||w>=L.width*L.height},updateNode:A,updateNodeData:(j,F,U={replace:!1})=>{A(j,(Q)=>{let L=typeof F==="function"?F(Q):F;return U.replace?{...Q,data:L}:{...Q,data:{...Q.data,...L}}},U)},updateEdge:c,updateEdgeData:(j,F,U={replace:!1})=>{c(j,(Q)=>{let L=typeof F==="function"?F(Q):F;return U.replace?{...Q,data:L}:{...Q,data:{...Q.data,...L}}},U)},getNodesBounds:(j)=>{let{nodeLookup:F,nodeOrigin:U}=f.getState();return Rc(j,{nodeLookup:F,nodeOrigin:U})},getHandleConnections:({type:j,id:F,nodeId:U})=>Array.from(f.getState().connectionLookup.get(`${U}-${j}${F?`-${F}`:""}`)?.values()??[]),getNodeConnections:({type:j,handleId:F,nodeId:U})=>Array.from(f.getState().connectionLookup.get(`${U}${j?F?`-${j}-${F}`:`-${j}`:""}`)?.values()??[]),fitView:async(j)=>{let F=f.getState().fitViewResolver??rN();return f.setState({fitViewQueued:!0,fitViewOptions:j,fitViewResolver:F}),l.nodeQueue.push((U)=>[...U]),F.promise}}},[]);return yu.useMemo(()=>{return{...n,...u,viewportInitialized:r}},[r])}var oN=(u)=>u.selected,WD=typeof window<"u"?window:void 0;function LD({deleteKeyCode:u,multiSelectionKeyCode:f}){let l=Zf(),{deleteElements:r}=c9(),n=z$(u,{actInsideInputWithModifier:!1}),i=z$(f,{target:WD});yu.useEffect(()=>{if(n){let{edges:y,nodes:_}=l.getState();r({nodes:_.filter(oN),edges:y.filter(oN)}),l.setState({nodesSelectionActive:!1})}},[n]),yu.useEffect(()=>{l.setState({multiSelectionActive:i})},[i])}function wD(u){let f=Zf();yu.useEffect(()=>{let l=()=>{if(!u.current||!(u.current.checkVisibility?.()??!0))return!1;let r=b6(u.current);if(r.height===0||r.width===0)f.getState().onError?.("004",Fr.error004());f.setState({width:r.width||500,height:r.height||500})};if(u.current){l(),window.addEventListener("resize",l);let r=new ResizeObserver(()=>l());return r.observe(u.current),()=>{if(window.removeEventListener("resize",l),r&&u.current)r.unobserve(u.current)}}},[])}var i8={position:"absolute",width:"100%",height:"100%",top:0,left:0},KD=(u)=>({userSelectionActive:u.userSelectionActive,lib:u.lib,connectionInProgress:u.connection.inProgress});function GD({onPaneContextMenu:u,zoomOnScroll:f=!0,zoomOnPinch:l=!0,panOnScroll:r=!1,panOnScrollSpeed:n=0.5,panOnScrollMode:i=C0.Free,zoomOnDoubleClick:y=!0,panOnDrag:_=!0,defaultViewport:$,translateExtent:A,minZoom:c,maxZoom:j,zoomActivationKeyCode:F,preventScrolling:U=!0,children:Q,noWheelClassName:L,noPanClassName:w,onViewportChange:J,isControlledViewport:N,paneClickDistance:q,selectionOnDrag:W}){let z=Zf(),Z=yu.useRef(null),{userSelectionActive:H,lib:E,connectionInProgress:D}=eu(KD,zf),h=z$(F),V=yu.useRef();wD(Z);let Y=yu.useCallback((p)=>{if(J?.({x:p[0],y:p[1],zoom:p[2]}),!N)z.setState({transform:p})},[J,N]);return yu.useEffect(()=>{if(Z.current){V.current=GN({domNode:Z.current,minZoom:c,maxZoom:j,translateExtent:A,viewport:$,onDraggingChange:(X)=>z.setState((v)=>v.paneDragging===X?v:{paneDragging:X}),onPanZoomStart:(X,v)=>{let{onViewportChangeStart:T,onMoveStart:S}=z.getState();S?.(X,v),T?.(v)},onPanZoom:(X,v)=>{let{onViewportChange:T,onMove:S}=z.getState();S?.(X,v),T?.(v)},onPanZoomEnd:(X,v)=>{let{onViewportChangeEnd:T,onMoveEnd:S}=z.getState();S?.(X,v),T?.(v)}});let{x:p,y:O,zoom:m}=V.current.getViewport();return z.setState({panZoom:V.current,transform:[p,O,m],domNode:Z.current.closest(".react-flow")}),()=>{V.current?.destroy()}}},[]),yu.useEffect(()=>{V.current?.update({onPaneContextMenu:u,zoomOnScroll:f,zoomOnPinch:l,panOnScroll:r,panOnScrollSpeed:n,panOnScrollMode:i,zoomOnDoubleClick:y,panOnDrag:_,zoomActivationKeyPressed:h,preventScrolling:U,noPanClassName:w,userSelectionActive:H,noWheelClassName:L,lib:E,onTransformChange:Y,connectionInProgress:D,selectionOnDrag:W,paneClickDistance:q})},[u,f,l,r,n,i,y,_,h,U,w,H,L,E,Y,D,W,q]),ru.jsx("div",{className:"react-flow__renderer",ref:Z,style:i8,children:Q})}var zD=(u)=>({userSelectionActive:u.userSelectionActive,userSelectionRect:u.userSelectionRect});function TD(){let{userSelectionActive:u,userSelectionRect:f}=eu(zD,zf);if(!(u&&f))return null;return ru.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:f.width,height:f.height,transform:`translate(${f.x}px, ${f.y}px)`}})}var _9=(u,f)=>{return(l)=>{if(l.target!==f.current)return;u?.(l)}},ED=(u)=>({userSelectionActive:u.userSelectionActive,elementsSelectable:u.elementsSelectable,connectionInProgress:u.connection.inProgress,dragging:u.paneDragging});function ZD({isSelecting:u,selectionKeyPressed:f,selectionMode:l=X1.Full,panOnDrag:r,paneClickDistance:n,selectionOnDrag:i,onSelectionStart:y,onSelectionEnd:_,onPaneClick:$,onPaneContextMenu:A,onPaneScroll:c,onPaneMouseEnter:j,onPaneMouseMove:F,onPaneMouseLeave:U,children:Q}){let L=Zf(),{userSelectionActive:w,elementsSelectable:J,dragging:N,connectionInProgress:q}=eu(ED,zf),W=J&&(u||w),z=yu.useRef(null),Z=yu.useRef(),H=yu.useRef(new Set),E=yu.useRef(new Set),D=yu.useRef(!1),h=(T)=>{if(D.current||q){D.current=!1;return}$?.(T),L.getState().resetSelectedElements(),L.setState({nodesSelectionActive:!1})},V=(T)=>{if(Array.isArray(r)&&r?.includes(2)){T.preventDefault();return}A?.(T)},Y=c?(T)=>c(T):void 0,p=(T)=>{if(D.current)T.stopPropagation(),D.current=!1},O=(T)=>{let{domNode:S}=L.getState();if(Z.current=S?.getBoundingClientRect(),!Z.current)return;let k=T.target===z.current;if(!k&&!!T.target.closest(".nokey")||!u||!(i&&k||f)||T.button!==0||!T.isPrimary)return;T.target?.setPointerCapture?.(T.pointerId),D.current=!1;let{x:o,y:s}=Zr(T.nativeEvent,Z.current);if(L.setState({userSelectionRect:{width:0,height:0,startX:o,startY:s,x:o,y:s}}),!k)T.stopPropagation(),T.preventDefault()},m=(T)=>{let{userSelectionRect:S,transform:k,nodeLookup:I,edgeLookup:b,connectionLookup:o,triggerNodeChanges:s,triggerEdgeChanges:x,defaultEdgeOptions:fu,resetSelectedElements:$u}=L.getState();if(!Z.current||!S)return;let{x:tu,y:ju}=Zr(T.nativeEvent,Z.current),{startX:Gu,startY:qu}=S;if(!D.current){let g=f?0:n;if(Math.hypot(tu-Gu,ju-qu)<=g)return;$u(),y?.(T)}D.current=!0;let P={startX:Gu,startY:qu,x:tug.id)),E.current=new Set;let Wu=fu?.selectable??!0;for(let g of H.current){let Qu=o.get(g);if(!Qu)continue;for(let{edgeId:Tu}of Qu.values()){let Zu=b.get(Tu);if(Zu&&(Zu.selectable??Wu))E.current.add(Tu)}}if(!gc(e,H.current)){let g=ty(I,H.current,!0);s(g)}if(!gc(uu,E.current)){let g=ty(b,E.current);x(g)}L.setState({userSelectionRect:P,userSelectionActive:!0,nodesSelectionActive:!1})},X=(T)=>{if(T.button!==0)return;if(T.target?.releasePointerCapture?.(T.pointerId),!w&&T.target===z.current&&L.getState().userSelectionRect)h?.(T);if(L.setState({userSelectionActive:!1,userSelectionRect:null}),D.current)_?.(T),L.setState({nodesSelectionActive:H.current.size>0})},v=r===!0||Array.isArray(r)&&r.includes(0);return ru.jsxs("div",{className:Yf(["react-flow__pane",{draggable:v,dragging:N,selection:u}]),onClick:W?void 0:_9(h,z),onContextMenu:_9(V,z),onWheel:_9(Y,z),onPointerEnter:W?void 0:j,onPointerMove:W?m:F,onPointerUp:W?X:void 0,onPointerDownCapture:W?O:void 0,onClickCapture:W?p:void 0,onPointerLeave:U,ref:z,style:i8,children:[Q,ru.jsx(TD,{})]})}function A9({id:u,store:f,unselect:l=!1,nodeRef:r}){let{addSelectedNodes:n,unselectNodesAndEdges:i,multiSelectionActive:y,nodeLookup:_,onError:$}=f.getState(),A=_.get(u);if(!A){$?.("012",Fr.error012(u));return}if(f.setState({nodesSelectionActive:!1}),!A.selected)n([u]);else if(l||A.selected&&y)i({nodes:[A],edges:[]}),requestAnimationFrame(()=>r?.current?.blur())}function QW({nodeRef:u,disabled:f=!1,noDragClassName:l,handleSelector:r,nodeId:n,isSelectable:i,nodeClickDistance:y}){let _=Zf(),[$,A]=yu.useState(!1),c=yu.useRef();return yu.useEffect(()=>{c.current=UN({getStoreItems:()=>_.getState(),onNodeMouseDown:(j)=>{A9({id:j,store:_,nodeRef:u})},onDragStart:()=>{A(!0)},onDragStop:()=>{A(!1)}})},[]),yu.useEffect(()=>{if(f||!u.current||!c.current)return;return c.current.update({noDragClassName:l,handleSelector:r,domNode:u.current,isSelectable:i,nodeId:n,nodeClickDistance:y}),()=>{c.current?.destroy()}},[l,r,f,i,u,n,y]),$}var OD=(u)=>(f)=>f.selected&&(f.draggable||u&&typeof f.draggable>"u");function qW(){let u=Zf();return yu.useCallback((l)=>{let{nodeExtent:r,snapToGrid:n,snapGrid:i,nodesDraggable:y,onError:_,updateNodePositions:$,nodeLookup:A,nodeOrigin:c}=u.getState(),j=new Map,F=OD(y),U=n?i[0]:5,Q=n?i[1]:5,L=l.direction.x*U*l.factor,w=l.direction.y*Q*l.factor;for(let[,J]of A){if(!F(J))continue;let N={x:J.internals.positionAbsolute.x+L,y:J.internals.positionAbsolute.y+w};if(n)N=iy(N,i);let{position:q,positionAbsolute:W}=xc({nodeId:J.id,nextPosition:N,nodeLookup:A,nodeExtent:r,nodeOrigin:c,onError:_});J.position=q,J.internals.positionAbsolute=W,j.set(J.id,J)}$(j)},[])}var j9=yu.createContext(null),HD=j9.Provider;j9.Consumer;var NW=()=>{return yu.useContext(j9)},BD=(u)=>({connectOnClick:u.connectOnClick,noPanClassName:u.noPanClassName,rfId:u.rfId}),VD=(u,f,l)=>(r)=>{let{connectionClickStartHandle:n,connectionMode:i,connection:y}=r,{fromHandle:_,toHandle:$,isValid:A}=y,c=$?.nodeId===u&&$?.id===f&&$?.type===l;return{connectingFrom:_?.nodeId===u&&_?.id===f&&_?.type===l,connectingTo:c,clickConnecting:n?.nodeId===u&&n?.id===f&&n?.type===l,isPossibleEndHandle:i===Vn.Strict?_?.type!==l:u!==_?.nodeId||f!==_?.id,connectionInProcess:!!_,clickConnectionInProcess:!!n,valid:c&&A}};function DD({type:u="source",position:f=wu.Top,isValidConnection:l,isConnectable:r=!0,isConnectableStart:n=!0,isConnectableEnd:i=!0,id:y,onConnect:_,children:$,className:A,onMouseDown:c,onTouchStart:j,...F},U){let Q=y||null,L=u==="target",w=Zf(),J=NW(),{connectOnClick:N,noPanClassName:q,rfId:W}=eu(BD,zf),{connectingFrom:z,connectingTo:Z,clickConnecting:H,isPossibleEndHandle:E,connectionInProcess:D,clickConnectionInProcess:h,valid:V}=eu(VD(J,Q,u),zf);if(!J)w.getState().onError?.("010",Fr.error010());let Y=(m)=>{let{defaultEdgeOptions:X,onConnect:v,hasDefaultEdges:T}=w.getState(),S={...X,...m};if(T){let{edges:k,setEdges:I}=w.getState();I(ec(S,k))}v?.(S),_?.(S)},p=(m)=>{if(!J)return;let X=oc(m.nativeEvent);if(n&&(X&&m.button===0||!X)){let v=w.getState();o6.onPointerDown(m.nativeEvent,{handleDomNode:m.currentTarget,autoPanOnConnect:v.autoPanOnConnect,connectionMode:v.connectionMode,connectionRadius:v.connectionRadius,domNode:v.domNode,nodeLookup:v.nodeLookup,lib:v.lib,isTarget:L,handleId:Q,nodeId:J,flowId:v.rfId,panBy:v.panBy,cancelConnection:v.cancelConnection,onConnectStart:v.onConnectStart,onConnectEnd:(...T)=>w.getState().onConnectEnd?.(...T),updateConnection:v.updateConnection,onConnect:Y,isValidConnection:l||((...T)=>w.getState().isValidConnection?.(...T)??!0),getTransform:()=>w.getState().transform,getFromHandle:()=>w.getState().connection.fromHandle,autoPanSpeed:v.autoPanSpeed,dragThreshold:v.connectionDragThreshold})}if(X)c?.(m);else j?.(m)},O=(m)=>{let{onClickConnectStart:X,onClickConnectEnd:v,connectionClickStartHandle:T,connectionMode:S,isValidConnection:k,lib:I,rfId:b,nodeLookup:o,connection:s}=w.getState();if(!J||!T&&!n)return;if(!T){X?.(m.nativeEvent,{nodeId:J,handleId:Q,handleType:u}),w.setState({connectionClickStartHandle:{nodeId:J,type:u,id:Q}});return}let x=sc(m.target),fu=l||k,{connection:$u,isValid:tu}=o6.isValid(m.nativeEvent,{handle:{nodeId:J,id:Q,type:u},connectionMode:S,fromNodeId:T.nodeId,fromHandleId:T.id||null,fromType:T.type,isValidConnection:fu,flowId:b,doc:x,lib:I,nodeLookup:o});if(tu&&$u)Y($u);let ju=structuredClone(s);delete ju.inProgress,ju.toPosition=ju.toHandle?ju.toHandle.position:null,v?.(m,ju),w.setState({connectionClickStartHandle:null})};return ru.jsx("div",{"data-handleid":Q,"data-nodeid":J,"data-handlepos":f,"data-id":`${W}-${J}-${Q}-${u}`,className:Yf(["react-flow__handle",`react-flow__handle-${f}`,"nodrag",q,A,{source:!L,target:L,connectable:r,connectablestart:n,connectableend:i,clickconnecting:H,connectingfrom:z,connectingto:Z,valid:V,connectionindicator:r&&(!D||E)&&(D||h?i:n)}]),onMouseDown:p,onTouchStart:p,onClick:N?O:void 0,ref:U,...F,children:$})}var m1=yu.memo(JW(DD));function XD({data:u,isConnectable:f,sourcePosition:l=wu.Bottom}){return ru.jsxs(ru.Fragment,{children:[u?.label,ru.jsx(m1,{type:"source",position:l,isConnectable:f})]})}function YD({data:u,isConnectable:f,targetPosition:l=wu.Top,sourcePosition:r=wu.Bottom}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(m1,{type:"target",position:l,isConnectable:f}),u?.label,ru.jsx(m1,{type:"source",position:r,isConnectable:f})]})}function SD(){return null}function pD({data:u,isConnectable:f,targetPosition:l=wu.Top}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(m1,{type:"target",position:l,isConnectable:f}),u?.label]})}var l8={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},dN={input:XD,default:YD,output:pD,group:SD};function mD(u){if(u.internals.handleBounds===void 0)return{width:u.width??u.initialWidth??u.style?.width,height:u.height??u.initialHeight??u.style?.height};return{width:u.width??u.style?.width,height:u.height??u.style?.height}}var PD=(u)=>{let{width:f,height:l,x:r,y:n}=ry(u.nodeLookup,{filter:(i)=>!!i.selected});return{width:Er(f)?f:null,height:Er(l)?l:null,userSelectionActive:u.userSelectionActive,transformString:`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]}) translate(${r}px,${n}px)`}};function MD({onSelectionContextMenu:u,noPanClassName:f,disableKeyboardA11y:l}){let r=Zf(),{width:n,height:i,transformString:y,userSelectionActive:_}=eu(PD,zf),$=qW(),A=yu.useRef(null);yu.useEffect(()=>{if(!l)A.current?.focus({preventScroll:!0})},[l]);let c=!_&&n!==null&&i!==null;if(QW({nodeRef:A,disabled:!c}),!c)return null;let j=u?(U)=>{let Q=r.getState().nodes.filter((L)=>L.selected);u(U,Q)}:void 0,F=(U)=>{if(Object.prototype.hasOwnProperty.call(l8,U.key))U.preventDefault(),$({direction:l8[U.key],factor:U.shiftKey?4:1})};return ru.jsx("div",{className:Yf(["react-flow__nodesselection","react-flow__container",f]),style:{transform:y},children:ru.jsx("div",{ref:A,className:"react-flow__nodesselection-rect",onContextMenu:j,tabIndex:l?void 0:-1,onKeyDown:l?void 0:F,style:{width:n,height:i}})})}var eN=typeof window<"u"?window:void 0,CD=(u)=>{return{nodesSelectionActive:u.nodesSelectionActive,userSelectionActive:u.userSelectionActive}};function WW({children:u,onPaneClick:f,onPaneMouseEnter:l,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,paneClickDistance:_,deleteKeyCode:$,selectionKeyCode:A,selectionOnDrag:c,selectionMode:j,onSelectionStart:F,onSelectionEnd:U,multiSelectionKeyCode:Q,panActivationKeyCode:L,zoomActivationKeyCode:w,elementsSelectable:J,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:W,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:E,defaultViewport:D,translateExtent:h,minZoom:V,maxZoom:Y,preventScrolling:p,onSelectionContextMenu:O,noWheelClassName:m,noPanClassName:X,disableKeyboardA11y:v,onViewportChange:T,isControlledViewport:S}){let{nodesSelectionActive:k,userSelectionActive:I}=eu(CD,zf),b=z$(A,{target:eN}),o=z$(L,{target:eN}),s=o||E,x=o||W,fu=c&&s!==!0,$u=b||I||fu;return LD({deleteKeyCode:$,multiSelectionKeyCode:Q}),ru.jsx(GD,{onPaneContextMenu:i,elementsSelectable:J,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:x,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:!b&&s,defaultViewport:D,translateExtent:h,minZoom:V,maxZoom:Y,zoomActivationKeyCode:w,preventScrolling:p,noWheelClassName:m,noPanClassName:X,onViewportChange:T,isControlledViewport:S,paneClickDistance:_,selectionOnDrag:fu,children:ru.jsxs(ZD,{onSelectionStart:F,onSelectionEnd:U,onPaneClick:f,onPaneMouseEnter:l,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,panOnDrag:s,isSelecting:!!$u,selectionMode:j,selectionKeyPressed:b,paneClickDistance:_,selectionOnDrag:fu,children:[u,k&&ru.jsx(MD,{onSelectionContextMenu:O,noPanClassName:X,disableKeyboardA11y:v})]})})}WW.displayName="FlowRenderer";var RD=yu.memo(WW),xD=(u)=>(f)=>{return u?R6(f.nodeLookup,{x:0,y:0,width:f.width,height:f.height},f.transform,!0).map((l)=>l.id):Array.from(f.nodeLookup.keys())};function hD(u){return eu(yu.useCallback(xD(u),[u]),zf)}var bD=(u)=>u.updateNodeInternals;function vD(){let u=eu(bD),[f]=yu.useState(()=>{if(typeof ResizeObserver>"u")return null;return new ResizeObserver((l)=>{let r=new Map;l.forEach((n)=>{let i=n.target.getAttribute("data-id");r.set(i,{id:i,nodeElement:n.target,force:!0})}),u(r)})});return yu.useEffect(()=>{return()=>{f?.disconnect()}},[f]),f}function kD({node:u,nodeType:f,hasDimensions:l,resizeObserver:r}){let n=Zf(),i=yu.useRef(null),y=yu.useRef(null),_=yu.useRef(u.sourcePosition),$=yu.useRef(u.targetPosition),A=yu.useRef(f),c=l&&!!u.internals.handleBounds;return yu.useEffect(()=>{if(i.current&&!u.hidden&&(!c||y.current!==i.current)){if(y.current)r?.unobserve(y.current);r?.observe(i.current),y.current=i.current}},[c,u.hidden]),yu.useEffect(()=>{return()=>{if(y.current)r?.unobserve(y.current),y.current=null}},[]),yu.useEffect(()=>{if(i.current){let j=A.current!==f,F=_.current!==u.sourcePosition,U=$.current!==u.targetPosition;if(j||F||U)A.current=f,_.current=u.sourcePosition,$.current=u.targetPosition,n.getState().updateNodeInternals(new Map([[u.id,{id:u.id,nodeElement:i.current,force:!0}]]))}},[u.id,f,u.sourcePosition,u.targetPosition]),i}function ID({id:u,onClick:f,onMouseEnter:l,onMouseMove:r,onMouseLeave:n,onContextMenu:i,onDoubleClick:y,nodesDraggable:_,elementsSelectable:$,nodesConnectable:A,nodesFocusable:c,resizeObserver:j,noDragClassName:F,noPanClassName:U,disableKeyboardA11y:Q,rfId:L,nodeTypes:w,nodeClickDistance:J,onError:N}){let{node:q,internals:W,isParent:z}=eu((tu)=>{let ju=tu.nodeLookup.get(u),Gu=tu.parentLookup.has(u);return{node:ju,internals:ju.internals,isParent:Gu}},zf),Z=q.type||"default",H=w?.[Z]||dN[Z];if(H===void 0)N?.("003",Fr.error003(Z)),Z="default",H=w?.default||dN.default;let E=!!(q.draggable||_&&typeof q.draggable>"u"),D=!!(q.selectable||$&&typeof q.selectable>"u"),h=!!(q.connectable||A&&typeof q.connectable>"u"),V=!!(q.focusable||c&&typeof q.focusable>"u"),Y=Zf(),p=kc(q),O=kD({node:q,nodeType:Z,hasDimensions:p,resizeObserver:j}),m=QW({nodeRef:O,disabled:q.hidden||!E,noDragClassName:F,handleSelector:q.dragHandle,nodeId:u,isSelectable:D,nodeClickDistance:J}),X=qW();if(q.hidden)return null;let v=t0(q),T=mD(q),S=D||E||f||l||r||n,k=l?(tu)=>l(tu,{...W.userNode}):void 0,I=r?(tu)=>r(tu,{...W.userNode}):void 0,b=n?(tu)=>n(tu,{...W.userNode}):void 0,o=i?(tu)=>i(tu,{...W.userNode}):void 0,s=y?(tu)=>y(tu,{...W.userNode}):void 0,x=(tu)=>{let{selectNodesOnDrag:ju,nodeDragThreshold:Gu}=Y.getState();if(D&&(!ju||!E||Gu>0))A9({id:u,store:Y,nodeRef:O});if(f)f(tu,{...W.userNode})},fu=(tu)=>{if(ac(tu.nativeEvent)||Q)return;if(Sc.includes(tu.key)&&D){let ju=tu.key==="Escape";A9({id:u,store:Y,unselect:ju,nodeRef:O})}else if(E&&q.selected&&Object.prototype.hasOwnProperty.call(l8,tu.key)){tu.preventDefault();let{ariaLabelConfig:ju}=Y.getState();Y.setState({ariaLiveMessage:ju["node.a11yDescription.ariaLiveMessage"]({direction:tu.key.replace("Arrow","").toLowerCase(),x:~~W.positionAbsolute.x,y:~~W.positionAbsolute.y})}),X({direction:l8[tu.key],factor:tu.shiftKey?4:1})}},$u=()=>{if(Q||!O.current?.matches(":focus-visible"))return;let{transform:tu,width:ju,height:Gu,autoPanOnNodeFocus:qu,setCenter:P}=Y.getState();if(!qu)return;if(!(R6(new Map([[u,q]]),{x:0,y:0,width:ju,height:Gu},tu,!0).length>0))P(q.position.x+v.width/2,q.position.y+v.height/2,{zoom:tu[2]})};return ru.jsx("div",{className:Yf(["react-flow__node",`react-flow__node-${Z}`,{[U]:E},q.className,{selected:q.selected,selectable:D,parent:z,draggable:E,dragging:m}]),ref:O,style:{zIndex:W.z,transform:`translate(${W.positionAbsolute.x}px,${W.positionAbsolute.y}px)`,pointerEvents:S?"all":"none",visibility:p?"visible":"hidden",...q.style,...T},"data-id":u,"data-testid":`rf__node-${u}`,onMouseEnter:k,onMouseMove:I,onMouseLeave:b,onContextMenu:o,onClick:x,onDoubleClick:s,onKeyDown:V?fu:void 0,tabIndex:V?0:void 0,onFocus:V?$u:void 0,role:q.ariaRole??(V?"group":void 0),"aria-roledescription":"node","aria-describedby":Q?void 0:`${AW}-${L}`,"aria-label":q.ariaLabel,...q.domAttributes,children:ru.jsx(HD,{value:u,children:ru.jsx(H,{id:u,data:q.data,type:Z,positionAbsoluteX:W.positionAbsolute.x,positionAbsoluteY:W.positionAbsolute.y,selected:q.selected??!1,selectable:D,draggable:E,deletable:q.deletable??!0,isConnectable:h,sourcePosition:q.sourcePosition,targetPosition:q.targetPosition,dragging:m,dragHandle:q.dragHandle,zIndex:W.z,parentId:q.parentId,...v})})})}var gD=yu.memo(ID),sD=(u)=>({nodesDraggable:u.nodesDraggable,nodesConnectable:u.nodesConnectable,nodesFocusable:u.nodesFocusable,elementsSelectable:u.elementsSelectable,onError:u.onError});function LW(u){let{nodesDraggable:f,nodesConnectable:l,nodesFocusable:r,elementsSelectable:n,onError:i}=eu(sD,zf),y=hD(u.onlyRenderVisibleElements),_=vD();return ru.jsx("div",{className:"react-flow__nodes",style:i8,children:y.map(($)=>{return ru.jsx(gD,{id:$,nodeTypes:u.nodeTypes,nodeExtent:u.nodeExtent,onClick:u.onNodeClick,onMouseEnter:u.onNodeMouseEnter,onMouseMove:u.onNodeMouseMove,onMouseLeave:u.onNodeMouseLeave,onContextMenu:u.onNodeContextMenu,onDoubleClick:u.onNodeDoubleClick,noDragClassName:u.noDragClassName,noPanClassName:u.noPanClassName,rfId:u.rfId,disableKeyboardA11y:u.disableKeyboardA11y,resizeObserver:_,nodesDraggable:f,nodesConnectable:l,nodesFocusable:r,elementsSelectable:n,nodeClickDistance:u.nodeClickDistance,onError:i},$)})})}LW.displayName="NodeRenderer";var aD=yu.memo(LW);function oD(u){return eu(yu.useCallback((l)=>{if(!u)return l.edges.map((n)=>n.id);let r=[];if(l.width&&l.height)for(let n of l.edges){let i=l.nodeLookup.get(n.source),y=l.nodeLookup.get(n.target);if(i&&y&&yN({sourceNode:i,targetNode:y,width:l.width,height:l.height,transform:l.transform}))r.push(n.id)}return r},[u]),zf)}var dD=({color:u="none",strokeWidth:f=1})=>{let l={strokeWidth:f,...u&&{stroke:u}};return ru.jsx("polyline",{className:"arrow",style:l,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},eD=({color:u="none",strokeWidth:f=1})=>{let l={strokeWidth:f,...u&&{stroke:u,fill:u}};return ru.jsx("polyline",{className:"arrowclosed",style:l,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},uW={[Dn.Arrow]:dD,[Dn.ArrowClosed]:eD};function uX(u){let f=Zf();return yu.useMemo(()=>{if(!Object.prototype.hasOwnProperty.call(uW,u))return f.getState().onError?.("009",Fr.error009(u)),null;return uW[u]},[u])}var fX=({id:u,type:f,color:l,width:r=12.5,height:n=12.5,markerUnits:i="strokeWidth",strokeWidth:y,orient:_="auto-start-reverse"})=>{let $=uX(f);if(!$)return null;return ru.jsx("marker",{className:"react-flow__arrowhead",id:u,markerWidth:`${r}`,markerHeight:`${n}`,viewBox:"-10 -10 20 20",markerUnits:i,orient:_,refX:"0",refY:"0",children:ru.jsx($,{color:l,strokeWidth:y})})},wW=({defaultColor:u,rfId:f})=>{let l=eu((i)=>i.edges),r=eu((i)=>i.defaultEdgeOptions),n=yu.useMemo(()=>{return $N(l,{id:f,defaultColor:u,defaultMarkerStart:r?.markerStart,defaultMarkerEnd:r?.markerEnd})},[l,r,f,u]);if(!n.length)return null;return ru.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:ru.jsx("defs",{children:n.map((i)=>ru.jsx(fX,{id:i.id,type:i.type,color:i.color,width:i.width,height:i.height,markerUnits:i.markerUnits,strokeWidth:i.strokeWidth,orient:i.orient},i.id))})})};wW.displayName="MarkerDefinitions";var lX=yu.memo(wW);function KW({x:u,y:f,label:l,labelStyle:r,labelShowBg:n=!0,labelBgStyle:i,labelBgPadding:y=[2,4],labelBgBorderRadius:_=2,children:$,className:A,...c}){let[j,F]=yu.useState({x:1,y:0,width:0,height:0}),U=Yf(["react-flow__edge-textwrapper",A]),Q=yu.useRef(null);if(yu.useEffect(()=>{if(Q.current){let L=Q.current.getBBox();F({x:L.x,y:L.y,width:L.width,height:L.height})}},[l]),!l)return null;return ru.jsxs("g",{transform:`translate(${u-j.width/2} ${f-j.height/2})`,className:U,visibility:j.width?"visible":"hidden",...c,children:[n&&ru.jsx("rect",{width:j.width+2*y[0],x:-y[0],y:-y[1],height:j.height+2*y[1],className:"react-flow__edge-textbg",style:i,rx:_,ry:_}),ru.jsx("text",{className:"react-flow__edge-text",y:j.height/2,dy:"0.3em",ref:Q,style:r,children:l}),$]})}KW.displayName="EdgeText";var rX=yu.memo(KW);function Ay({path:u,labelX:f,labelY:l,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:_,labelBgBorderRadius:$,interactionWidth:A=20,...c}){return ru.jsxs(ru.Fragment,{children:[ru.jsx("path",{...c,d:u,fill:"none",className:Yf(["react-flow__edge-path",c.className])}),A?ru.jsx("path",{d:u,fill:"none",strokeOpacity:0,strokeWidth:A,className:"react-flow__edge-interaction"}):null,r&&Er(f)&&Er(l)?ru.jsx(rX,{x:f,y:l,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:_,labelBgBorderRadius:$}):null]})}function fW({pos:u,x1:f,y1:l,x2:r,y2:n}){if(u===wu.Left||u===wu.Right)return[0.5*(f+r),l];return[f,0.5*(l+n)]}function GW({sourceX:u,sourceY:f,sourcePosition:l=wu.Bottom,targetX:r,targetY:n,targetPosition:i=wu.Top}){let[y,_]=fW({pos:l,x1:u,y1:f,x2:r,y2:n}),[$,A]=fW({pos:i,x1:r,y1:n,x2:u,y2:f}),[c,j,F,U]=v6({sourceX:u,sourceY:f,targetX:r,targetY:n,sourceControlX:y,sourceControlY:_,targetControlX:$,targetControlY:A});return[`M${u},${f} C${y},${_} ${$},${A} ${r},${n}`,c,j,F,U]}function zW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,sourcePosition:y,targetPosition:_,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,interactionWidth:J})=>{let[N,q,W]=GW({sourceX:l,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:_}),z=u.isInternal?void 0:f;return ru.jsx(Ay,{id:z,path:N,labelX:q,labelY:W,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,interactionWidth:J})})}var nX=zW({isInternal:!1}),TW=zW({isInternal:!0});nX.displayName="SimpleBezierEdge";TW.displayName="SimpleBezierEdgeInternal";function EW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,sourcePosition:U=wu.Bottom,targetPosition:Q=wu.Top,markerEnd:L,markerStart:w,pathOptions:J,interactionWidth:N})=>{let[q,W,z]=G$({sourceX:l,sourceY:r,sourcePosition:U,targetX:n,targetY:i,targetPosition:Q,borderRadius:J?.borderRadius,offset:J?.offset,stepPosition:J?.stepPosition}),Z=u.isInternal?void 0:f;return ru.jsx(Ay,{id:Z,path:q,labelX:W,labelY:z,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,markerEnd:L,markerStart:w,interactionWidth:N})})}var ZW=EW({isInternal:!1}),OW=EW({isInternal:!0});ZW.displayName="SmoothStepEdge";OW.displayName="SmoothStepEdgeInternal";function HW(u){return yu.memo(({id:f,...l})=>{let r=u.isInternal?void 0:f;return ru.jsx(ZW,{...l,id:r,pathOptions:yu.useMemo(()=>({borderRadius:0,offset:l.pathOptions?.offset}),[l.pathOptions?.offset])})})}var iX=HW({isInternal:!1}),BW=HW({isInternal:!0});iX.displayName="StepEdge";BW.displayName="StepEdgeInternal";function VW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,markerEnd:U,markerStart:Q,interactionWidth:L})=>{let[w,J,N]=I6({sourceX:l,sourceY:r,targetX:n,targetY:i}),q=u.isInternal?void 0:f;return ru.jsx(Ay,{id:q,path:w,labelX:J,labelY:N,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,markerEnd:U,markerStart:Q,interactionWidth:L})})}var yX=VW({isInternal:!1}),DW=VW({isInternal:!0});yX.displayName="StraightEdge";DW.displayName="StraightEdgeInternal";function XW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,sourcePosition:y=wu.Bottom,targetPosition:_=wu.Top,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,pathOptions:J,interactionWidth:N})=>{let[q,W,z]=k6({sourceX:l,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:_,curvature:J?.curvature}),Z=u.isInternal?void 0:f;return ru.jsx(Ay,{id:Z,path:q,labelX:W,labelY:z,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,interactionWidth:N})})}var _X=XW({isInternal:!1}),YW=XW({isInternal:!0});_X.displayName="BezierEdge";YW.displayName="BezierEdgeInternal";var lW={default:YW,straight:DW,step:BW,smoothstep:OW,simplebezier:TW},rW={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null},$X=(u,f,l)=>{if(l===wu.Left)return u-f;if(l===wu.Right)return u+f;return u},tX=(u,f,l)=>{if(l===wu.Top)return u-f;if(l===wu.Bottom)return u+f;return u},nW="react-flow__edgeupdater";function iW({position:u,centerX:f,centerY:l,radius:r=10,onMouseDown:n,onMouseEnter:i,onMouseOut:y,type:_}){return ru.jsx("circle",{onMouseDown:n,onMouseEnter:i,onMouseOut:y,className:Yf([nW,`${nW}-${_}`]),cx:$X(f,r,u),cy:tX(l,r,u),r,stroke:"transparent",fill:"transparent"})}function AX({isReconnectable:u,reconnectRadius:f,edge:l,sourceX:r,sourceY:n,targetX:i,targetY:y,sourcePosition:_,targetPosition:$,onReconnect:A,onReconnectStart:c,onReconnectEnd:j,setReconnecting:F,setUpdateHover:U}){let Q=Zf(),L=(W,z)=>{if(W.button!==0)return;let{autoPanOnConnect:Z,domNode:H,connectionMode:E,connectionRadius:D,lib:h,onConnectStart:V,cancelConnection:Y,nodeLookup:p,rfId:O,panBy:m,updateConnection:X}=Q.getState(),v=z.type==="target",T=(I,b)=>{F(!1),j?.(I,l,z.type,b)},S=(I)=>A?.(l,I),k=(I,b)=>{F(!0),c?.(W,l,z.type),V?.(I,b)};o6.onPointerDown(W.nativeEvent,{autoPanOnConnect:Z,connectionMode:E,connectionRadius:D,domNode:H,handleId:z.id,nodeId:z.nodeId,nodeLookup:p,isTarget:v,edgeUpdaterType:z.type,lib:h,flowId:O,cancelConnection:Y,panBy:m,isValidConnection:(...I)=>Q.getState().isValidConnection?.(...I)??!0,onConnect:S,onConnectStart:k,onConnectEnd:(...I)=>Q.getState().onConnectEnd?.(...I),onReconnectEnd:T,updateConnection:X,getTransform:()=>Q.getState().transform,getFromHandle:()=>Q.getState().connection.fromHandle,dragThreshold:Q.getState().connectionDragThreshold,handleDomNode:W.currentTarget})},w=(W)=>L(W,{nodeId:l.target,id:l.targetHandle??null,type:"target"}),J=(W)=>L(W,{nodeId:l.source,id:l.sourceHandle??null,type:"source"}),N=()=>U(!0),q=()=>U(!1);return ru.jsxs(ru.Fragment,{children:[(u===!0||u==="source")&&ru.jsx(iW,{position:_,centerX:r,centerY:n,radius:f,onMouseDown:w,onMouseEnter:N,onMouseOut:q,type:"source"}),(u===!0||u==="target")&&ru.jsx(iW,{position:$,centerX:i,centerY:y,radius:f,onMouseDown:J,onMouseEnter:N,onMouseOut:q,type:"target"})]})}function cX({id:u,edgesFocusable:f,edgesReconnectable:l,elementsSelectable:r,onClick:n,onDoubleClick:i,onContextMenu:y,onMouseEnter:_,onMouseMove:$,onMouseLeave:A,reconnectRadius:c,onReconnect:j,onReconnectStart:F,onReconnectEnd:U,rfId:Q,edgeTypes:L,noPanClassName:w,onError:J,disableKeyboardA11y:N}){let q=eu((P)=>P.edgeLookup.get(u)),W=eu((P)=>P.defaultEdgeOptions);q=W?{...W,...q}:q;let z=q.type||"default",Z=L?.[z]||lW[z];if(Z===void 0)J?.("011",Fr.error011(z)),z="default",Z=L?.default||lW.default;let H=!!(q.focusable||f&&typeof q.focusable>"u"),E=typeof j<"u"&&(q.reconnectable||l&&typeof q.reconnectable>"u"),D=!!(q.selectable||r&&typeof q.selectable>"u"),h=yu.useRef(null),[V,Y]=yu.useState(!1),[p,O]=yu.useState(!1),m=Zf(),{zIndex:X,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b}=eu(yu.useCallback((P)=>{let e=P.nodeLookup.get(q.source),uu=P.nodeLookup.get(q.target);if(!e||!uu)return{zIndex:q.zIndex,...rW};let Wu=_N({id:u,sourceNode:e,targetNode:uu,sourceHandle:q.sourceHandle||null,targetHandle:q.targetHandle||null,connectionMode:P.connectionMode,onError:J});return{zIndex:iN({selected:q.selected,zIndex:q.zIndex,sourceNode:e,targetNode:uu,elevateOnSelect:P.elevateEdgesOnSelect,zIndexMode:P.zIndexMode}),...Wu||rW}},[q.source,q.target,q.sourceHandle,q.targetHandle,q.selected,q.zIndex]),zf),o=yu.useMemo(()=>q.markerStart?`url('#${g6(q.markerStart,Q)}')`:void 0,[q.markerStart,Q]),s=yu.useMemo(()=>q.markerEnd?`url('#${g6(q.markerEnd,Q)}')`:void 0,[q.markerEnd,Q]);if(q.hidden||v===null||T===null||S===null||k===null)return null;let x=(P)=>{let{addSelectedEdges:e,unselectNodesAndEdges:uu,multiSelectionActive:Wu}=m.getState();if(D)if(m.setState({nodesSelectionActive:!1}),q.selected&&Wu)uu({nodes:[],edges:[q]}),h.current?.blur();else e([u]);if(n)n(P,q)},fu=i?(P)=>{i(P,{...q})}:void 0,$u=y?(P)=>{y(P,{...q})}:void 0,tu=_?(P)=>{_(P,{...q})}:void 0,ju=$?(P)=>{$(P,{...q})}:void 0,Gu=A?(P)=>{A(P,{...q})}:void 0,qu=(P)=>{if(!N&&Sc.includes(P.key)&&D){let{unselectNodesAndEdges:e,addSelectedEdges:uu}=m.getState();if(P.key==="Escape")h.current?.blur(),e({edges:[q]});else uu([u])}};return ru.jsx("svg",{style:{zIndex:X},children:ru.jsxs("g",{className:Yf(["react-flow__edge",`react-flow__edge-${z}`,q.className,w,{selected:q.selected,animated:q.animated,inactive:!D&&!n,updating:V,selectable:D}]),onClick:x,onDoubleClick:fu,onContextMenu:$u,onMouseEnter:tu,onMouseMove:ju,onMouseLeave:Gu,onKeyDown:H?qu:void 0,tabIndex:H?0:void 0,role:q.ariaRole??(H?"group":"img"),"aria-roledescription":"edge","data-id":u,"data-testid":`rf__edge-${u}`,"aria-label":q.ariaLabel===null?void 0:q.ariaLabel||`Edge from ${q.source} to ${q.target}`,"aria-describedby":H?`${cW}-${Q}`:void 0,ref:h,...q.domAttributes,children:[!p&&ru.jsx(Z,{id:u,source:q.source,target:q.target,type:q.type,selected:q.selected,animated:q.animated,selectable:D,deletable:q.deletable??!0,label:q.label,labelStyle:q.labelStyle,labelShowBg:q.labelShowBg,labelBgStyle:q.labelBgStyle,labelBgPadding:q.labelBgPadding,labelBgBorderRadius:q.labelBgBorderRadius,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b,data:q.data,style:q.style,sourceHandleId:q.sourceHandle,targetHandleId:q.targetHandle,markerStart:o,markerEnd:s,pathOptions:"pathOptions"in q?q.pathOptions:void 0,interactionWidth:q.interactionWidth}),E&&ru.jsx(AX,{edge:q,isReconnectable:E,reconnectRadius:c,onReconnect:j,onReconnectStart:F,onReconnectEnd:U,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b,setUpdateHover:Y,setReconnecting:O})]})})}var jX=yu.memo(cX),FX=(u)=>({edgesFocusable:u.edgesFocusable,edgesReconnectable:u.edgesReconnectable,elementsSelectable:u.elementsSelectable,connectionMode:u.connectionMode,onError:u.onError});function SW({defaultMarkerColor:u,onlyRenderVisibleElements:f,rfId:l,edgeTypes:r,noPanClassName:n,onReconnect:i,onEdgeContextMenu:y,onEdgeMouseEnter:_,onEdgeMouseMove:$,onEdgeMouseLeave:A,onEdgeClick:c,reconnectRadius:j,onEdgeDoubleClick:F,onReconnectStart:U,onReconnectEnd:Q,disableKeyboardA11y:L}){let{edgesFocusable:w,edgesReconnectable:J,elementsSelectable:N,onError:q}=eu(FX,zf),W=oD(f);return ru.jsxs("div",{className:"react-flow__edges",children:[ru.jsx(lX,{defaultColor:u,rfId:l}),W.map((z)=>{return ru.jsx(jX,{id:z,edgesFocusable:w,edgesReconnectable:J,elementsSelectable:N,noPanClassName:n,onReconnect:i,onContextMenu:y,onMouseEnter:_,onMouseMove:$,onMouseLeave:A,onClick:c,reconnectRadius:j,onDoubleClick:F,onReconnectStart:U,onReconnectEnd:Q,rfId:l,onError:q,edgeTypes:r,disableKeyboardA11y:L},z)})]})}SW.displayName="EdgeRenderer";var JX=yu.memo(SW),UX=(u)=>`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]})`;function QX({children:u}){let f=eu(UX);return ru.jsx("div",{className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:f},children:u})}function qX(u){let f=c9(),l=yu.useRef(!1);yu.useEffect(()=>{if(!l.current&&f.viewportInitialized&&u)setTimeout(()=>u(f),1),l.current=!0},[u,f.viewportInitialized])}var NX=(u)=>u.panZoom?.syncViewport;function WX(u){let f=eu(NX),l=Zf();return yu.useEffect(()=>{if(u)f?.(u),l.setState({transform:[u.x,u.y,u.zoom]})},[u,f]),null}function yW(u){return u.connection.inProgress?{...u.connection,to:yy(u.connection.to,u.transform)}:{...u.connection}}function LX(u){if(u)return(l)=>{let r=yW(l);return u(r)};return yW}function wX(u){let f=LX(u);return eu(f,zf)}var KX=(u)=>({nodesConnectable:u.nodesConnectable,isValid:u.connection.isValid,inProgress:u.connection.inProgress,width:u.width,height:u.height});function GX({containerStyle:u,style:f,type:l,component:r}){let{nodesConnectable:n,width:i,height:y,isValid:_,inProgress:$}=eu(KX,zf);if(!(i&&n&&$))return null;return ru.jsx("svg",{style:u,width:i,height:y,className:"react-flow__connectionline react-flow__container",children:ru.jsx("g",{className:Yf(["react-flow__connection",Pc(_)]),children:ru.jsx(pW,{style:f,type:l,CustomComponent:r,isValid:_})})})}var pW=({style:u,type:f=$0.Bezier,CustomComponent:l,isValid:r})=>{let{inProgress:n,from:i,fromNode:y,fromHandle:_,fromPosition:$,to:A,toNode:c,toHandle:j,toPosition:F,pointer:U}=wX();if(!n)return;if(l)return ru.jsx(l,{connectionLineType:f,connectionLineStyle:u,fromNode:y,fromHandle:_,fromX:i.x,fromY:i.y,toX:A.x,toY:A.y,fromPosition:$,toPosition:F,connectionStatus:Pc(r),toNode:c,toHandle:j,pointer:U});let Q="",L={sourceX:i.x,sourceY:i.y,sourcePosition:$,targetX:A.x,targetY:A.y,targetPosition:F};switch(f){case $0.Bezier:[Q]=k6(L);break;case $0.SimpleBezier:[Q]=GW(L);break;case $0.Step:[Q]=G$({...L,borderRadius:0});break;case $0.SmoothStep:[Q]=G$(L);break;default:[Q]=I6(L)}return ru.jsx("path",{d:Q,fill:"none",className:"react-flow__connection-path",style:u})};pW.displayName="ConnectionLine";var zX={};function _W(u=zX){let f=yu.useRef(u),l=Zf();yu.useEffect(()=>{},[u])}function TX(){let u=Zf(),f=yu.useRef(!1);yu.useEffect(()=>{},[])}function mW({nodeTypes:u,edgeTypes:f,onInit:l,onNodeClick:r,onEdgeClick:n,onNodeDoubleClick:i,onEdgeDoubleClick:y,onNodeMouseEnter:_,onNodeMouseMove:$,onNodeMouseLeave:A,onNodeContextMenu:c,onSelectionContextMenu:j,onSelectionStart:F,onSelectionEnd:U,connectionLineType:Q,connectionLineStyle:L,connectionLineComponent:w,connectionLineContainerStyle:J,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,deleteKeyCode:E,onlyRenderVisibleElements:D,elementsSelectable:h,defaultViewport:V,translateExtent:Y,minZoom:p,maxZoom:O,preventScrolling:m,defaultMarkerColor:X,zoomOnScroll:v,zoomOnPinch:T,panOnScroll:S,panOnScrollSpeed:k,panOnScrollMode:I,zoomOnDoubleClick:b,panOnDrag:o,onPaneClick:s,onPaneMouseEnter:x,onPaneMouseMove:fu,onPaneMouseLeave:$u,onPaneScroll:tu,onPaneContextMenu:ju,paneClickDistance:Gu,nodeClickDistance:qu,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:Wu,reconnectRadius:g,onReconnect:Qu,onReconnectStart:Tu,onReconnectEnd:Zu,noDragClassName:Xu,noWheelClassName:uf,noPanClassName:_f,disableKeyboardA11y:Jf,nodeExtent:Pf,rfId:Sl,viewport:vf,onViewportChange:ll}){return _W(u),_W(f),TX(),qX(l),WX(vf),ru.jsx(RD,{onPaneClick:s,onPaneMouseEnter:x,onPaneMouseMove:fu,onPaneMouseLeave:$u,onPaneContextMenu:ju,onPaneScroll:tu,paneClickDistance:Gu,deleteKeyCode:E,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,onSelectionStart:F,onSelectionEnd:U,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,elementsSelectable:h,zoomOnScroll:v,zoomOnPinch:T,zoomOnDoubleClick:b,panOnScroll:S,panOnScrollSpeed:k,panOnScrollMode:I,panOnDrag:o,defaultViewport:V,translateExtent:Y,minZoom:p,maxZoom:O,onSelectionContextMenu:j,preventScrolling:m,noDragClassName:Xu,noWheelClassName:uf,noPanClassName:_f,disableKeyboardA11y:Jf,onViewportChange:ll,isControlledViewport:!!vf,children:ru.jsxs(QX,{children:[ru.jsx(JX,{edgeTypes:f,onEdgeClick:n,onEdgeDoubleClick:y,onReconnect:Qu,onReconnectStart:Tu,onReconnectEnd:Zu,onlyRenderVisibleElements:D,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:Wu,reconnectRadius:g,defaultMarkerColor:X,noPanClassName:_f,disableKeyboardA11y:Jf,rfId:Sl}),ru.jsx(GX,{style:L,type:Q,component:w,containerStyle:J}),ru.jsx("div",{className:"react-flow__edgelabel-renderer"}),ru.jsx(aD,{nodeTypes:u,onNodeClick:r,onNodeDoubleClick:i,onNodeMouseEnter:_,onNodeMouseMove:$,onNodeMouseLeave:A,onNodeContextMenu:c,nodeClickDistance:qu,onlyRenderVisibleElements:D,noPanClassName:_f,noDragClassName:Xu,disableKeyboardA11y:Jf,nodeExtent:Pf,rfId:Sl}),ru.jsx("div",{className:"react-flow__viewport-portal"})]})})}mW.displayName="GraphView";var EX=yu.memo(mW),$W=({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$=0.5,maxZoom:A=2,nodeOrigin:c,nodeExtent:j,zIndexMode:F="basic"}={})=>{let U=new Map,Q=new Map,L=new Map,w=new Map,J=r??f??[],N=l??u??[],q=c??[0,0],W=j??ly;n9(L,w,J);let{nodesInitialized:z}=s6(N,U,Q,{nodeOrigin:q,nodeExtent:W,zIndexMode:F}),Z=[0,0,1];if(y&&n&&i){let H=ry(U,{filter:(V)=>!!((V.width||V.initialWidth)&&(V.height||V.initialHeight))}),{x:E,y:D,zoom:h}=K$(H,n,i,$,A,_?.padding??0.1);Z=[E,D,h]}return{rfId:"1",width:n??0,height:i??0,transform:Z,nodes:N,nodesInitialized:z,nodeLookup:U,parentLookup:Q,edges:J,edgeLookup:w,connectionLookup:L,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:l!==void 0,hasDefaultEdges:r!==void 0,panZoom:null,minZoom:$,maxZoom:A,translateExtent:ly,nodeExtent:W,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:Vn.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:q,nodeDragThreshold:1,connectionDragThreshold:1,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesReconnectable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,elevateEdgesOnSelect:!0,selectNodesOnDrag:!0,multiSelectionActive:!1,fitViewQueued:y??!1,fitViewOptions:_,fitViewResolver:null,connection:{...mc},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:vc,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:pc,zIndexMode:F,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},ZX=({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$,maxZoom:A,nodeOrigin:c,nodeExtent:j,zIndexMode:F})=>MN((U,Q)=>{async function L(){let{nodeLookup:w,panZoom:J,fitViewOptions:N,fitViewResolver:q,width:W,height:z,minZoom:Z,maxZoom:H}=Q();if(!J)return;await eq({nodes:w,width:W,height:z,panZoom:J,minZoom:Z,maxZoom:H},N),q?.resolve(!0),U({fitViewResolver:null})}return{...$W({nodes:u,edges:f,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$,maxZoom:A,nodeOrigin:c,nodeExtent:j,defaultNodes:l,defaultEdges:r,zIndexMode:F}),setNodes:(w)=>{let{nodeLookup:J,parentLookup:N,nodeOrigin:q,elevateNodesOnSelect:W,fitViewQueued:z,zIndexMode:Z,nodesSelectionActive:H}=Q(),{nodesInitialized:E,hasSelectedNodes:D}=s6(w,J,N,{nodeOrigin:q,nodeExtent:j,elevateNodesOnSelect:W,checkEquality:!0,zIndexMode:Z}),h=H&&D;if(z&&E)L(),U({nodes:w,nodesInitialized:E,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:h});else U({nodes:w,nodesInitialized:E,nodesSelectionActive:h})},setEdges:(w)=>{let{connectionLookup:J,edgeLookup:N}=Q();n9(J,N,w),U({edges:w})},setDefaultNodesAndEdges:(w,J)=>{if(w){let{setNodes:N}=Q();N(w),U({hasDefaultNodes:!0})}if(J){let{setEdges:N}=Q();N(J),U({hasDefaultEdges:!0})}},updateNodeInternals:(w)=>{let{triggerNodeChanges:J,nodeLookup:N,parentLookup:q,domNode:W,nodeOrigin:z,nodeExtent:Z,debug:H,fitViewQueued:E,zIndexMode:D}=Q(),{changes:h,updatedInternals:V}=jN(w,N,q,W,z,Z,D);if(!V)return;if(AN(N,q,{nodeOrigin:z,nodeExtent:Z,zIndexMode:D}),E)L(),U({fitViewQueued:!1,fitViewOptions:void 0});else U({});if(h?.length>0){if(H)console.log("React Flow: trigger node changes",h);J?.(h)}},updateNodePositions:(w,J=!1)=>{let N=[],q=[],{nodeLookup:W,triggerNodeChanges:z,connection:Z,updateConnection:H,onNodesChangeMiddlewareMap:E}=Q();for(let[D,h]of w){let V=W.get(D),Y=!!(V?.expandParent&&V?.parentId&&h?.position),p={id:D,type:"position",position:Y?{x:Math.max(0,h.position.x),y:Math.max(0,h.position.y)}:h.position,dragging:J};if(V&&Z.inProgress&&Z.fromNode.id===V.id){let O=Xn(V,Z.fromHandle,wu.Left,!0);H({...Z,from:O})}if(Y&&V.parentId)N.push({id:D,parentId:V.parentId,rect:{...h.internals.positionAbsolute,width:h.measured.width??0,height:h.measured.height??0}});q.push(p)}if(N.length>0){let{parentLookup:D,nodeOrigin:h}=Q(),V=a6(N,W,D,h);q.push(...V)}for(let D of E.values())q=D(q);z(q)},triggerNodeChanges:(w)=>{let{onNodesChange:J,setNodes:N,nodes:q,hasDefaultNodes:W,debug:z}=Q();if(w?.length){if(W){let Z=jD(w,q);N(Z)}if(z)console.log("React Flow: trigger node changes",w);J?.(w)}},triggerEdgeChanges:(w)=>{let{onEdgesChange:J,setEdges:N,edges:q,hasDefaultEdges:W,debug:z}=Q();if(w?.length){if(W){let Z=FD(w,q);N(Z)}if(z)console.log("React Flow: trigger edge changes",w);J?.(w)}},addSelectedNodes:(w)=>{let{multiSelectionActive:J,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(J){let Z=w.map((H)=>p1(H,!0));W(Z);return}W(ty(q,new Set([...w]),!0)),z(ty(N))},addSelectedEdges:(w)=>{let{multiSelectionActive:J,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(J){let Z=w.map((H)=>p1(H,!0));z(Z);return}z(ty(N,new Set([...w]))),W(ty(q,new Set,!0))},unselectNodesAndEdges:({nodes:w,edges:J}={})=>{let{edges:N,nodes:q,nodeLookup:W,triggerNodeChanges:z,triggerEdgeChanges:Z}=Q(),H=w?w:q,E=J?J:N,D=[];for(let V of H){if(!V.selected)continue;let Y=W.get(V.id);if(Y)Y.selected=!1;D.push(p1(V.id,!1))}let h=[];for(let V of E){if(!V.selected)continue;h.push(p1(V.id,!1))}z(D),Z(h)},setMinZoom:(w)=>{let{panZoom:J,maxZoom:N}=Q();J?.setScaleExtent([w,N]),U({minZoom:w})},setMaxZoom:(w)=>{let{panZoom:J,minZoom:N}=Q();J?.setScaleExtent([N,w]),U({maxZoom:w})},setTranslateExtent:(w)=>{Q().panZoom?.setTranslateExtent(w),U({translateExtent:w})},resetSelectedElements:()=>{let{edges:w,nodes:J,triggerNodeChanges:N,triggerEdgeChanges:q,elementsSelectable:W}=Q();if(!W)return;let z=J.reduce((H,E)=>E.selected?[...H,p1(E.id,!1)]:H,[]),Z=w.reduce((H,E)=>E.selected?[...H,p1(E.id,!1)]:H,[]);N(z),q(Z)},setNodeExtent:(w)=>{let{nodes:J,nodeLookup:N,parentLookup:q,nodeOrigin:W,elevateNodesOnSelect:z,nodeExtent:Z,zIndexMode:H}=Q();if(w[0][0]===Z[0][0]&&w[0][1]===Z[0][1]&&w[1][0]===Z[1][0]&&w[1][1]===Z[1][1])return;s6(J,N,q,{nodeOrigin:W,nodeExtent:w,elevateNodesOnSelect:z,checkEquality:!1,zIndexMode:H}),U({nodeExtent:w})},panBy:(w)=>{let{transform:J,width:N,height:q,panZoom:W,translateExtent:z}=Q();return FN({delta:w,panZoom:W,transform:J,translateExtent:z,width:N,height:q})},setCenter:async(w,J,N)=>{let{width:q,height:W,maxZoom:z,panZoom:Z}=Q();if(!Z)return Promise.resolve(!1);let H=typeof N?.zoom<"u"?N.zoom:z;return await Z.setViewport({x:q/2-w*H,y:W/2-J*H,zoom:H},{duration:N?.duration,ease:N?.ease,interpolate:N?.interpolate}),Promise.resolve(!0)},cancelConnection:()=>{U({connection:{...mc}})},updateConnection:(w)=>{U({connection:w})},reset:()=>U({...$W()})}},Object.is);function OX({initialNodes:u,initialEdges:f,defaultNodes:l,defaultEdges:r,initialWidth:n,initialHeight:i,initialMinZoom:y,initialMaxZoom:_,initialFitViewOptions:$,fitView:A,nodeOrigin:c,nodeExtent:j,zIndexMode:F,children:U}){let[Q]=yu.useState(()=>ZX({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:A,minZoom:y,maxZoom:_,fitViewOptions:$,nodeOrigin:c,nodeExtent:j,zIndexMode:F}));return ru.jsx(kV,{value:Q,children:ru.jsx(QD,{children:U})})}function HX({children:u,nodes:f,edges:l,defaultNodes:r,defaultEdges:n,width:i,height:y,fitView:_,fitViewOptions:$,minZoom:A,maxZoom:c,nodeOrigin:j,nodeExtent:F,zIndexMode:U}){if(yu.useContext(r8))return ru.jsx(ru.Fragment,{children:u});return ru.jsx(OX,{initialNodes:f,initialEdges:l,defaultNodes:r,defaultEdges:n,initialWidth:i,initialHeight:y,fitView:_,initialFitViewOptions:$,initialMinZoom:A,initialMaxZoom:c,nodeOrigin:j,nodeExtent:F,zIndexMode:U,children:u})}var BX={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function VX({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,className:n,nodeTypes:i,edgeTypes:y,onNodeClick:_,onEdgeClick:$,onInit:A,onMove:c,onMoveStart:j,onMoveEnd:F,onConnect:U,onConnectStart:Q,onConnectEnd:L,onClickConnectStart:w,onClickConnectEnd:J,onNodeMouseEnter:N,onNodeMouseMove:q,onNodeMouseLeave:W,onNodeContextMenu:z,onNodeDoubleClick:Z,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onNodesDelete:h,onEdgesDelete:V,onDelete:Y,onSelectionChange:p,onSelectionDragStart:O,onSelectionDrag:m,onSelectionDragStop:X,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:S,onBeforeDelete:k,connectionMode:I,connectionLineType:b=$0.Bezier,connectionLineStyle:o,connectionLineComponent:s,connectionLineContainerStyle:x,deleteKeyCode:fu="Backspace",selectionKeyCode:$u="Shift",selectionOnDrag:tu=!1,selectionMode:ju=X1.Full,panActivationKeyCode:Gu="Space",multiSelectionKeyCode:qu=_y()?"Meta":"Control",zoomActivationKeyCode:P=_y()?"Meta":"Control",snapToGrid:e,snapGrid:uu,onlyRenderVisibleElements:Wu=!1,selectNodesOnDrag:g,nodesDraggable:Qu,autoPanOnNodeFocus:Tu,nodesConnectable:Zu,nodesFocusable:Xu,nodeOrigin:uf=jW,edgesFocusable:_f,edgesReconnectable:Jf,elementsSelectable:Pf=!0,defaultViewport:Sl=iD,minZoom:vf=0.5,maxZoom:ll=2,translateExtent:dl=ly,preventScrolling:el=!0,nodeExtent:cu,defaultMarkerColor:ku="#b1b1b7",zoomOnScroll:Tl=!0,zoomOnPinch:pu=!0,panOnScroll:rl=!1,panOnScrollSpeed:El=0.5,panOnScrollMode:Jl=C0.Free,zoomOnDoubleClick:nl=!0,panOnDrag:pl=!0,onPaneClick:qr,onPaneMouseEnter:rf,onPaneMouseMove:C1,onPaneMouseLeave:kn,onPaneScroll:R1,onPaneContextMenu:lu,paneClickDistance:Ou=1,nodeClickDistance:Yu=0,children:Iu,onReconnect:Qf,onReconnectStart:il,onReconnectEnd:ff,onEdgeContextMenu:df,onEdgeDoubleClick:$f,onEdgeMouseEnter:C$,onEdgeMouseMove:V8,onEdgeMouseLeave:Tf,reconnectRadius:u7=10,onNodesChange:kf,onEdgesChange:ur,noDragClassName:Wy="nodrag",noWheelClassName:R$="nowheel",noPanClassName:x1="nopan",fitView:Ly,fitViewOptions:h1,connectOnClick:x$,attributionPosition:ml,proOptions:sr,defaultEdgeOptions:h$,elevateNodesOnSelect:b$=!0,elevateEdgesOnSelect:wy=!1,disableKeyboardA11y:Ky=!1,autoPanOnConnect:ar,autoPanOnNodeDrag:v$,autoPanSpeed:pf,connectionRadius:D8,isValidConnection:k$,onError:Dr,style:In,id:b0,nodeDragThreshold:b1,connectionDragThreshold:gn,viewport:Gy,onViewportChange:f7,width:v1,height:l7,colorMode:I$="light",debug:X8,onScroll:g$,ariaLabelConfig:Y8,zIndexMode:U0="basic",...k1},sn){let Ul=b0||"1",s$=tD(I$),zy=yu.useCallback((fr)=>{fr.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),g$?.(fr)},[g$]);return ru.jsx("div",{"data-testid":"rf__wrapper",...k1,onScroll:zy,style:{...In,...BX},ref:sn,className:Yf(["react-flow",n,s$]),id:b0,role:"application",children:ru.jsxs(HX,{nodes:u,edges:f,width:v1,height:l7,fitView:Ly,fitViewOptions:h1,minZoom:vf,maxZoom:ll,nodeOrigin:uf,nodeExtent:cu,zIndexMode:U0,children:[ru.jsx($D,{nodes:u,edges:f,defaultNodes:l,defaultEdges:r,onConnect:U,onConnectStart:Q,onConnectEnd:L,onClickConnectStart:w,onClickConnectEnd:J,nodesDraggable:Qu,autoPanOnNodeFocus:Tu,nodesConnectable:Zu,nodesFocusable:Xu,edgesFocusable:_f,edgesReconnectable:Jf,elementsSelectable:Pf,elevateNodesOnSelect:b$,elevateEdgesOnSelect:wy,minZoom:vf,maxZoom:ll,nodeExtent:cu,onNodesChange:kf,onEdgesChange:ur,snapToGrid:e,snapGrid:uu,connectionMode:I,translateExtent:dl,connectOnClick:x$,defaultEdgeOptions:h$,fitView:Ly,fitViewOptions:h1,onNodesDelete:h,onEdgesDelete:V,onDelete:Y,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onSelectionDrag:m,onSelectionDragStart:O,onSelectionDragStop:X,onMove:c,onMoveStart:j,onMoveEnd:F,noPanClassName:x1,nodeOrigin:uf,rfId:Ul,autoPanOnConnect:ar,autoPanOnNodeDrag:v$,autoPanSpeed:pf,onError:Dr,connectionRadius:D8,isValidConnection:k$,selectNodesOnDrag:g,nodeDragThreshold:b1,connectionDragThreshold:gn,onBeforeDelete:k,debug:X8,ariaLabelConfig:Y8,zIndexMode:U0}),ru.jsx(EX,{onInit:A,onNodeClick:_,onEdgeClick:$,onNodeMouseEnter:N,onNodeMouseMove:q,onNodeMouseLeave:W,onNodeContextMenu:z,onNodeDoubleClick:Z,nodeTypes:i,edgeTypes:y,connectionLineType:b,connectionLineStyle:o,connectionLineComponent:s,connectionLineContainerStyle:x,selectionKeyCode:$u,selectionOnDrag:tu,selectionMode:ju,deleteKeyCode:fu,multiSelectionKeyCode:qu,panActivationKeyCode:Gu,zoomActivationKeyCode:P,onlyRenderVisibleElements:Wu,defaultViewport:Sl,translateExtent:dl,minZoom:vf,maxZoom:ll,preventScrolling:el,zoomOnScroll:Tl,zoomOnPinch:pu,zoomOnDoubleClick:nl,panOnScroll:rl,panOnScrollSpeed:El,panOnScrollMode:Jl,panOnDrag:pl,onPaneClick:qr,onPaneMouseEnter:rf,onPaneMouseMove:C1,onPaneMouseLeave:kn,onPaneScroll:R1,onPaneContextMenu:lu,paneClickDistance:Ou,nodeClickDistance:Yu,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:S,onReconnect:Qf,onReconnectStart:il,onReconnectEnd:ff,onEdgeContextMenu:df,onEdgeDoubleClick:$f,onEdgeMouseEnter:C$,onEdgeMouseMove:V8,onEdgeMouseLeave:Tf,reconnectRadius:u7,defaultMarkerColor:ku,noDragClassName:Wy,noWheelClassName:R$,noPanClassName:x1,rfId:Ul,disableKeyboardA11y:Ky,nodeExtent:cu,viewport:Gy,onViewportChange:f7}),ru.jsx(nD,{onSelectionChange:p}),Iu,ru.jsx(eV,{proOptions:sr,position:ml}),ru.jsx(dV,{rfId:Ul,disableKeyboardA11y:Ky})]})})}var PW=JW(VX);var cb=Fr.error014();function DX({dimensions:u,lineWidth:f,variant:l,className:r}){return ru.jsx("path",{strokeWidth:f,d:`M${u[0]/2} 0 V${u[1]} M0 ${u[1]/2} H${u[0]}`,className:Yf(["react-flow__background-pattern",l,r])})}function XX({radius:u,className:f}){return ru.jsx("circle",{cx:u,cy:u,r:u,className:Yf(["react-flow__background-pattern","dots",f])})}var Sn;(function(u){u.Lines="lines",u.Dots="dots",u.Cross="cross"})(Sn||(Sn={}));var YX={[Sn.Dots]:1,[Sn.Lines]:1,[Sn.Cross]:6},SX=(u)=>({transform:u.transform,patternId:`pattern-${u.rfId}`});function MW({id:u,variant:f=Sn.Dots,gap:l=20,size:r,lineWidth:n=1,offset:i=0,color:y,bgColor:_,style:$,className:A,patternClassName:c}){let j=yu.useRef(null),{transform:F,patternId:U}=eu(SX,zf),Q=r||YX[f],L=f===Sn.Dots,w=f===Sn.Cross,J=Array.isArray(l)?l:[l,l],N=[J[0]*F[2]||1,J[1]*F[2]||1],q=Q*F[2],W=Array.isArray(i)?i:[i,i],z=w?[q,q]:N,Z=[W[0]*F[2]||1+z[0]/2,W[1]*F[2]||1+z[1]/2],H=`${U}${u?u:""}`;return ru.jsxs("svg",{className:Yf(["react-flow__background",A]),style:{...$,...i8,"--xy-background-color-props":_,"--xy-background-pattern-color-props":y},ref:j,"data-testid":"rf__background",children:[ru.jsx("pattern",{id:H,x:F[0]%N[0],y:F[1]%N[1],width:N[0],height:N[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${Z[0]},-${Z[1]})`,children:L?ru.jsx(XX,{radius:q/2,className:c}):ru.jsx(DX,{dimensions:z,lineWidth:n,variant:f,className:c})}),ru.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${H})`})]})}MW.displayName="Background";var CW=yu.memo(MW);function pX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:ru.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function mX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:ru.jsx("path",{d:"M0 0h32v4.2H0z"})})}function PX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:ru.jsx("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"})})}function MX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:ru.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"})})}function CX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:ru.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"})})}function f8({children:u,className:f,...l}){return ru.jsx("button",{type:"button",className:Yf(["react-flow__controls-button",f]),...l,children:u})}var RX=(u)=>({isInteractive:u.nodesDraggable||u.nodesConnectable||u.elementsSelectable,minZoomReached:u.transform[2]<=u.minZoom,maxZoomReached:u.transform[2]>=u.maxZoom,ariaLabelConfig:u.ariaLabelConfig});function RW({style:u,showZoom:f=!0,showFitView:l=!0,showInteractive:r=!0,fitViewOptions:n,onZoomIn:i,onZoomOut:y,onFitView:_,onInteractiveChange:$,className:A,children:c,position:j="bottom-left",orientation:F="vertical","aria-label":U}){let Q=Zf(),{isInteractive:L,minZoomReached:w,maxZoomReached:J,ariaLabelConfig:N}=eu(RX,zf),{zoomIn:q,zoomOut:W,fitView:z}=c9(),Z=()=>{q(),i?.()},H=()=>{W(),y?.()},E=()=>{z(n),_?.()},D=()=>{Q.setState({nodesDraggable:!L,nodesConnectable:!L,elementsSelectable:!L}),$?.(!L)};return ru.jsxs(n8,{className:Yf(["react-flow__controls",F==="horizontal"?"horizontal":"vertical",A]),position:j,style:u,"data-testid":"rf__controls","aria-label":U??N["controls.ariaLabel"],children:[f&&ru.jsxs(ru.Fragment,{children:[ru.jsx(f8,{onClick:Z,className:"react-flow__controls-zoomin",title:N["controls.zoomIn.ariaLabel"],"aria-label":N["controls.zoomIn.ariaLabel"],disabled:J,children:ru.jsx(pX,{})}),ru.jsx(f8,{onClick:H,className:"react-flow__controls-zoomout",title:N["controls.zoomOut.ariaLabel"],"aria-label":N["controls.zoomOut.ariaLabel"],disabled:w,children:ru.jsx(mX,{})})]}),l&&ru.jsx(f8,{className:"react-flow__controls-fitview",onClick:E,title:N["controls.fitView.ariaLabel"],"aria-label":N["controls.fitView.ariaLabel"],children:ru.jsx(PX,{})}),r&&ru.jsx(f8,{className:"react-flow__controls-interactive",onClick:D,title:N["controls.interactive.ariaLabel"],"aria-label":N["controls.interactive.ariaLabel"],children:L?ru.jsx(CX,{}):ru.jsx(MX,{})}),c]})}RW.displayName="Controls";var xW=yu.memo(RW);function xX({id:u,x:f,y:l,width:r,height:n,style:i,color:y,strokeColor:_,strokeWidth:$,className:A,borderRadius:c,shapeRendering:j,selected:F,onClick:U}){let{background:Q,backgroundColor:L}=i||{},w=y||Q||L;return ru.jsx("rect",{className:Yf(["react-flow__minimap-node",{selected:F},A]),x:f,y:l,rx:c,ry:c,width:r,height:n,style:{fill:w,stroke:_,strokeWidth:$},shapeRendering:j,onClick:U?(J)=>U(J,u):void 0})}var hX=yu.memo(xX),bX=(u)=>u.nodes.map((f)=>f.id),$9=(u)=>u instanceof Function?u:()=>u;function vX({nodeStrokeColor:u,nodeColor:f,nodeClassName:l="",nodeBorderRadius:r=5,nodeStrokeWidth:n,nodeComponent:i=hX,onClick:y}){let _=eu(bX,zf),$=$9(f),A=$9(u),c=$9(l),j=typeof window>"u"||!!window.chrome?"crispEdges":"geometricPrecision";return ru.jsx(ru.Fragment,{children:_.map((F)=>ru.jsx(IX,{id:F,nodeColorFunc:$,nodeStrokeColorFunc:A,nodeClassNameFunc:c,nodeBorderRadius:r,nodeStrokeWidth:n,NodeComponent:i,onClick:y,shapeRendering:j},F))})}function kX({id:u,nodeColorFunc:f,nodeStrokeColorFunc:l,nodeClassNameFunc:r,nodeBorderRadius:n,nodeStrokeWidth:i,shapeRendering:y,NodeComponent:_,onClick:$}){let{node:A,x:c,y:j,width:F,height:U}=eu((Q)=>{let L=Q.nodeLookup.get(u);if(!L)return{node:void 0,x:0,y:0,width:0,height:0};let w=L.internals.userNode,{x:J,y:N}=L.internals.positionAbsolute,{width:q,height:W}=t0(w);return{node:w,x:J,y:N,width:q,height:W}},zf);if(!A||A.hidden||!kc(A))return null;return ru.jsx(_,{x:c,y:j,width:F,height:U,style:A.style,selected:!!A.selected,className:r(A),color:f(A),borderRadius:n,strokeColor:l(A),strokeWidth:i,shapeRendering:y,onClick:$,id:A.id})}var IX=yu.memo(kX),gX=yu.memo(vX),sX=200,aX=150,oX=(u)=>!u.hidden,dX=(u)=>{let f={x:-u.transform[0]/u.transform[2],y:-u.transform[1]/u.transform[2],width:u.width/u.transform[2],height:u.height/u.transform[2]};return{viewBB:f,boundingRect:u.nodeLookup.size>0?hc(ry(u.nodeLookup,{filter:oX}),f):f,rfId:u.rfId,panZoom:u.panZoom,translateExtent:u.translateExtent,flowWidth:u.width,flowHeight:u.height,ariaLabelConfig:u.ariaLabelConfig}},eX="react-flow__minimap-desc";function hW({style:u,className:f,nodeStrokeColor:l,nodeColor:r,nodeClassName:n="",nodeBorderRadius:i=5,nodeStrokeWidth:y,nodeComponent:_,bgColor:$,maskColor:A,maskStrokeColor:c,maskStrokeWidth:j,position:F="bottom-right",onClick:U,onNodeClick:Q,pannable:L=!1,zoomable:w=!1,ariaLabel:J,inversePan:N,zoomStep:q=1,offsetScale:W=5}){let z=Zf(),Z=yu.useRef(null),{boundingRect:H,viewBB:E,rfId:D,panZoom:h,translateExtent:V,flowWidth:Y,flowHeight:p,ariaLabelConfig:O}=eu(dX,zf),m=u?.width??sX,X=u?.height??aX,v=H.width/m,T=H.height/X,S=Math.max(v,T),k=S*m,I=S*X,b=W*S,o=H.x-(k-H.width)/2-b,s=H.y-(I-H.height)/2-b,x=k+b*2,fu=I+b*2,$u=`${eX}-${D}`,tu=yu.useRef(0),ju=yu.useRef();tu.current=S,yu.useEffect(()=>{if(Z.current&&h)return ju.current=LN({domNode:Z.current,panZoom:h,getTransform:()=>z.getState().transform,getViewScale:()=>tu.current}),()=>{ju.current?.destroy()}},[h]),yu.useEffect(()=>{ju.current?.update({translateExtent:V,width:Y,height:p,inversePan:N,pannable:L,zoomStep:q,zoomable:w})},[L,w,N,q,V,Y,p]);let Gu=U?(e)=>{let[uu,Wu]=ju.current?.pointer(e)||[0,0];U(e,{x:uu,y:Wu})}:void 0,qu=Q?yu.useCallback((e,uu)=>{let Wu=z.getState().nodeLookup.get(uu).internals.userNode;Q(e,Wu)},[]):void 0,P=J??O["minimap.ariaLabel"];return ru.jsx(n8,{position:F,style:{...u,"--xy-minimap-background-color-props":typeof $==="string"?$:void 0,"--xy-minimap-mask-background-color-props":typeof A==="string"?A:void 0,"--xy-minimap-mask-stroke-color-props":typeof c==="string"?c:void 0,"--xy-minimap-mask-stroke-width-props":typeof j==="number"?j*S:void 0,"--xy-minimap-node-background-color-props":typeof r==="string"?r:void 0,"--xy-minimap-node-stroke-color-props":typeof l==="string"?l:void 0,"--xy-minimap-node-stroke-width-props":typeof y==="number"?y:void 0},className:Yf(["react-flow__minimap",f]),"data-testid":"rf__minimap",children:ru.jsxs("svg",{width:m,height:X,viewBox:`${o} ${s} ${x} ${fu}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":$u,ref:Z,onClick:Gu,children:[P&&ru.jsx("title",{id:$u,children:P}),ru.jsx(gX,{onClick:qu,nodeColor:r,nodeStrokeColor:l,nodeBorderRadius:i,nodeClassName:n,nodeStrokeWidth:y,nodeComponent:_}),ru.jsx("path",{className:"react-flow__minimap-mask",d:`M${o-b},${s-b}h${x+b*2}v${fu+b*2}h${-x-b*2}z - M${E.x},${E.y}h${E.width}v${E.height}h${-E.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}hW.displayName="MiniMap";var jb=yu.memo(hW),uY=(u)=>(f)=>u?`${Math.max(1/f.transform[2],1)}`:void 0,fY={[Yn.Line]:"right",[Yn.Handle]:"bottom-right"};function lY({nodeId:u,position:f,variant:l=Yn.Handle,className:r,style:n=void 0,children:i,color:y,minWidth:_=10,minHeight:$=10,maxWidth:A=Number.MAX_VALUE,maxHeight:c=Number.MAX_VALUE,keepAspectRatio:j=!1,resizeDirection:F,autoScale:U=!0,shouldResize:Q,onResizeStart:L,onResize:w,onResizeEnd:J}){let N=NW(),q=typeof u==="string"?u:N,W=Zf(),z=yu.useRef(null),Z=l===Yn.Handle,H=eu(yu.useCallback(uY(Z&&U),[Z,U]),zf),E=yu.useRef(null),D=f??fY[l];yu.useEffect(()=>{if(!z.current||!q)return;if(!E.current)E.current=TN({domNode:z.current,nodeId:q,getStoreItems:()=>{let{nodeLookup:V,transform:Y,snapGrid:p,snapToGrid:O,nodeOrigin:m,domNode:X}=W.getState();return{nodeLookup:V,transform:Y,snapGrid:p,snapToGrid:O,nodeOrigin:m,paneDomNode:X}},onChange:(V,Y)=>{let{triggerNodeChanges:p,nodeLookup:O,parentLookup:m,nodeOrigin:X}=W.getState(),v=[],T={x:V.x,y:V.y},S=O.get(q);if(S&&S.expandParent&&S.parentId){let k=S.origin??X,I=V.width??S.measured.width??0,b=V.height??S.measured.height??0,o={id:S.id,parentId:S.parentId,rect:{width:I,height:b,...Ic({x:V.x??S.position.x,y:V.y??S.position.y},{width:I,height:b},S.parentId,O,k)}},s=a6([o],O,m,X);v.push(...s),T.x=V.x?Math.max(k[0]*I,V.x):void 0,T.y=V.y?Math.max(k[1]*b,V.y):void 0}if(T.x!==void 0&&T.y!==void 0){let k={id:q,type:"position",position:{...T}};v.push(k)}if(V.width!==void 0&&V.height!==void 0){let I={id:q,type:"dimensions",resizing:!0,setAttributes:!F?!0:F==="horizontal"?"width":"height",dimensions:{width:V.width,height:V.height}};v.push(I)}for(let k of Y){let I={...k,type:"position"};v.push(I)}p(v)},onEnd:({width:V,height:Y})=>{let p={id:q,type:"dimensions",resizing:!1,dimensions:{width:V,height:Y}};W.getState().triggerNodeChanges([p])}});return E.current.update({controlPosition:D,boundaries:{minWidth:_,minHeight:$,maxWidth:A,maxHeight:c},keepAspectRatio:j,resizeDirection:F,onResizeStart:L,onResize:w,onResizeEnd:J,shouldResize:Q}),()=>{E.current?.destroy()}},[D,_,$,A,c,j,L,w,J,Q]);let h=D.split("-");return ru.jsx("div",{className:Yf(["react-flow__resize-control","nodrag",...h,l,r]),ref:z,style:{...n,scale:H,...y&&{[Z?"backgroundColor":"borderColor"]:y}},children:i})}var Fb=yu.memo(lY);var G=Mn.default.createElement,{useEffect:j0}=Mn.default,gl=Mn.default.useState,Pn=Mn.default.useRef,B$=[{id:"in-left",side:"left",position:wu.Left,style:{top:"50%"}},{id:"in-top-left",side:"top",slot:"left",slotIndex:-1,position:wu.Top,style:{left:"28%"}},{id:"in-top-mid",side:"top",slot:"mid",slotIndex:0,position:wu.Top,style:{left:"50%"}},{id:"in-top-right",side:"top",slot:"right",slotIndex:1,position:wu.Top,style:{left:"72%"}},{id:"in-bottom-left",side:"bottom",slot:"left",slotIndex:-1,position:wu.Bottom,style:{left:"28%"}},{id:"in-bottom-mid",side:"bottom",slot:"mid",slotIndex:0,position:wu.Bottom,style:{left:"50%"}},{id:"in-bottom-right",side:"bottom",slot:"right",slotIndex:1,position:wu.Bottom,style:{left:"72%"}}],Z$=[{id:"out-right",position:wu.Right,style:{top:"50%"}}],bW=["#4eb7a8","#d7a13a","#69aee8","#e0835f","#b7d86b","#d98bd2","#5fc6bf"],jy=236,Fy=88,vW=15000,rY=10,F9=96,A0=72,J9=64,kW=12;function y8(){return typeof document>"u"||document.visibilityState!=="hidden"}function IW(u,f){let l=Number.parseFloat(String(u||""));return Number.isFinite(l)?l/100:f}function nY(u,f,l){let r=String(u.side||"");if(r!=="top"&&r!=="bottom")return 0;let n=Number(u.slotIndex||0),i=r==="top"?"in-top-mid":"in-bottom-mid",y=f.get(u.id)||0,_=f.get(i)||0;if(n===0)return _===0?-26:28+y*74;let $=l===0?Math.abs(n)*2:Math.sign(l)===Math.sign(n)?-3:3;if(_>0&&y===0)return-14+$;return 8+y*74+$}function _8(u){let f=u.filter((i,y)=>{let _=u[y-1];return!_||Math.abs(_.x-i.x)>0.5||Math.abs(_.y-i.y)>0.5});if(f.length<2)return"";let l=`M ${f[0].x},${f[0].y}`,r=f[0];for(let i=1;i0.5||Math.abs(F.y-r.y)>0.5)l+=` L ${F.x},${F.y}`;l+=` Q ${_.x},${_.y} ${U.x},${U.y}`,r=U}let n=f[f.length-1];return`${l} L ${n.x},${n.y}`}function cL(u,f,l,r,n,i,y=""){let _=l>=u,$=Math.max(1,Math.abs(l-u)),A=Math.abs(r-f),c=Math.max(34,Math.min(118,$*0.26)),j=Math.min(280,Math.abs(i));if(_&&n===wu.Left&&j<4&&A<28&&$<420)return`M ${u},${f} C ${u+c},${f} ${l-c},${r} ${l},${r}`;if(_&&n===wu.Left&&(y==="direct-forward-left"||$<=260&&A<=210)){let J=Math.max(42,Math.min(140,$*0.48)),N=Math.max(-28,Math.min(28,i*0.18));return`M ${u},${f} C ${u+J},${f+N} ${l-J},${r} ${l},${r}`}if(_){let J=u+c;if(n===wu.Top||n===wu.Bottom){let W=n===wu.Top?-1:1,z=r+W*(54+j*0.42);return _8([{x:u,y:f},{x:J,y:f},{x:J+Math.min(120,$*0.18),y:z},{x:l,y:z},{x:l,y:r+W*34},{x:l,y:r}])}let N=l-c,q=(f+r)/2+i;return _8([{x:u,y:f},{x:J,y:f},{x:J+Math.min(110,$*0.16),y:q},{x:N-Math.min(90,$*0.12),y:q},{x:N,y:r},{x:l,y:r}])}let Q=n===wu.Bottom?1:n===wu.Top?-1:i>=0?1:-1,L=Math.max(u,l)+92+Math.min(180,j*0.52),w=Q<0?Math.min(f,r)-84-j*0.62:Math.max(f,r)+84+j*0.62;if(n===wu.Top||n===wu.Bottom)return _8([{x:u,y:f},{x:u+c,y:f},{x:L,y:w},{x:l,y:w},{x:l,y:r+Q*38},{x:l,y:r}]);return _8([{x:u,y:f},{x:u+c,y:f},{x:L,y:w},{x:l-c,y:w},{x:l-c,y:r},{x:l,y:r}])}function iY({data:u}){return G("div",{className:"pipeline-flow-node-body"},B$.map((f)=>G(m1,{key:f.id,id:f.id,type:"target",position:f.position,isConnectable:!1,className:`pipeline-flow-handle input ${f.side} slot-${f.slot||"mid"}`,style:f.style})),Z$.map((f)=>G(m1,{key:f.id,id:f.id,type:"source",position:f.position,isConnectable:!1,className:"pipeline-flow-handle output right",style:f.style})),u?.label)}function yY({id:u,sourceX:f,sourceY:l,targetX:r,targetY:n,targetPosition:i,markerEnd:y,markerStart:_,style:$,data:A}){let c=Number(A?.laneOffset||0),j=cL(f,l,r,n,i,c,String(A?.routeMode||""));return G(Ay,{id:u,path:j,markerEnd:y,markerStart:_,style:$,interactionWidth:28})}var _Y={pipelineCurve:yY},$Y={pipelineNode:iY};function c8(u){if(!u)return"--";let f=new Date(u);if(Number.isNaN(f.getTime()))return"--";return tf(f)}function Hr(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.round(f/1000);if(l<60)return`${l}s`;if(l<3600)return`${Math.floor(l/60)}m ${l%60}s`;return`${Math.floor(l/3600)}h ${Math.floor(l%3600/60)}m`}function U9(u){let f=Number(u);if(!Number.isFinite(f))return"--";return f.toLocaleString("zh-CN")}function gW(u){let f=Number(u);if(!Number.isFinite(f))return"--";return`${Math.round(Math.max(0,Math.min(1,f))*100)}%`}function Du(u){return typeof u==="object"&&u!==null&&!Array.isArray(u)}function Vu(u){return Array.isArray(u)?u:[]}function vu(u){if(!u)return null;let f=new Date(u);return Number.isNaN(f.getTime())?null:f.getTime()}function V$(u){return Number.isFinite(Number(u))?new Date(Number(u)).toISOString():""}function Y$(...u){for(let f of u){let l=vu(f);if(l!==null)return new Date(l).toISOString()}return""}function B9(...u){let f=u.map(vu).filter((l)=>l!==null);return f.length>0?new Date(Math.max(...f)).toISOString():""}function V9(u){return["succeeded","failed","skipped","cancelled","canceled","completed"].includes(String(u||"").toLowerCase())}function jL(u){let f=UL(u).toLowerCase();return["running","active","in-progress","in_progress"].includes(f)}function sW(u,f="status"){return u.reduce((l,r)=>{let n=String(r?.[f]||"unknown").toLowerCase();return l[n]=(l[n]||0)+1,l},{})}function FL(u){if(!u||typeof u!=="string")return null;try{let f=JSON.parse(u);return Du(f)?f:null}catch{return null}}function Q9(u){let f=u.map(FL).filter((i)=>Boolean(i)),l=f.flatMap((i)=>[i.timestamp,i.createdAt,i.updatedAt]).filter(Boolean),r=B9(...l),n=Array.from(new Set(f.map((i)=>String(i.event||i.action||i.type||"")).filter(Boolean))).slice(0,3);return{total:u.length,parsed:f.length,lastAt:r,eventKinds:n}}function j8(u){if(u===null||u===void 0)return"--";if(typeof u==="boolean")return u?"是":"否";if(typeof u==="number")return String(u);if(typeof u==="string")return u.length>80?`${u.slice(0,77)}...`:u;if(Array.isArray(u))return`${u.length} 项`;if(typeof u==="object")return`${Object.keys(u).length} 字段`;return String(u)}function JL(u,f=280){if(u===null||u===void 0)return"";let r=(typeof u==="string"?u:String(u)).replace(/\r\n/gu,` -`).trim();return r.length>f?`${r.slice(0,Math.max(0,f-1))}...`:r}function UL(u){if(typeof u==="string")return u;if(Du(u))return String(u.status||u.state||u.phase||"unknown");return"unknown"}function tY(u){return u.filter((f)=>f&&f.value!==void 0&&f.value!==null&&String(f.value)!=="")}function K9({items:u}){let f=tY(Vu(u));return G("div",{className:"pipeline-kv-grid"},f.map((l)=>G("span",{key:l.label},G("b",null,l.label),G("span",null,l.value))))}function D9({items:u}){let f=Vu(u).map((l)=>String(l||"")).filter(Boolean);if(f.length===0)return null;return G("div",{className:"pipeline-chip-row"},f.map((l,r)=>G("span",{key:`${r}-${l}`},l)))}function G9(u,f){let l=String(f?.procedureRunId||""),r=Vu(u?.procedureRuns);return r.find((n)=>String(Br(n))===l)||r.at(-1)||null}function AY(u,f){let l=String(f||"");if(!l)return null;return Vu(u?.procedureRuns).find((r)=>Br(r)===l)||null}function q9(u){return Vu(u?.attempts).length}function aW(u){return Vu(u?.attempts).reduce((f,l)=>f+W8(l).length,0)}function W8(u){return Vu(u?.opencodeMessages?.steps).filter(Du)}function QL(u){let f=String(u?.status||"").toLowerCase();if(["error","failed","failure"].includes(f))return"failed";if(["completed","succeeded","success"].includes(f))return"succeeded";if(["running","started","in_progress"].includes(f))return"running";return"unknown"}function cY(u,f){let l=T9(u.map((i)=>i?.agent)).slice(0,3),r=T9(u.map((i)=>i?.model)).slice(0,3),n=f.length<=2?f.map((i)=>`session ${i}`):[`sessions ${f.length}`,...f.slice(0,2).map((i)=>`session ${i}`)];return[...l.map((i)=>`agent ${i}`),...r.map((i)=>`model ${i}`),...n]}function O$(u,f=0){return String(u?.messageId||u?.index||"")||`step-${f}`}function jY({steps:u,sessionIds:f,sessionFacts:l,matchedStepKey:r}){let n=Vu(u),i=n.findIndex((w,J)=>O$(w,J)===r),y=i>=0?n[i]:null,_=n.flatMap((w)=>[vu(w?.createdAt),vu(w?.completedAt)]).filter((w)=>w!==null),$=_.length>0?Math.min(..._):null,A=_.length>0?Math.max(..._):null,c=$!==null&&A!==null?Math.max(0,A-$):null,j=n.reduce((w,J)=>w+Vu(J?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool").length,0),F=n.reduce((w,J)=>w+Vu(J?.parts).filter((N)=>["text","reasoning"].includes(String(N?.type||"").toLowerCase())).length,0),U=n.reduce((w,J)=>w+Vu(J?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool"&&QL(N)==="failed").length,0),Q=[`${n.length} steps`,`${f.length} sessions`,`${F} messages`,`${j} tools`,c!==null?`duration ${Hr(c)}`:"",U>0?`${U} failed tools`:""].filter(Boolean),L=y?[`Step ${y?.index??i+1}`,String(y?.role||"role --"),y?.model?`model ${y.model}`:"",y?.finish?`finish ${y.finish}`:"",y?.durationMs!==void 0&&y?.durationMs!==null?`duration ${Hr(y.durationMs)}`:""].filter(Boolean):[];return G("section",{className:"pipeline-trace-timeline","data-testid":"pipeline-step-timeline"},G("div",{className:"pipeline-trace-head"},G("div",null,G("b",null,"OpenCode Trace"),G("span",null,"Trace 使用 Code Queue 统一样式展示完整 agent loop;Pipeline 旧 step/message/tool 卡片样式已废弃。")),G("div",{className:"pipeline-trace-session-head","data-testid":"pipeline-step-timeline-session"},G("span",null,Q.join(" / ")||"Trace"),l.length>0?G(D9,{items:l}):null)),y?G("div",{className:"pipeline-trace-focus","data-testid":"pipeline-trace-matched-step"},G("span",{className:"codex-output-channel"},"Matched"),G("strong",null,`Gantt selection -> ${L.join(" / ")}`),G("time",null,`${c8(y?.createdAt)} -> ${c8(y?.completedAt)}`)):null,G(St,{port:mU,input:n,className:"codex-transcript pipeline-trace",testId:"pipeline-opencode-step-trace",emptyText:"暂无 OpenCode Trace 输出",keepRecentToolCalls:3}))}function z9(u){return Vu(u).flatMap((f)=>{if(Du(f))return[f];let l=FL(f);return l?[l]:[]})}function Ir(u){return String(u?.event||u?.action||u?.requestedAction||u?.type||"").toLowerCase()}function cy(u){return Y$(u?.timestamp,u?.createdAt,u?.updatedAt,u?.startedAt,u?.finishedAt)}function FY(u){return vu(cy(u))}function L8(u){return String(u?.attempt||u?.id||"")}function T9(u){let f=new Set,l=[];for(let r of u){let n=String(r||"");if(!n||f.has(n))continue;f.add(n),l.push(n)}return l}function oW(u){switch(String(u||"").toLowerCase()){case"monitor":return"monitor";case"webui":return"webui";case"cli":return"cli";case"system":return"runner";default:return String(u||"--")}}function P1(u){return String(u?.requestedAction||u?.action||"").toLowerCase()}function H$(u){switch(P1(u)){case"guide":return"引导";case"modify":return"修改";case"approve":return"审核通过";case"restart":return"重启";case"redo":return"重做";default:return String(u?.requestedAction||u?.action||"控制")}}function dW(u){switch(Ir(u)){case"initial-prompt-delivered":return"初始 prompt";case"append-prompt-delivered":return"追加 prompt";case"append-prompt-queued":return"追加 prompt 已排队";case"monitor-prompt-delivered":return"Monitor prompt";case"node-long-running-observation":return"长任务观察";case"node-finished":return"节点完成";case"oa-policy-downstream-evaluated":return"OA 下游策略";case"control-command-queued":return`${H$(u)} 已发起`;case"control-command-applied":return`${H$(u)} 已生效`;case"control-command-ignored":return`${H$(u)} 已忽略`;default:return String(u?.event||u?.action||u?.requestedAction||"event")}}function eW(u){return JL(u?.promptPreview||u?.reasonPreview||u?.prompt||u?.reason||"",240)}function JY(u){let f=String(u?.prompt||""),l=String(u?.reason||u?.restartReason||""),r=f?"":String(u?.promptPreview||""),n=l?"":String(u?.reasonPreview||"");return[f||r?{label:f?"prompt":"prompt preview",value:f||r}:null,l||n?{label:l?"reason":"reason preview",value:l||n}:null,Vu(u?.resetNodeIds).length>0?{label:"reset nodes",value:Vu(u.resetNodeIds).join(", ")}:null,Vu(u?.runningResetNodeIds).length>0?{label:"interrupted running nodes",value:Vu(u.runningResetNodeIds).join(", ")}:null,Vu(u?.interruptedProcedureRunIds).length>0?{label:"interrupted procedures",value:Vu(u.interruptedProcedureRunIds).join(", ")}:null,u?.interruptedProcedureRunId?{label:"interrupted procedure",value:String(u.interruptedProcedureRunId)}:null].filter(Boolean)}function N9(u){let f=W8(u),l=f.map(($)=>vu($?.createdAt)).filter(($)=>$!==null),r=f.map(($)=>vu($?.completedAt)??vu($?.createdAt)).filter(($)=>$!==null),n=z9(u?.controlEventRecords).map(($)=>FY($)).filter(($)=>$!==null),i=Vu(u?.assistantOutputs).map(($)=>vu($?.updatedAt)).filter(($)=>$!==null),y=l[0]??n[0]??i[0]??null,_=r.at(-1)??n.at(-1)??i.at(-1)??y;return{startMs:y,endMs:_}}function UY(u,f,l,r,n=""){let i=Vu(u?.procedureRuns).filter((_)=>w8(_,f)===l);if(i.length===0)return null;if(n){let _=i.find(($)=>Br($)===n);if(_)return _}if(r===null)return i.at(-1)||null;let y=i.find((_)=>{let $=vu($8(_,u)),A=vu(t8(_,u))??$;return $!==null&&A!==null&&r>=$-1000&&r<=A+1000});if(y)return y;return i.slice().sort((_,$)=>{let A=vu($8(_,u))??r,c=vu(t8(_,u))??A,j=vu($8($,u))??r,F=vu(t8($,u))??j,U=Math.min(Math.abs(A-r),Math.abs(c-r)),Q=Math.min(Math.abs(j-r),Math.abs(F-r));return U-Q})[0]||null}function qL(u,f){let l=Vu(u?.attempts).filter(Du);if(l.length===0)return null;let r=String(f?.attempt||"");if(r){let y=l.find((_)=>L8(_)===r);if(y)return y}let n=Number.isFinite(Number(f?.ms))?Number(f.ms):null;if(n===null)return l.at(-1)||null;let i=l.find((y)=>{let _=N9(y);return Number.isFinite(_.startMs)&&Number.isFinite(_.endMs)&&n>=Number(_.startMs)-1000&&n<=Number(_.endMs)+1000});if(i)return i;return l.slice().sort((y,_)=>{let $=N9(y),A=N9(_),c=Math.min(Math.abs(Number($.startMs??n)-n),Math.abs(Number($.endMs??n)-n)),j=Math.min(Math.abs(Number(A.startMs??n)-n),Math.abs(Number(A.endMs??n)-n));return c-j})[0]||l.at(-1)||null}function NL(u,f){let l=W8(u);if(l.length===0)return{step:null,stepIndex:-1,stepKey:""};if(f===null){let i=l[0];return{step:i,stepIndex:0,stepKey:O$(i,0)}}for(let i=0;i=_-1000&&f<=$+1000)return{step:y,stepIndex:i,stepKey:O$(y,i)}}let r=l.findIndex((i)=>{let y=vu(i?.createdAt)??vu(i?.completedAt);return y!==null&&y>=f});if(r>=0){let i=l[r];return{step:i,stepIndex:r,stepKey:O$(i,r)}}let n=Math.max(0,l.length-1);return{step:l[n],stepIndex:n,stepKey:O$(l[n],n)}}function QY(u,f){let l=String(f?.runId||u?.runId||"");if(String(f?.mode||"")==="interval"){let A=f?.interval||{},c=G9(u,A)||A.raw||{};return{mode:"interval",runId:l,interval:A,marker:null,nodeId:String(A?.nodeId||w8(c,l)||""),procedure:c,attempt:null,matchedStep:null,matchedStepIndex:-1,matchedStepKey:""}}let r=Du(f?.marker)?f.marker:{},n=Number.isFinite(Number(r?.ms))?Number(r.ms):null,i=String(r?.nodeId||""),y=i?UY(u,l,i,n,String(r?.procedureRunId||"")):null,_=y?qL(y,r):null,$=_?NL(_,n):{step:null,stepIndex:-1,stepKey:""};return{mode:"event",runId:l,interval:null,marker:r,nodeId:i,procedure:y,attempt:_,matchedStep:$.step,matchedStepIndex:$.stepIndex,matchedStepKey:$.stepKey}}function qY({procedure:u,matchedStepKey:f="",matchedAttemptId:l=""}){let r=Vu(u?.attempts);if(r.length===0)return G(Ur,{title:"暂无 attempt 详情",text:"当前 procedure 还没有可展示的 attempt / OpenCode Trace;若刚点击甘特线,请等待 node 详情抓取完成。"});return r.map((n,i)=>{let y=n?.opencodeMessages||{},_=W8(n),$=Vu(y.sessionIds).map((F)=>String(F)).filter(Boolean),A=cY(_,$),c=L8(n)||`attempt-${i+1}`,j=_.reduce((F,U)=>F+Vu(U?.parts).filter((Q)=>String(Q?.type||"").toLowerCase()==="tool"&&QL(Q)==="failed").length,0);return G("article",{key:c,className:`pipeline-attempt-card ${l===c?"matched":""}`},G("div",{className:"pipeline-attempt-head"},G("div",null,G("strong",null,c),G("span",null,y.source||"opencode")),G("div",{className:"pipeline-attempt-badges"},G("span",null,`${_.length} steps`),G("span",null,`${y.toolCallCount??"--"} tools`),j>0?G("span",{className:"danger"},`${j} failed`):null)),G(K9,{items:[{label:"messages",value:y.messageCount??"--"},{label:"steps",value:y.stepCount??"--"},{label:"tools",value:y.toolCallCount??"--"},{label:"updated",value:Nu(y.updatedAt)},{label:"sessions",value:$.join(", ")||"--"}]}),_.length===0?G("p",{className:"muted paragraph"},"当前 attempt 尚未返回 OpenCode Trace;请确认 D601 pipeline-control 已重建并重新抓取。"):G(jY,{steps:_,sessionIds:$,sessionFacts:A,matchedStepKey:f}))})}function W9(u,f){return`${u}::${f}`}function F8(u,f,l){if(!Du(u))return null;return String(u.runId||"")===f&&String(u.nodeId||"")===l?u:null}function NY(u,f){let l=Du(u)?u:{};if(!Du(f))return l;let r=Vu(f.attempts),n=Vu(l.attempts);return{...l,...f,attempts:r.length>0?r:n}}function WY(u,f,l,r){if(!F8(f,l,r))return u;let n=Vu(f.procedureRuns),i=Du(u)?u:{};return{...i,...f,controlEvents:Vu(f.controlEvents).length>0?f.controlEvents:i.controlEvents,procedureRuns:n.length>0?n:i.procedureRuns}}function LY({selection:u,runDetails:f,nodeDetails:l,nodeDetailsState:r,onRaw:n,onCollapse:i}){if(!u?.mode)return G("aside",{className:"pipeline-gantt-detail-panel empty","data-testid":"pipeline-gantt-detail-panel"},G("div",{className:"pipeline-gantt-detail-head"},G("div",null,G("span",{className:"panel-eyebrow"},"Gantt Detail"),G(nf,{title:"未选择元素",level:3})),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起")),G(Ur,{title:"选择一条执行线或一个控制点",text:"点击甘特图中的 node 执行线、prompt 点或控制点,在这里查看结构化过程和 OpenCode step。"}));let y=String(u?.runId||""),_=String(u?.interval?.nodeId||u?.marker?.nodeId||""),$=f?.runId===y?f.details:null,A=F8(l,y,_),c=String(r?.runId||"")===y&&String(r?.nodeId||"")===_,j=WY($,A,y,_),F=(String(f?.runId||"")!==y||Boolean(f?.loading))&&!j,U=String(f?.runId||"")===y?String(f?.error||""):"",Q=c?String(r?.error||""):"",L=j?QY(j,u):null,w=L?.interval||u?.interval||null,J=L?.marker||u?.marker||null,N=String(w?.procedureRunId||J?.procedureRunId||""),q=A?AY(A,N)||G9(A,w||{procedureRunId:N}):null,W=L?.procedure||(j?G9(j,w||{procedureRunId:N}):null)||w?.raw||{};if(q&&(q9(W)===0||aW(q)>=aW(W)))W=NY(W,q);let z=L?.attempt||null,Z=String(L?.matchedStepKey||"");if(!z&&J&&q9(W)>0)z=qL(W,J),Z=String(NL(z,Number.isFinite(Number(J?.ms))?Number(J.ms):null).stepKey||"");let H=L8(z),E=q9(W)>0,D=c&&Boolean(r?.loading)&&!E,h=Boolean(F||D),V=[E?"":U,Q].filter(Boolean).join(" / "),Y=c&&r?.fetchedAt?r.fetchedAt:f?.fetchedAt,p=UL(W?.status||w?.status||J?.status||J?.event),O=u?.mode==="event"?J?.label||dW(J?.raw||J)||"event":L?.nodeId||w?.nodeId||"node",m=J?JY(J?.raw||J):[],X=J?[Ir(J?.raw||J)?`event ${Ir(J?.raw||J)}`:"",J?.promptEvent?`prompt ${J.promptEvent}`:"",J?.action?`action ${J.action}`:"",J?.sourceKind?`source ${oW(J.sourceKind)}`:"",J?.sourceNodeId?`from ${J.sourceNodeId}`:"",J?.targetNodeId?`to ${J.targetNodeId}`:"",J?.snapReason?`draw ${J.snapReason}`:""].filter(Boolean):[];return G("aside",{className:"pipeline-gantt-detail-panel","data-testid":"pipeline-gantt-detail-panel"},G("div",{className:"pipeline-gantt-detail-head"},G("div",null,G("span",{className:"panel-eyebrow"},u?.mode==="event"?"Gantt Event Detail":"Gantt Line Detail"),G(nf,{title:O,level:3,loading:h})),G("div",{className:"pipeline-gantt-detail-head-actions"},G(Cn,{status:p},p),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起"))),J?G("article",{className:"pipeline-event-card"},G("div",{className:"pipeline-event-card-head"},G("strong",null,J?.label||dW(J?.raw||J)),G(D9,{items:X})),G(K9,{items:[{label:"event time",value:Nu(J?.timestampIso||J?.timestamp||"--")},J?.snapped?{label:"drawn time",value:Nu(J?.renderedTimestampIso||J?.ms)}:null,{label:"node",value:J?.nodeId||"--"},{label:"procedure",value:J?.procedureRunId||Br(W)||"--"},{label:"attempt",value:J?.attempt||H||"--"},{label:"source kind",value:J?.sourceKind?oW(J.sourceKind):"--"},{label:"source node",value:J?.sourceNodeId||"--"},{label:"target node",value:J?.targetNodeId||"--"},{label:"command",value:J?.commandId||J?.eventId||"--"},J?.snapReason?{label:"placement",value:J.snapReason}:null]}),m.length>0?G("div",{className:"pipeline-event-blocks"},m.map((v,T)=>G("section",{key:`${v.label}-${T}`,className:"pipeline-event-text-block"},G("b",null,v.label),G("p",null,v.value)))):null,eW(J?.raw||J)?G("p",{className:"pipeline-text-preview"},eW(J?.raw||J)):null):null,G(K9,{items:[{label:"epoch",value:y||w?.runId||"--"},{label:"node",value:L?.nodeId||w?.nodeId||J?.nodeId||"--"},{label:"procedure",value:w?.procedureRunId||J?.procedureRunId||Br(W)||"--"},{label:"started",value:Nu(w?.startedAt||W?.startedAt)},{label:"finished",value:Nu(w?.finishedAt||W?.finishedAt)},{label:"duration",value:Hr(w?.durationMs||W?.durationMs)},{label:"fetched",value:Y?tf(Y):"--"},L?.matchedStep?{label:"matched step",value:`Step ${L.matchedStep.index??L.matchedStepIndex+1}`}:null]}),G(yf,{error:V}),G("div",{className:"pipeline-gantt-detail-actions"},G(gr,{title:`Procedure ${w?.procedureRunId||J?.procedureRunId||L?.nodeId||"node"}`,data:W,onOpen:n,testId:"raw-pipeline-gantt-procedure"}),J?G(gr,{title:`Pipeline event ${J?.id||J?.commandId||J?.eventId||L?.nodeId||"event"}`,data:J?.raw||J,onOpen:n,testId:"raw-pipeline-gantt-event"}):null,j?G(gr,{title:`Pipeline run ${y||"--"}`,data:j,onOpen:n,testId:"raw-pipeline-gantt-node-details"}):null),!h&&!Br(W)&&!J?G(Ur,{title:"暂无过程详情",text:"当前选择还没有可匹配的 procedure 运行记录。"}):null,!h&&Br(W)?G(qY,{procedure:W,matchedStepKey:Z,matchedAttemptId:H}):null)}function wY({value:u}){let l=String(u||"--").split(/([_-])/u);return G(Mn.default.Fragment,null,l.map((r,n)=>r==="-"||r==="_"?G(Mn.default.Fragment,{key:n},r,G("wbr",null)):G(Mn.default.Fragment,{key:n},r)))}async function pn(u,f={}){return Eu(u,{invalidJsonPrefix:"Pipeline 返回了无效 JSON",...f})}function Cn({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return G("span",{className:`status-badge ${l}`},f||u||"unknown")}function Yl({label:u,value:f,hint:l,tone:r}){return G("article",{className:`metric-card ${r||""}`},G("div",{className:"metric-label"},u),G("div",{className:"metric-value"},f),G("div",{className:"metric-hint"},l))}function c0({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return G("section",{className:`panel ${n||""}`},G("div",{className:"panel-head"},G("div",null,f?G("p",{className:"panel-eyebrow"},f):null,G(nf,{title:u,loading:i})),l?G("div",{className:"panel-actions"},l):null),G("div",{className:"panel-body"},r))}function gr({title:u,data:f,onOpen:l,testId:r}){return G("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function Or({title:u,subtitle:f,facts:l,data:r,onRaw:n,testId:i}){let y=Vu(l).map((_)=>String(_||"")).filter(Boolean);return G("article",{className:"pipeline-evidence-row"},G("div",{className:"pipeline-evidence-main"},G("strong",null,u),f?G("span",null,f):null),G("div",{className:"pipeline-evidence-facts"},y.map((_,$)=>G("span",{key:`${$}-${_.slice(0,16)}`},_))),r!==void 0?G(gr,{title:u,data:r,onOpen:n,testId:i}):null)}function Ur({title:u,text:f}){return G("div",{className:"empty-state"},G("strong",null,u),G("span",null,f))}function KY(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function GY(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function zY(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function TY(u){return{components:Array.isArray(u?.registry?.components)?u.registry.components:[],pipelines:Array.isArray(u?.pipelines)?u.pipelines:[],runs:Array.isArray(u?.runs)?u.runs:[]}}function uL(u,f,l){let r=u?._unidesk?.arrayLimits?.[f],n=Number(r?.originalLength);return Number.isFinite(n)?n:l}function WL(u){if(!u||typeof u!=="object"||Array.isArray(u))return"--";return`${u.componentClass||"--"}/${u.id||"--"}`}function J8(u){if(!u||typeof u!=="object"||Array.isArray(u))return"";let f=String(u.componentClass||"").trim(),l=String(u.id||"").trim();return f&&l?`${f}/${l}`:""}function X9(u){return u?.config&&typeof u.config==="object"&&!Array.isArray(u.config)?u.config:{}}function LL(u){let f=X9(u),l=Array.isArray(f.nodes)?f.nodes:Array.isArray(u?.nodes)?u.nodes:[],r=new Map;for(let y of l){let _=String(y?.id||y?.nodeId||"");if(_)r.set(_,{...y,id:_})}let n=Y9(u),i=(y)=>{if(y&&!r.has(y))r.set(y,{id:y})};for(let y of S9(u))D$(y).forEach(i);for(let y of n)i(String(y?.from||y?.source||"")),i(String(y?.to||y?.target||""));return Array.from(r.values())}function Y9(u){let f=X9(u);return Array.isArray(f.edges)?f.edges:Array.isArray(u?.edges)?u.edges:[]}function S9(u){let f=X9(u);return Array.isArray(f.topologicalBatches)?f.topologicalBatches:Array.isArray(u?.topologicalBatches)?u.topologicalBatches:[]}function EY(u){let f=new Map;for(let l of u){let r=J8(l);if(r)f.set(r,l);let n=Array.isArray(l?.refs)?l.refs:[];for(let i of n){let y=J8(i);if(y)f.set(y,l)}}return f}function fL(u,f){let l=f.get(J8(u?.componentRef));if(l)return l;let r=J8({componentClass:u?.kind,id:u?.id});return r?f.get(r)||null:null}function lL(u,f){let l=wL(u,f);return String(l?.status||"pending")}function wL(u,f){return(Array.isArray(u?.nodes)?u.nodes:[]).find((r)=>r?.nodeId===f||r?.id===f)||null}function ZY(u){return u.reduce((f,l)=>{let r=String(l?.status||"unknown").toLowerCase();return f[r]=(f[r]||0)+1,f},{})}function OY(u){if(Array.isArray(u?.scorers))return u.scorers.filter(Du);if(Array.isArray(u?.summary?.scorers))return u.summary.scorers.filter(Du);if(Array.isArray(u?.artifact?.summary?.scorers))return u.artifact.summary.scorers.filter(Du);return[]}function HY(u){if(Du(u?.run))return u.run;if(Du(u?.runSummary))return u.runSummary;return null}function BY(u,f){if(!Du(u)&&!Du(f))return null;if(!Du(u))return f;if(!Du(f))return u;return{...u,...f,request:Du(u.request)||Du(f.request)?{...Du(u.request)?u.request:{},...Du(f.request)?f.request:{}}:f.request??u.request,artifact:Du(u.artifact)||Du(f.artifact)?{...Du(u.artifact)?u.artifact:{},...Du(f.artifact)?f.artifact:{}}:f.artifact??u.artifact,summary:Du(u.summary)||Du(f.summary)?{...Du(u.summary)?u.summary:{},...Du(f.summary)?f.summary:{}}:f.summary??u.summary}}function U8(u){let f=OY(u),l=f.find((c)=>Du(c?.score))||f[0]||null,r=Du(l?.score)?l.score:{},n=Number(r.passed),i=Number(r.total),y=Number(r.ratio),_=Number.isFinite(y)?y:Number.isFinite(n)&&Number.isFinite(i)&&i>0?n/i:null,$=_===null?null:Math.round(Math.max(0,Math.min(100,_<=1?_*100:_))),A=String(r.text||(Number.isFinite(n)&&Number.isFinite(i)?`${n}/${i}`:""));return{scorer:l,scorers:f,score:r,passed:Number.isFinite(n)?n:null,total:Number.isFinite(i)?i:null,percent:$,text:A}}function E9(u){let f=U8(u);return f.text||(f.scorers.length>0?String(f.scorer?.status||"pending"):"--")}function p9(u){let f=U8(u);if(f.total>0&&f.passed===f.total)return"succeeded";if(f.total>0&&f.passed>0)return"running";if(f.scorers.length>0)return"failed";return"pending"}function VY(u){return Array.isArray(u?.items)?u.items.filter(Du):[]}function DY({run:u}){let f=E9(u);return G("span",{className:`pipeline-score-badge ${p9(u)}`},`score ${f}`)}function XY({run:u,onRaw:f}){let r=U8(u).scorers;if(!u)return G(Ur,{title:"暂无评分",text:"选择一个 epoch 后会显示 scorer 结果。"});if(r.length===0)return G("div",{className:"pipeline-score-empty"},G("strong",null,"评分器等待中"),G("span",null,"DAG 完成后,Pipeline control backend 会把 scorer summary 追加到 run artifact,并通过 UniDesk 显示。"));return G("div",{className:"pipeline-score-board","data-testid":"pipeline-score-board"},r.map((n,i)=>{let y=U8({scorers:[n]}),_=VY(n),$=y.percent??0;return G("article",{key:`${n.scorerId||n.component||i}`,className:`pipeline-score-card ${p9({scorers:[n]})}`},G("div",{className:"pipeline-score-head"},G("div",null,G("span",null,n.scorerId||n.component||"scorer"),G("strong",null,y.text||n.status||"--")),G(Cn,{status:n.status||"unknown"},n.status||"unknown")),G("div",{className:"pipeline-score-meter","aria-label":`score ${$}%`},G("span",{style:{width:`${$}%`}})),G("div",{className:"pipeline-score-facts"},G("span",null,`${$}%`),G("span",null,n.component||"--"),G("span",null,n.applicationCheckoutRef||"--")),_.length>0?G("div",{className:"pipeline-score-items"},_.map((A)=>G("span",{key:`${A.id||A.filter}`,className:`pipeline-score-item ${String(A.status||"").toLowerCase()}`,title:`${A.filter||"--"} / ran=${A.ran??"?"}`},G("b",null,A.id||"--"),G("small",null,A.status||"--")))):G("p",{className:"muted paragraph"},"当前 scorer 尚未返回 item 级结果。"),n.error?G("p",{className:"pipeline-score-error"},JL(n.error,360)):null,G("div",{className:"panel-actions inline-actions"},G(gr,{title:`Scorer ${n.scorerId||i}`,data:n,onOpen:f,testId:"raw-pipeline-score"})))}))}function YY(u){let f=u.reduce((l,r)=>{let n=String(r?.componentClass||"unknown");return l[n]=(l[n]||0)+1,l},{});return Object.entries(f).map(([l,r])=>({name:l,count:Number(r)})).sort((l,r)=>r.count-l.count||l.name.localeCompare(r.name))}function D$(u){if(Array.isArray(u))return u.map((f)=>typeof f==="string"?f:String(f?.id||f?.nodeId||"")).filter(Boolean);if(Array.isArray(u?.nodes))return D$(u.nodes);if(Array.isArray(u?.nodeIds))return D$(u.nodeIds);return[]}function SY(u){return Du(u?.instanceInputs?.monitor)?u.instanceInputs.monitor:{}}function KL(u,f){if(String(u?.kind||"").toLowerCase()!=="procedure")return!1;let l=SY(u);if(u?.instanceInputs?.monitorMode===!0||l.enabled===!0)return!0;let r=WL(u?.componentRef);return String(f?.id||f?.config?.id||r||"").toLowerCase().includes("monitor")}function pY(u){return u.filter((f)=>KL(f)).map((f)=>String(f?.id||"")).filter(Boolean)}function mY(u,f){if(f.length===0)return u;let l=new Set(f),r=f.filter((n)=>u.includes(n));if(r.length===0)return u;return[...r,...u.filter((n)=>!l.has(n))]}function PY(u,f){if(f.length===0)return u;let l=new Set(f),r=f.filter((i)=>u.some((y)=>y.includes(i)));if(r.length===0)return u;let n=u.map((i)=>i.filter((y)=>!l.has(y))).filter((i)=>i.length>0);return[r,...n]}function MY(u,f,l){let n=S9(u).map(D$).filter((F)=>F.length>0);if(n.length>0)return n;let i=f.map((F)=>String(F?.id||"")).filter(Boolean),y=new Set(i),_=new Map(i.map((F)=>[F,0])),$=new Map(i.map((F)=>[F,[]]));for(let F of l){let U=String(F?.from||F?.source||""),Q=String(F?.to||F?.target||"");if(!y.has(U)||!y.has(Q))continue;$.get(U)?.push(Q),_.set(Q,(_.get(Q)||0)+1)}let A=new Map,c=i.filter((F)=>(_.get(F)||0)===0);for(let F of c)A.set(F,0);while(c.length>0){let F=c.shift(),U=(A.get(F)||0)+1;for(let Q of $.get(F)||[])if(_.set(Q,Math.max(0,(_.get(Q)||0)-1)),A.set(Q,Math.max(A.get(Q)||0,U)),(_.get(Q)||0)===0)c.push(Q)}i.forEach((F)=>{if(!A.has(F))A.set(F,0)});let j=Math.max(0,...Array.from(A.values()));return Array.from({length:j+1},(F,U)=>i.filter((Q)=>A.get(Q)===U)).filter((F)=>F.length>0)}function CY(u,f,l){let n=S9(u).map(D$).filter((_)=>_.length>0),i=n.length>0?n.flatMap((_)=>_):(()=>{let _=f.map((L)=>String(L?.id||"")).filter(Boolean),$=new Set(_),A=l.filter((L)=>String(L?.edgeType||"").toLowerCase()!=="rework"),c=new Map(_.map((L)=>[L,0])),j=new Map(_.map((L)=>[L,[]]));for(let L of A){let w=String(L?.from||L?.source||""),J=String(L?.to||L?.target||"");if(!$.has(w)||!$.has(J))continue;j.get(w)?.push(J),c.set(J,(c.get(J)||0)+1)}let F=new Map,U=_.filter((L)=>(c.get(L)||0)===0);for(let L of U)F.set(L,0);while(U.length>0){let L=U.shift(),w=(F.get(L)||0)+1;for(let J of j.get(L)||[])if(c.set(J,Math.max(0,(c.get(J)||0)-1)),F.set(J,Math.max(F.get(J)||0,w)),(c.get(J)||0)===0)U.push(J)}_.forEach((L)=>{if(!F.has(L))F.set(L,0)});let Q=Math.max(0,...Array.from(F.values()));return Array.from({length:Q+1},(L,w)=>_.filter((J)=>F.get(J)===w)).flatMap((L)=>L)})(),y=new Set(i);for(let _ of f){let $=String(_?.id||"");if(!$||y.has($))continue;i.push($),y.add($)}return mY(i,pY(f))}function T$(u){return`${u.source}->${u.target}-${u.index}`}function rL(u,f,l){let r=LL(u),n=Y9(u),i=EY(l),y=new Map(r.map((p)=>[String(p?.id||""),p])),_=r.filter((p)=>KL(p,fL(p,i))).map((p)=>String(p?.id||"")).filter(Boolean),$=PY(MY(u,r,n),_),A=[],c=new Map,j=330,F=122;$.forEach((p,O)=>{let m=p.length*122;p.forEach((X,v)=>{let T=y.get(X)||{id:X},S=fL(T,i),k=lL(f,X).toLowerCase(),I=String(T.kind||S?.componentClass||"node").toLowerCase(),b=WL(T.componentRef||S),o=String(S?.config?.version||S?.version||""),s=String(S?.config?.description||S?.description||""),x=v*122-Math.floor(m/2);c.set(X,{column:O,row:v,y:x}),A.push({id:X,type:"pipelineNode",position:{x:O*330,y:x},data:{exportLabel:{id:X,kind:I,componentRef:b,componentVersion:o,componentDescription:s,status:k},label:G("div",{className:"flow-node-label"},G("strong",null,X),G("span",null,I),G("code",{title:s||b},o?`${b}@${o}`:b),G(Cn,{status:k},k))},className:`pipeline-flow-node ${I} ${k}`})})});let U=n.flatMap((p,O)=>{let m=String(p?.from||p?.source||""),X=String(p?.to||p?.target||"");if(!y.has(m)||!y.has(X))return[];return[{source:m,target:X,index:O,condition:p?.condition,edgeType:p?.edgeType}]}),Q=U.reduce((p,O)=>p.set(O.source,(p.get(O.source)||0)+1),new Map),L=U.reduce((p,O)=>p.set(O.target,(p.get(O.target)||0)+1),new Map),w=U.reduce((p,O)=>{let m=`${O.source}->${O.target}`;return p.set(m,(p.get(m)||0)+1)},new Map),J=new Map,N=new Map,q=new Map,W=new Map,z=new Map,Z=new Map,H=U.reduce((p,O)=>{let m=c.get(O.source),X=c.get(O.target),v=(X?.column||0)-(m?.column||0);if(v<=0||String(O.edgeType||"").toLowerCase()==="rework"||v!==1)return p;let S=`${O.source}->column:${X?.column??""}`,k=p.get(S)||[];return k.push(O),p.set(S,k),p},new Map);for(let p of H.values()){if(p.length<2)continue;p.slice().sort((O,m)=>{let X=c.get(O.target),v=c.get(m.target);return(X?.y||0)-(v?.y||0)||O.index-m.index}).forEach((O,m,X)=>{Z.set(T$(O),{slot:m-(X.length-1)/2,count:X.length})})}[...U].sort((p,O)=>{let m=c.get(p.source),X=c.get(p.target),v=c.get(O.source),T=c.get(O.target),S=Math.abs((X?.column||0)-(m?.column||0))*330+Math.abs((X?.y||0)-(m?.y||0)),k=Math.abs((T?.column||0)-(v?.column||0))*330+Math.abs((T?.y||0)-(v?.y||0));return S-k||p.index-O.index}).forEach((p)=>{let O=c.get(p.source)||{column:0,row:0,y:0},m=c.get(p.target)||{column:0,row:0,y:0},X=m.column-O.column,v=Math.max(0,X),T=X<=0||String(p.edgeType||"").toLowerCase()==="rework",S=O.y-m.y,k=L.get(p.target)||1,I=Z.has(T$(p)),b=!T&&v<=1&&(I||k===1),o=z.get(p.target)||new Map;z.set(p.target,o);let s=B$.slice().sort((x,fu)=>{let $u=(qu)=>{let P=String(qu.side),e=0;if(T){if(P==="left")e+=86;if(P==="top")e+=m.y<=0?-22:12;if(P==="bottom")e+=m.y>=0?-22:12;if(Math.abs(m.y)<12&&P!=="left")e+=p.index%2===0?P==="top"?-6:6:P==="bottom"?-6:6;return e}if(b){if(P==="left")e-=I?72:44;if(P!=="left")e+=I?72:44;return e+Math.abs(S)*0.02}if(P==="left")e+=v<=1?0:24;if(P==="top")e+=S<-36?-18:42;if(P==="bottom")e+=S>36?-18:42;if(v<=1&&Math.abs(S)<=82&&P!=="left")e+=38;if(v>1&&P!=="left")e-=10;return e},tu=O.y-m.y,ju=tu!==0?tu:p.index%2===0?-1:1,Gu=(qu)=>{let P=o.get(qu.id)||0;return $u(qu)+P*64+nY(qu,o,ju)};return Gu(x)-Gu(fu)||String(x.id).localeCompare(String(fu.id))})[0];o.set(s.id,(o.get(s.id)||0)+1),W.set(T$(p),s)});let D=U.map((p)=>{let O=lL(f,p.target).toLowerCase(),m=`${p.source}->${p.target}`,X=J.get(p.source)||0,v=N.get(p.target)||0,T=q.get(m)||0;J.set(p.source,X+1),N.set(p.target,v+1),q.set(m,T+1);let S=X-((Q.get(p.source)||1)-1)/2,k=v-((L.get(p.target)||1)-1)/2,I=T-((w.get(m)||1)-1)/2,b=c.get(p.source),o=c.get(p.target),s=(o?.column||0)-(b?.column||0),x=Math.max(1,Math.abs(s)),fu=s<=0||String(p.edgeType||"").toLowerCase()==="rework",$u=Math.abs((o?.y||0)-(b?.y||0)),tu=Z.get(T$(p)),ju=!fu&&s===1&&(L.get(p.target)||0)>1,Gu=tu?tu.slot:I*2+S+k*0.45,qu=Gu===0?p.index%2===0?-1:1:Math.sign(Gu),P=W.get(T$(p))||B$[1],e=P.side==="top"?-1:P.side==="bottom"?1:qu,uu=fu||x>1||$u>96||Math.abs(Gu)>0.2||P.side!=="left",Wu=fu?118+x*18:22+x*16,g=P.side==="left"?0:28,Qu=uu?Math.max(-280,Math.min(280,e*Math.min(180,Wu+g+$u*0.22)+Gu*28)):0,Tu=Math.max(0,Math.min(Z$.length-1,Math.round(S+(Z$.length-1)/2))),Zu=Z$[Tu]||Z$[1],Xu=O==="succeeded"?"var(--accent-2)":O==="running"?"var(--accent)":O==="failed"?"var(--danger)":"rgba(129, 147, 159, 0.78)",uf=b?.column||0,_f=o?.column||0,Jf=Qu===0?0:Math.sign(Qu),Pf=fu?`feedback:${uf}->${_f}:${Jf}`:tu?`fanout:${uf}->${_f}:${p.source}`:ju?`fanin:${uf}->${_f}:${p.target}`:P.side!=="left"||x>1?`corridor:${uf}->${_f}:${P.side}:${Jf}:${Math.round(Math.abs(Qu)/56)}`:"";return{id:`${p.source}->${p.target}-${p.index}`,source:p.source,target:p.target,sourceHandle:Zu.id,targetHandle:P.id,type:"pipelineCurve",zIndex:12,animated:O==="running",data:{baseEdgeColor:Xu,laneOffset:Qu,routeMode:tu&&P.side==="left"?"direct-forward-left":"",targetSide:P.side,isFeedback:fu,overlapGroup:Pf},targetStatus:O}}),h=D.reduce((p,O)=>{let m=String(O.data?.overlapGroup||"");return m?p.set(m,(p.get(m)||0)+1):p},new Map),V=new Map,Y=D.map((p)=>{let O=String(p.targetStatus||"pending"),m={...p};delete m.targetStatus;let X=String(p.data?.overlapGroup||""),v=X?h.get(X)||0:0,T=v>1?V.get(X)||0:-1;if(v>1)V.set(X,T+1);let S=T>=0?bW[T%bW.length]:String(p.data.baseEdgeColor),k={stroke:S};if(p.data.isFeedback)k.strokeDasharray="9 7";return{...m,data:{...p.data,edgeColor:S,overlapSlot:T,overlapCount:v},style:k,markerEnd:{type:Dn.ArrowClosed,color:S},className:`pipeline-flow-edge ${O} ${p.data.isFeedback?"feedback":""} ${T>=0?"overlap-colored":""}`}});return{nodes:A,edges:Y}}function sl(u){return String(u??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function nL(u){let f=String(u||"");if(f.includes("--accent-2"))return"#4eb7a8";if(f.includes("--accent"))return"#d7a13a";if(f.includes("--danger"))return"#cf6a54";return f.startsWith("#")?f:"#81939f"}function Q8(u){return`arrow-${u.replace(/[^a-zA-Z0-9_-]+/g,"")}`}function GL(u,f="pipeline"){return String(u||f).replace(/[^a-zA-Z0-9_-]+/g,"-").replace(/^-|-$/g,"")||f}function iL(u,f){let l=u.position.x,r=u.position.y,n=B$.find((i)=>i.id===f);if(n?.side==="top")return{x:l+jy*IW(n.style?.left,0.5),y:r,position:wu.Top};if(n?.side==="bottom")return{x:l+jy*IW(n.style?.left,0.5),y:r+Fy,position:wu.Bottom};return{x:l,y:r+Fy/2,position:wu.Left}}function RY(u){return{x:u.position.x+jy,y:u.position.y+Fy/2}}function xY(u,f){let l=Math.min(...u.nodes.map((L)=>L.position.x),0)-220,r=Math.min(...u.nodes.map((L)=>L.position.y),0)-220,n=Math.max(...u.nodes.map((L)=>L.position.x+jy),1)+220,i=Math.max(...u.nodes.map((L)=>L.position.y+Fy),1)+220,y=Math.ceil(n-l),_=Math.ceil(i-r),$=new Map(u.nodes.map((L)=>[L.id,L])),A=u.edges.map((L)=>nL(L.data?.edgeColor||L.style?.stroke)),j=Array.from(new Set(["#4eb7a8","#d7a13a","#cf6a54","#81939f",...A])).map((L)=>``).join(""),F=u.edges.flatMap((L)=>{let w=$.get(L.source),J=$.get(L.target);if(!w||!J)return[];let N=RY(w),q=iL(J,String(L.targetHandle||"in-left")),W=cL(N.x,N.y,q.x,q.y,q.position,Number(L.data?.laneOffset||0),String(L.data?.routeMode||"")),z=nL(L.data?.edgeColor||L.style?.stroke),Z=L.data?.isFeedback?' stroke-dasharray="9 7"':"";return``}).join(` -`),U=u.nodes.map((L)=>{let w=L.data?.exportLabel||{},J=String(w.status||"pending").toLowerCase(),N=J==="succeeded"?"#4eb7a8":J==="running"?"#d7a13a":J==="failed"?"#cf6a54":"#81939f",q=L.position.x,W=L.position.y,z=B$.map((Z)=>{let H=iL(L,Z.id);if(Z.side==="top"||Z.side==="bottom")return``;return``}).join(` +`)),c=A.reduce((j,F)=>j.concat(...F),[]);return[A,c]}return[[],[]]},[u]);return yu.useEffect(()=>{let $=f?.target??kN,A=f?.actInsideInputWithModifier??!0;if(u!==null){let c=(U)=>{if(n.current=U.ctrlKey||U.metaKey||U.shiftKey||U.altKey,(!n.current||n.current&&!A)&&dc(U))return!1;let L=gN(U.code,_);if(i.current.add(U[L]),IN(y,i.current,!1)){let w=U.composedPath?.()?.[0]||U.target,J=w?.nodeName==="BUTTON"||w?.nodeName==="A";if(f.preventDefault!==!1&&(n.current||!J))U.preventDefault();r(!0)}},j=(U)=>{let Q=gN(U.code,_);if(IN(y,i.current,!0))r(!1),i.current.clear();else i.current.delete(U[Q]);if(U.key==="Meta")i.current.clear();n.current=!1},F=()=>{i.current.clear(),r(!1)};return $?.addEventListener("keydown",c),$?.addEventListener("keyup",j),window.addEventListener("blur",F),window.addEventListener("contextmenu",F),()=>{$?.removeEventListener("keydown",c),$?.removeEventListener("keyup",j),window.removeEventListener("blur",F),window.removeEventListener("contextmenu",F)}}},[u,r]),l}function IN(u,f,l){return u.filter((r)=>l||r.length===f.size).some((r)=>r.every((n)=>f.has(n)))}function gN(u,f){return f.includes(u)?"code":"key"}var jD=()=>{let u=Ef();return yu.useMemo(()=>{return{zoomIn:(f)=>{let{panZoom:l}=u.getState();return l?l.scaleBy(1.2,f):Promise.resolve(!1)},zoomOut:(f)=>{let{panZoom:l}=u.getState();return l?l.scaleBy(0.8333333333333334,f):Promise.resolve(!1)},zoomTo:(f,l)=>{let{panZoom:r}=u.getState();return r?r.scaleTo(f,l):Promise.resolve(!1)},getZoom:()=>u.getState().transform[2],setViewport:async(f,l)=>{let{transform:[r,n,i],panZoom:y}=u.getState();if(!y)return Promise.resolve(!1);return await y.setViewport({x:f.x??r,y:f.y??n,zoom:f.zoom??i},l),Promise.resolve(!0)},getViewport:()=>{let[f,l,r]=u.getState().transform;return{x:f,y:l,zoom:r}},setCenter:async(f,l,r)=>{return u.getState().setCenter(f,l,r)},fitBounds:async(f,l)=>{let{width:r,height:n,minZoom:i,maxZoom:y,panZoom:_}=u.getState(),$=T$(f,r,n,i,y,l?.padding??0.1);if(!_)return Promise.resolve(!1);return await _.setViewport($,{duration:l?.duration,ease:l?.ease,interpolate:l?.interpolate}),Promise.resolve(!0)},screenToFlowPosition:(f,l={})=>{let{transform:r,snapGrid:n,snapToGrid:i,domNode:y}=u.getState();if(!y)return f;let{x:_,y:$}=y.getBoundingClientRect(),A={x:f.x-_,y:f.y-$},c=l.snapGrid??n,j=l.snapToGrid??i;return _y(A,r,j,c)},flowToScreenPosition:(f)=>{let{transform:l,domNode:r}=u.getState();if(!r)return f;let{x:n,y:i}=r.getBoundingClientRect(),y=G$(f,l);return{x:y.x+n,y:y.y+i}}}},[])};function UW(u,f){let l=[],r=new Map,n=[];for(let i of u)if(i.type==="add"){n.push(i);continue}else if(i.type==="remove"||i.type==="replace")r.set(i.id,[i]);else{let y=r.get(i.id);if(y)y.push(i);else r.set(i.id,[i])}for(let i of f){let y=r.get(i.id);if(!y){l.push(i);continue}if(y[0].type==="remove")continue;if(y[0].type==="replace"){l.push({...y[0].item});continue}let _={...i};for(let $ of y)FD($,_);l.push(_)}if(n.length)n.forEach((i)=>{if(i.index!==void 0)l.splice(i.index,0,{...i.item});else l.push({...i.item})});return l}function FD(u,f){switch(u.type){case"select":{f.selected=u.selected;break}case"position":{if(typeof u.position<"u")f.position=u.position;if(typeof u.dragging<"u")f.dragging=u.dragging;break}case"dimensions":{if(typeof u.dimensions<"u"){if(f.measured={...u.dimensions},u.setAttributes){if(u.setAttributes===!0||u.setAttributes==="width")f.width=u.dimensions.width;if(u.setAttributes===!0||u.setAttributes==="height")f.height=u.dimensions.height}}if(typeof u.resizing==="boolean")f.resizing=u.resizing;break}}}function JD(u,f){return UW(u,f)}function UD(u,f){return UW(u,f)}function M1(u,f){return{id:u,type:"select",selected:f}}function Ay(u,f=new Set,l=!1){let r=[];for(let[n,i]of u){let y=f.has(n);if(!(i.selected===void 0&&!y)&&i.selected!==y){if(l)i.selected=y;r.push(M1(i.id,y))}}return r}function sN({items:u=[],lookup:f}){let l=[],r=new Map(u.map((n)=>[n.id,n]));for(let[n,i]of u.entries()){let y=f.get(i.id),_=y?.internals?.userNode??y;if(_!==void 0&&_!==i)l.push({id:i.id,item:i,type:"replace"});if(_===void 0)l.push({item:i,type:"add",index:n})}for(let[n]of f)if(r.get(n)===void 0)l.push({id:n,type:"remove"});return l}function aN(u){return{id:u.id,type:"remove"}}var oN=(u)=>eq(u),QD=(u)=>Rc(u);function QW(u){return yu.forwardRef(u)}function dN(u){let[f,l]=yu.useState(BigInt(0)),[r]=yu.useState(()=>qD(()=>l((n)=>n+BigInt(1))));return c9(()=>{let n=r.get();if(n.length)u(n),r.reset()},[f]),r}function qD(u){let f=[];return{get:()=>f,reset:()=>{f=[]},push:(l)=>{f.push(l),u()}}}var qW=yu.createContext(null);function ND({children:u}){let f=Ef(),l=yu.useCallback((_)=>{let{nodes:$=[],setNodes:A,hasDefaultNodes:c,onNodesChange:j,nodeLookup:F,fitViewQueued:U,onNodesChangeMiddlewareMap:Q}=f.getState(),L=$;for(let J of _)L=typeof J==="function"?J(L):J;let w=sN({items:L,lookup:F});for(let J of Q.values())w=J(w);if(c)A(L);if(w.length>0)j?.(w);else if(U)window.requestAnimationFrame(()=>{let{fitViewQueued:J,nodes:N,setNodes:q}=f.getState();if(J)q(N)})},[]),r=dN(l),n=yu.useCallback((_)=>{let{edges:$=[],setEdges:A,hasDefaultEdges:c,onEdgesChange:j,edgeLookup:F}=f.getState(),U=$;for(let Q of _)U=typeof Q==="function"?Q(U):Q;if(c)A(U);else if(j)j(sN({items:U,lookup:F}))},[]),i=dN(n),y=yu.useMemo(()=>({nodeQueue:r,edgeQueue:i}),[]);return ru.jsx(qW.Provider,{value:y,children:u})}function WD(){let u=yu.useContext(qW);if(!u)throw Error("useBatchContext must be used within a BatchProvider");return u}var LD=(u)=>!!u.panZoom;function F9(){let u=jD(),f=Ef(),l=WD(),r=ff(LD),n=yu.useMemo(()=>{let i=(j)=>f.getState().nodeLookup.get(j),y=(j)=>{l.nodeQueue.push(j)},_=(j)=>{l.edgeQueue.push(j)},$=(j)=>{let{nodeLookup:F,nodeOrigin:U}=f.getState(),Q=oN(j)?j:F.get(j.id),L=Q.parentId?sc(Q.position,Q.measured,Q.parentId,F,U):Q.position,w={...Q,position:L,width:Q.measured?.width??Q.width,height:Q.measured?.height??Q.height};return P1(w)},A=(j,F,U={replace:!1})=>{y((Q)=>Q.map((L)=>{if(L.id===j){let w=typeof F==="function"?F(L):F;return U.replace&&oN(w)?w:{...L,...w}}return L}))},c=(j,F,U={replace:!1})=>{_((Q)=>Q.map((L)=>{if(L.id===j){let w=typeof F==="function"?F(L):F;return U.replace&&QD(w)?w:{...L,...w}}return L}))};return{getNodes:()=>f.getState().nodes.map((j)=>({...j})),getNode:(j)=>i(j)?.internals.userNode,getInternalNode:i,getEdges:()=>{let{edges:j=[]}=f.getState();return j.map((F)=>({...F}))},getEdge:(j)=>f.getState().edgeLookup.get(j),setNodes:y,setEdges:_,addNodes:(j)=>{let F=Array.isArray(j)?j:[j];l.nodeQueue.push((U)=>[...U,...F])},addEdges:(j)=>{let F=Array.isArray(j)?j:[j];l.edgeQueue.push((U)=>[...U,...F])},toObject:()=>{let{nodes:j=[],edges:F=[],transform:U}=f.getState(),[Q,L,w]=U;return{nodes:j.map((J)=>({...J})),edges:F.map((J)=>({...J})),viewport:{x:Q,y:L,zoom:w}}},deleteElements:async({nodes:j=[],edges:F=[]})=>{let{nodes:U,edges:Q,onNodesDelete:L,onEdgesDelete:w,triggerNodeChanges:J,triggerEdgeChanges:N,onDelete:q,onBeforeDelete:W}=f.getState(),{nodes:z,edges:Z}=await lN({nodesToRemove:j,edgesToRemove:F,nodes:U,edges:Q,onBeforeDelete:W}),H=Z.length>0,E=z.length>0;if(H){let D=Z.map(aN);w?.(Z),N(D)}if(E){let D=z.map(aN);L?.(z),J(D)}if(E||H)q?.({nodes:z,edges:Z});return{deletedNodes:z,deletedEdges:Z}},getIntersectingNodes:(j,F=!0,U)=>{let Q=kc(j),L=Q?j:$(j),w=U!==void 0;if(!L)return[];return(U||f.getState().nodes).filter((J)=>{let N=f.getState().nodeLookup.get(J.id);if(N&&!Q&&(J.id===j.id||!N.internals.positionAbsolute))return!1;let q=P1(w?J:N),W=iy(q,L);return F&&W>0||W>=q.width*q.height||W>=L.width*L.height})},isNodeIntersecting:(j,F,U=!0)=>{let L=kc(j)?j:$(j);if(!L)return!1;let w=iy(L,F);return U&&w>0||w>=F.width*F.height||w>=L.width*L.height},updateNode:A,updateNodeData:(j,F,U={replace:!1})=>{A(j,(Q)=>{let L=typeof F==="function"?F(Q):F;return U.replace?{...Q,data:L}:{...Q,data:{...Q.data,...L}}},U)},updateEdge:c,updateEdgeData:(j,F,U={replace:!1})=>{c(j,(Q)=>{let L=typeof F==="function"?F(Q):F;return U.replace?{...Q,data:L}:{...Q,data:{...Q.data,...L}}},U)},getNodesBounds:(j)=>{let{nodeLookup:F,nodeOrigin:U}=f.getState();return hc(j,{nodeLookup:F,nodeOrigin:U})},getHandleConnections:({type:j,id:F,nodeId:U})=>Array.from(f.getState().connectionLookup.get(`${U}-${j}${F?`-${F}`:""}`)?.values()??[]),getNodeConnections:({type:j,handleId:F,nodeId:U})=>Array.from(f.getState().connectionLookup.get(`${U}${j?F?`-${j}-${F}`:`-${j}`:""}`)?.values()??[]),fitView:async(j)=>{let F=f.getState().fitViewResolver??iN();return f.setState({fitViewQueued:!0,fitViewOptions:j,fitViewResolver:F}),l.nodeQueue.push((U)=>[...U]),F.promise}}},[]);return yu.useMemo(()=>{return{...n,...u,viewportInitialized:r}},[r])}var eN=(u)=>u.selected,wD=typeof window<"u"?window:void 0;function KD({deleteKeyCode:u,multiSelectionKeyCode:f}){let l=Ef(),{deleteElements:r}=F9(),n=Z$(u,{actInsideInputWithModifier:!1}),i=Z$(f,{target:wD});yu.useEffect(()=>{if(n){let{edges:y,nodes:_}=l.getState();r({nodes:_.filter(eN),edges:y.filter(eN)}),l.setState({nodesSelectionActive:!1})}},[n]),yu.useEffect(()=>{l.setState({multiSelectionActive:i})},[i])}function GD(u){let f=Ef();yu.useEffect(()=>{let l=()=>{if(!u.current||!(u.current.checkVisibility?.()??!0))return!1;let r=k6(u.current);if(r.height===0||r.width===0)f.getState().onError?.("004",Fr.error004());f.setState({width:r.width||500,height:r.height||500})};if(u.current){l(),window.addEventListener("resize",l);let r=new ResizeObserver(()=>l());return r.observe(u.current),()=>{if(window.removeEventListener("resize",l),r&&u.current)r.unobserve(u.current)}}},[])}var _8={position:"absolute",width:"100%",height:"100%",top:0,left:0},zD=(u)=>({userSelectionActive:u.userSelectionActive,lib:u.lib,connectionInProgress:u.connection.inProgress});function TD({onPaneContextMenu:u,zoomOnScroll:f=!0,zoomOnPinch:l=!0,panOnScroll:r=!1,panOnScrollSpeed:n=0.5,panOnScrollMode:i=R0.Free,zoomOnDoubleClick:y=!0,panOnDrag:_=!0,defaultViewport:$,translateExtent:A,minZoom:c,maxZoom:j,zoomActivationKeyCode:F,preventScrolling:U=!0,children:Q,noWheelClassName:L,noPanClassName:w,onViewportChange:J,isControlledViewport:N,paneClickDistance:q,selectionOnDrag:W}){let z=Ef(),Z=yu.useRef(null),{userSelectionActive:H,lib:E,connectionInProgress:D}=ff(zD,Gf),h=Z$(F),V=yu.useRef();GD(Z);let Y=yu.useCallback((p)=>{if(J?.({x:p[0],y:p[1],zoom:p[2]}),!N)z.setState({transform:p})},[J,N]);return yu.useEffect(()=>{if(Z.current){V.current=TN({domNode:Z.current,minZoom:c,maxZoom:j,translateExtent:A,viewport:$,onDraggingChange:(X)=>z.setState((v)=>v.paneDragging===X?v:{paneDragging:X}),onPanZoomStart:(X,v)=>{let{onViewportChangeStart:T,onMoveStart:S}=z.getState();S?.(X,v),T?.(v)},onPanZoom:(X,v)=>{let{onViewportChange:T,onMove:S}=z.getState();S?.(X,v),T?.(v)},onPanZoomEnd:(X,v)=>{let{onViewportChangeEnd:T,onMoveEnd:S}=z.getState();S?.(X,v),T?.(v)}});let{x:p,y:O,zoom:m}=V.current.getViewport();return z.setState({panZoom:V.current,transform:[p,O,m],domNode:Z.current.closest(".react-flow")}),()=>{V.current?.destroy()}}},[]),yu.useEffect(()=>{V.current?.update({onPaneContextMenu:u,zoomOnScroll:f,zoomOnPinch:l,panOnScroll:r,panOnScrollSpeed:n,panOnScrollMode:i,zoomOnDoubleClick:y,panOnDrag:_,zoomActivationKeyPressed:h,preventScrolling:U,noPanClassName:w,userSelectionActive:H,noWheelClassName:L,lib:E,onTransformChange:Y,connectionInProgress:D,selectionOnDrag:W,paneClickDistance:q})},[u,f,l,r,n,i,y,_,h,U,w,H,L,E,Y,D,W,q]),ru.jsx("div",{className:"react-flow__renderer",ref:Z,style:_8,children:Q})}var ED=(u)=>({userSelectionActive:u.userSelectionActive,userSelectionRect:u.userSelectionRect});function ZD(){let{userSelectionActive:u,userSelectionRect:f}=ff(ED,Gf);if(!(u&&f))return null;return ru.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:f.width,height:f.height,transform:`translate(${f.x}px, ${f.y}px)`}})}var t9=(u,f)=>{return(l)=>{if(l.target!==f.current)return;u?.(l)}},OD=(u)=>({userSelectionActive:u.userSelectionActive,elementsSelectable:u.elementsSelectable,connectionInProgress:u.connection.inProgress,dragging:u.paneDragging});function HD({isSelecting:u,selectionKeyPressed:f,selectionMode:l=p1.Full,panOnDrag:r,paneClickDistance:n,selectionOnDrag:i,onSelectionStart:y,onSelectionEnd:_,onPaneClick:$,onPaneContextMenu:A,onPaneScroll:c,onPaneMouseEnter:j,onPaneMouseMove:F,onPaneMouseLeave:U,children:Q}){let L=Ef(),{userSelectionActive:w,elementsSelectable:J,dragging:N,connectionInProgress:q}=ff(OD,Gf),W=J&&(u||w),z=yu.useRef(null),Z=yu.useRef(),H=yu.useRef(new Set),E=yu.useRef(new Set),D=yu.useRef(!1),h=(T)=>{if(D.current||q){D.current=!1;return}$?.(T),L.getState().resetSelectedElements(),L.setState({nodesSelectionActive:!1})},V=(T)=>{if(Array.isArray(r)&&r?.includes(2)){T.preventDefault();return}A?.(T)},Y=c?(T)=>c(T):void 0,p=(T)=>{if(D.current)T.stopPropagation(),D.current=!1},O=(T)=>{let{domNode:S}=L.getState();if(Z.current=S?.getBoundingClientRect(),!Z.current)return;let k=T.target===z.current;if(!k&&!!T.target.closest(".nokey")||!u||!(i&&k||f)||T.button!==0||!T.isPrimary)return;T.target?.setPointerCapture?.(T.pointerId),D.current=!1;let{x:o,y:g}=Zr(T.nativeEvent,Z.current);if(L.setState({userSelectionRect:{width:0,height:0,startX:o,startY:g,x:o,y:g}}),!k)T.stopPropagation(),T.preventDefault()},m=(T)=>{let{userSelectionRect:S,transform:k,nodeLookup:I,edgeLookup:b,connectionLookup:o,triggerNodeChanges:g,triggerEdgeChanges:x,defaultEdgeOptions:fu,resetSelectedElements:$u}=L.getState();if(!Z.current||!S)return;let{x:tu,y:ju}=Zr(T.nativeEvent,Z.current),{startX:Gu,startY:qu}=S;if(!D.current){let s=f?0:n;if(Math.hypot(tu-Gu,ju-qu)<=s)return;$u(),y?.(T)}D.current=!0;let P={startX:Gu,startY:qu,x:tus.id)),E.current=new Set;let wu=fu?.selectable??!0;for(let s of H.current){let Qu=o.get(s);if(!Qu)continue;for(let{edgeId:zu}of Qu.values()){let Ou=b.get(zu);if(Ou&&(Ou.selectable??wu))E.current.add(zu)}}if(!ac(e,H.current)){let s=Ay(I,H.current,!0);g(s)}if(!ac(uu,E.current)){let s=Ay(b,E.current);x(s)}L.setState({userSelectionRect:P,userSelectionActive:!0,nodesSelectionActive:!1})},X=(T)=>{if(T.button!==0)return;if(T.target?.releasePointerCapture?.(T.pointerId),!w&&T.target===z.current&&L.getState().userSelectionRect)h?.(T);if(L.setState({userSelectionActive:!1,userSelectionRect:null}),D.current)_?.(T),L.setState({nodesSelectionActive:H.current.size>0})},v=r===!0||Array.isArray(r)&&r.includes(0);return ru.jsxs("div",{className:Yf(["react-flow__pane",{draggable:v,dragging:N,selection:u}]),onClick:W?void 0:t9(h,z),onContextMenu:t9(V,z),onWheel:t9(Y,z),onPointerEnter:W?void 0:j,onPointerMove:W?m:F,onPointerUp:W?X:void 0,onPointerDownCapture:W?O:void 0,onClickCapture:W?p:void 0,onPointerLeave:U,ref:z,style:_8,children:[Q,ru.jsx(ZD,{})]})}function j9({id:u,store:f,unselect:l=!1,nodeRef:r}){let{addSelectedNodes:n,unselectNodesAndEdges:i,multiSelectionActive:y,nodeLookup:_,onError:$}=f.getState(),A=_.get(u);if(!A){$?.("012",Fr.error012(u));return}if(f.setState({nodesSelectionActive:!1}),!A.selected)n([u]);else if(l||A.selected&&y)i({nodes:[A],edges:[]}),requestAnimationFrame(()=>r?.current?.blur())}function NW({nodeRef:u,disabled:f=!1,noDragClassName:l,handleSelector:r,nodeId:n,isSelectable:i,nodeClickDistance:y}){let _=Ef(),[$,A]=yu.useState(!1),c=yu.useRef();return yu.useEffect(()=>{c.current=qN({getStoreItems:()=>_.getState(),onNodeMouseDown:(j)=>{j9({id:j,store:_,nodeRef:u})},onDragStart:()=>{A(!0)},onDragStop:()=>{A(!1)}})},[]),yu.useEffect(()=>{if(f||!u.current||!c.current)return;return c.current.update({noDragClassName:l,handleSelector:r,domNode:u.current,isSelectable:i,nodeId:n,nodeClickDistance:y}),()=>{c.current?.destroy()}},[l,r,f,i,u,n,y]),$}var BD=(u)=>(f)=>f.selected&&(f.draggable||u&&typeof f.draggable>"u");function WW(){let u=Ef();return yu.useCallback((l)=>{let{nodeExtent:r,snapToGrid:n,snapGrid:i,nodesDraggable:y,onError:_,updateNodePositions:$,nodeLookup:A,nodeOrigin:c}=u.getState(),j=new Map,F=BD(y),U=n?i[0]:5,Q=n?i[1]:5,L=l.direction.x*U*l.factor,w=l.direction.y*Q*l.factor;for(let[,J]of A){if(!F(J))continue;let N={x:J.internals.positionAbsolute.x+L,y:J.internals.positionAbsolute.y+w};if(n)N=yy(N,i);let{position:q,positionAbsolute:W}=bc({nodeId:J.id,nextPosition:N,nodeLookup:A,nodeExtent:r,nodeOrigin:c,onError:_});J.position=q,J.internals.positionAbsolute=W,j.set(J.id,J)}$(j)},[])}var J9=yu.createContext(null),VD=J9.Provider;J9.Consumer;var LW=()=>{return yu.useContext(J9)},DD=(u)=>({connectOnClick:u.connectOnClick,noPanClassName:u.noPanClassName,rfId:u.rfId}),XD=(u,f,l)=>(r)=>{let{connectionClickStartHandle:n,connectionMode:i,connection:y}=r,{fromHandle:_,toHandle:$,isValid:A}=y,c=$?.nodeId===u&&$?.id===f&&$?.type===l;return{connectingFrom:_?.nodeId===u&&_?.id===f&&_?.type===l,connectingTo:c,clickConnecting:n?.nodeId===u&&n?.id===f&&n?.type===l,isPossibleEndHandle:i===Yn.Strict?_?.type!==l:u!==_?.nodeId||f!==_?.id,connectionInProcess:!!_,clickConnectionInProcess:!!n,valid:c&&A}};function YD({type:u="source",position:f=Lu.Top,isValidConnection:l,isConnectable:r=!0,isConnectableStart:n=!0,isConnectableEnd:i=!0,id:y,onConnect:_,children:$,className:A,onMouseDown:c,onTouchStart:j,...F},U){let Q=y||null,L=u==="target",w=Ef(),J=LW(),{connectOnClick:N,noPanClassName:q,rfId:W}=ff(DD,Gf),{connectingFrom:z,connectingTo:Z,clickConnecting:H,isPossibleEndHandle:E,connectionInProcess:D,clickConnectionInProcess:h,valid:V}=ff(XD(J,Q,u),Gf);if(!J)w.getState().onError?.("010",Fr.error010());let Y=(m)=>{let{defaultEdgeOptions:X,onConnect:v,hasDefaultEdges:T}=w.getState(),S={...X,...m};if(T){let{edges:k,setEdges:I}=w.getState();I(f9(S,k))}v?.(S),_?.(S)},p=(m)=>{if(!J)return;let X=ec(m.nativeEvent);if(n&&(X&&m.button===0||!X)){let v=w.getState();e6.onPointerDown(m.nativeEvent,{handleDomNode:m.currentTarget,autoPanOnConnect:v.autoPanOnConnect,connectionMode:v.connectionMode,connectionRadius:v.connectionRadius,domNode:v.domNode,nodeLookup:v.nodeLookup,lib:v.lib,isTarget:L,handleId:Q,nodeId:J,flowId:v.rfId,panBy:v.panBy,cancelConnection:v.cancelConnection,onConnectStart:v.onConnectStart,onConnectEnd:(...T)=>w.getState().onConnectEnd?.(...T),updateConnection:v.updateConnection,onConnect:Y,isValidConnection:l||((...T)=>w.getState().isValidConnection?.(...T)??!0),getTransform:()=>w.getState().transform,getFromHandle:()=>w.getState().connection.fromHandle,autoPanSpeed:v.autoPanSpeed,dragThreshold:v.connectionDragThreshold})}if(X)c?.(m);else j?.(m)},O=(m)=>{let{onClickConnectStart:X,onClickConnectEnd:v,connectionClickStartHandle:T,connectionMode:S,isValidConnection:k,lib:I,rfId:b,nodeLookup:o,connection:g}=w.getState();if(!J||!T&&!n)return;if(!T){X?.(m.nativeEvent,{nodeId:J,handleId:Q,handleType:u}),w.setState({connectionClickStartHandle:{nodeId:J,type:u,id:Q}});return}let x=oc(m.target),fu=l||k,{connection:$u,isValid:tu}=e6.isValid(m.nativeEvent,{handle:{nodeId:J,id:Q,type:u},connectionMode:S,fromNodeId:T.nodeId,fromHandleId:T.id||null,fromType:T.type,isValidConnection:fu,flowId:b,doc:x,lib:I,nodeLookup:o});if(tu&&$u)Y($u);let ju=structuredClone(g);delete ju.inProgress,ju.toPosition=ju.toHandle?ju.toHandle.position:null,v?.(m,ju),w.setState({connectionClickStartHandle:null})};return ru.jsx("div",{"data-handleid":Q,"data-nodeid":J,"data-handlepos":f,"data-id":`${W}-${J}-${Q}-${u}`,className:Yf(["react-flow__handle",`react-flow__handle-${f}`,"nodrag",q,A,{source:!L,target:L,connectable:r,connectablestart:n,connectableend:i,clickconnecting:H,connectingfrom:z,connectingto:Z,valid:V,connectionindicator:r&&(!D||E)&&(D||h?i:n)}]),onMouseDown:p,onTouchStart:p,onClick:N?O:void 0,ref:U,...F,children:$})}var C1=yu.memo(QW(YD));function SD({data:u,isConnectable:f,sourcePosition:l=Lu.Bottom}){return ru.jsxs(ru.Fragment,{children:[u?.label,ru.jsx(C1,{type:"source",position:l,isConnectable:f})]})}function pD({data:u,isConnectable:f,targetPosition:l=Lu.Top,sourcePosition:r=Lu.Bottom}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(C1,{type:"target",position:l,isConnectable:f}),u?.label,ru.jsx(C1,{type:"source",position:r,isConnectable:f})]})}function mD(){return null}function PD({data:u,isConnectable:f,targetPosition:l=Lu.Top}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(C1,{type:"target",position:l,isConnectable:f}),u?.label]})}var n8={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},uW={input:SD,default:pD,output:PD,group:mD};function MD(u){if(u.internals.handleBounds===void 0)return{width:u.width??u.initialWidth??u.style?.width,height:u.height??u.initialHeight??u.style?.height};return{width:u.width??u.style?.width,height:u.height??u.style?.height}}var CD=(u)=>{let{width:f,height:l,x:r,y:n}=ny(u.nodeLookup,{filter:(i)=>!!i.selected});return{width:Er(f)?f:null,height:Er(l)?l:null,userSelectionActive:u.userSelectionActive,transformString:`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]}) translate(${r}px,${n}px)`}};function RD({onSelectionContextMenu:u,noPanClassName:f,disableKeyboardA11y:l}){let r=Ef(),{width:n,height:i,transformString:y,userSelectionActive:_}=ff(CD,Gf),$=WW(),A=yu.useRef(null);yu.useEffect(()=>{if(!l)A.current?.focus({preventScroll:!0})},[l]);let c=!_&&n!==null&&i!==null;if(NW({nodeRef:A,disabled:!c}),!c)return null;let j=u?(U)=>{let Q=r.getState().nodes.filter((L)=>L.selected);u(U,Q)}:void 0,F=(U)=>{if(Object.prototype.hasOwnProperty.call(n8,U.key))U.preventDefault(),$({direction:n8[U.key],factor:U.shiftKey?4:1})};return ru.jsx("div",{className:Yf(["react-flow__nodesselection","react-flow__container",f]),style:{transform:y},children:ru.jsx("div",{ref:A,className:"react-flow__nodesselection-rect",onContextMenu:j,tabIndex:l?void 0:-1,onKeyDown:l?void 0:F,style:{width:n,height:i}})})}var fW=typeof window<"u"?window:void 0,xD=(u)=>{return{nodesSelectionActive:u.nodesSelectionActive,userSelectionActive:u.userSelectionActive}};function wW({children:u,onPaneClick:f,onPaneMouseEnter:l,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,paneClickDistance:_,deleteKeyCode:$,selectionKeyCode:A,selectionOnDrag:c,selectionMode:j,onSelectionStart:F,onSelectionEnd:U,multiSelectionKeyCode:Q,panActivationKeyCode:L,zoomActivationKeyCode:w,elementsSelectable:J,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:W,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:E,defaultViewport:D,translateExtent:h,minZoom:V,maxZoom:Y,preventScrolling:p,onSelectionContextMenu:O,noWheelClassName:m,noPanClassName:X,disableKeyboardA11y:v,onViewportChange:T,isControlledViewport:S}){let{nodesSelectionActive:k,userSelectionActive:I}=ff(xD,Gf),b=Z$(A,{target:fW}),o=Z$(L,{target:fW}),g=o||E,x=o||W,fu=c&&g!==!0,$u=b||I||fu;return KD({deleteKeyCode:$,multiSelectionKeyCode:Q}),ru.jsx(TD,{onPaneContextMenu:i,elementsSelectable:J,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:x,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:!b&&g,defaultViewport:D,translateExtent:h,minZoom:V,maxZoom:Y,zoomActivationKeyCode:w,preventScrolling:p,noWheelClassName:m,noPanClassName:X,onViewportChange:T,isControlledViewport:S,paneClickDistance:_,selectionOnDrag:fu,children:ru.jsxs(HD,{onSelectionStart:F,onSelectionEnd:U,onPaneClick:f,onPaneMouseEnter:l,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,panOnDrag:g,isSelecting:!!$u,selectionMode:j,selectionKeyPressed:b,paneClickDistance:_,selectionOnDrag:fu,children:[u,k&&ru.jsx(RD,{onSelectionContextMenu:O,noPanClassName:X,disableKeyboardA11y:v})]})})}wW.displayName="FlowRenderer";var hD=yu.memo(wW),bD=(u)=>(f)=>{return u?h6(f.nodeLookup,{x:0,y:0,width:f.width,height:f.height},f.transform,!0).map((l)=>l.id):Array.from(f.nodeLookup.keys())};function vD(u){return ff(yu.useCallback(bD(u),[u]),Gf)}var kD=(u)=>u.updateNodeInternals;function ID(){let u=ff(kD),[f]=yu.useState(()=>{if(typeof ResizeObserver>"u")return null;return new ResizeObserver((l)=>{let r=new Map;l.forEach((n)=>{let i=n.target.getAttribute("data-id");r.set(i,{id:i,nodeElement:n.target,force:!0})}),u(r)})});return yu.useEffect(()=>{return()=>{f?.disconnect()}},[f]),f}function gD({node:u,nodeType:f,hasDimensions:l,resizeObserver:r}){let n=Ef(),i=yu.useRef(null),y=yu.useRef(null),_=yu.useRef(u.sourcePosition),$=yu.useRef(u.targetPosition),A=yu.useRef(f),c=l&&!!u.internals.handleBounds;return yu.useEffect(()=>{if(i.current&&!u.hidden&&(!c||y.current!==i.current)){if(y.current)r?.unobserve(y.current);r?.observe(i.current),y.current=i.current}},[c,u.hidden]),yu.useEffect(()=>{return()=>{if(y.current)r?.unobserve(y.current),y.current=null}},[]),yu.useEffect(()=>{if(i.current){let j=A.current!==f,F=_.current!==u.sourcePosition,U=$.current!==u.targetPosition;if(j||F||U)A.current=f,_.current=u.sourcePosition,$.current=u.targetPosition,n.getState().updateNodeInternals(new Map([[u.id,{id:u.id,nodeElement:i.current,force:!0}]]))}},[u.id,f,u.sourcePosition,u.targetPosition]),i}function sD({id:u,onClick:f,onMouseEnter:l,onMouseMove:r,onMouseLeave:n,onContextMenu:i,onDoubleClick:y,nodesDraggable:_,elementsSelectable:$,nodesConnectable:A,nodesFocusable:c,resizeObserver:j,noDragClassName:F,noPanClassName:U,disableKeyboardA11y:Q,rfId:L,nodeTypes:w,nodeClickDistance:J,onError:N}){let{node:q,internals:W,isParent:z}=ff((tu)=>{let ju=tu.nodeLookup.get(u),Gu=tu.parentLookup.has(u);return{node:ju,internals:ju.internals,isParent:Gu}},Gf),Z=q.type||"default",H=w?.[Z]||uW[Z];if(H===void 0)N?.("003",Fr.error003(Z)),Z="default",H=w?.default||uW.default;let E=!!(q.draggable||_&&typeof q.draggable>"u"),D=!!(q.selectable||$&&typeof q.selectable>"u"),h=!!(q.connectable||A&&typeof q.connectable>"u"),V=!!(q.focusable||c&&typeof q.focusable>"u"),Y=Ef(),p=gc(q),O=gD({node:q,nodeType:Z,hasDimensions:p,resizeObserver:j}),m=NW({nodeRef:O,disabled:q.hidden||!E,noDragClassName:F,handleSelector:q.dragHandle,nodeId:u,isSelectable:D,nodeClickDistance:J}),X=WW();if(q.hidden)return null;let v=A0(q),T=MD(q),S=D||E||f||l||r||n,k=l?(tu)=>l(tu,{...W.userNode}):void 0,I=r?(tu)=>r(tu,{...W.userNode}):void 0,b=n?(tu)=>n(tu,{...W.userNode}):void 0,o=i?(tu)=>i(tu,{...W.userNode}):void 0,g=y?(tu)=>y(tu,{...W.userNode}):void 0,x=(tu)=>{let{selectNodesOnDrag:ju,nodeDragThreshold:Gu}=Y.getState();if(D&&(!ju||!E||Gu>0))j9({id:u,store:Y,nodeRef:O});if(f)f(tu,{...W.userNode})},fu=(tu)=>{if(dc(tu.nativeEvent)||Q)return;if(mc.includes(tu.key)&&D){let ju=tu.key==="Escape";j9({id:u,store:Y,unselect:ju,nodeRef:O})}else if(E&&q.selected&&Object.prototype.hasOwnProperty.call(n8,tu.key)){tu.preventDefault();let{ariaLabelConfig:ju}=Y.getState();Y.setState({ariaLiveMessage:ju["node.a11yDescription.ariaLiveMessage"]({direction:tu.key.replace("Arrow","").toLowerCase(),x:~~W.positionAbsolute.x,y:~~W.positionAbsolute.y})}),X({direction:n8[tu.key],factor:tu.shiftKey?4:1})}},$u=()=>{if(Q||!O.current?.matches(":focus-visible"))return;let{transform:tu,width:ju,height:Gu,autoPanOnNodeFocus:qu,setCenter:P}=Y.getState();if(!qu)return;if(!(h6(new Map([[u,q]]),{x:0,y:0,width:ju,height:Gu},tu,!0).length>0))P(q.position.x+v.width/2,q.position.y+v.height/2,{zoom:tu[2]})};return ru.jsx("div",{className:Yf(["react-flow__node",`react-flow__node-${Z}`,{[U]:E},q.className,{selected:q.selected,selectable:D,parent:z,draggable:E,dragging:m}]),ref:O,style:{zIndex:W.z,transform:`translate(${W.positionAbsolute.x}px,${W.positionAbsolute.y}px)`,pointerEvents:S?"all":"none",visibility:p?"visible":"hidden",...q.style,...T},"data-id":u,"data-testid":`rf__node-${u}`,onMouseEnter:k,onMouseMove:I,onMouseLeave:b,onContextMenu:o,onClick:x,onDoubleClick:g,onKeyDown:V?fu:void 0,tabIndex:V?0:void 0,onFocus:V?$u:void 0,role:q.ariaRole??(V?"group":void 0),"aria-roledescription":"node","aria-describedby":Q?void 0:`${jW}-${L}`,"aria-label":q.ariaLabel,...q.domAttributes,children:ru.jsx(VD,{value:u,children:ru.jsx(H,{id:u,data:q.data,type:Z,positionAbsoluteX:W.positionAbsolute.x,positionAbsoluteY:W.positionAbsolute.y,selected:q.selected??!1,selectable:D,draggable:E,deletable:q.deletable??!0,isConnectable:h,sourcePosition:q.sourcePosition,targetPosition:q.targetPosition,dragging:m,dragHandle:q.dragHandle,zIndex:W.z,parentId:q.parentId,...v})})})}var aD=yu.memo(sD),oD=(u)=>({nodesDraggable:u.nodesDraggable,nodesConnectable:u.nodesConnectable,nodesFocusable:u.nodesFocusable,elementsSelectable:u.elementsSelectable,onError:u.onError});function KW(u){let{nodesDraggable:f,nodesConnectable:l,nodesFocusable:r,elementsSelectable:n,onError:i}=ff(oD,Gf),y=vD(u.onlyRenderVisibleElements),_=ID();return ru.jsx("div",{className:"react-flow__nodes",style:_8,children:y.map(($)=>{return ru.jsx(aD,{id:$,nodeTypes:u.nodeTypes,nodeExtent:u.nodeExtent,onClick:u.onNodeClick,onMouseEnter:u.onNodeMouseEnter,onMouseMove:u.onNodeMouseMove,onMouseLeave:u.onNodeMouseLeave,onContextMenu:u.onNodeContextMenu,onDoubleClick:u.onNodeDoubleClick,noDragClassName:u.noDragClassName,noPanClassName:u.noPanClassName,rfId:u.rfId,disableKeyboardA11y:u.disableKeyboardA11y,resizeObserver:_,nodesDraggable:f,nodesConnectable:l,nodesFocusable:r,elementsSelectable:n,nodeClickDistance:u.nodeClickDistance,onError:i},$)})})}KW.displayName="NodeRenderer";var dD=yu.memo(KW);function eD(u){return ff(yu.useCallback((l)=>{if(!u)return l.edges.map((n)=>n.id);let r=[];if(l.width&&l.height)for(let n of l.edges){let i=l.nodeLookup.get(n.source),y=l.nodeLookup.get(n.target);if(i&&y&&$N({sourceNode:i,targetNode:y,width:l.width,height:l.height,transform:l.transform}))r.push(n.id)}return r},[u]),Gf)}var uX=({color:u="none",strokeWidth:f=1})=>{let l={strokeWidth:f,...u&&{stroke:u}};return ru.jsx("polyline",{className:"arrow",style:l,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},fX=({color:u="none",strokeWidth:f=1})=>{let l={strokeWidth:f,...u&&{stroke:u,fill:u}};return ru.jsx("polyline",{className:"arrowclosed",style:l,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},lW={[Sn.Arrow]:uX,[Sn.ArrowClosed]:fX};function lX(u){let f=Ef();return yu.useMemo(()=>{if(!Object.prototype.hasOwnProperty.call(lW,u))return f.getState().onError?.("009",Fr.error009(u)),null;return lW[u]},[u])}var rX=({id:u,type:f,color:l,width:r=12.5,height:n=12.5,markerUnits:i="strokeWidth",strokeWidth:y,orient:_="auto-start-reverse"})=>{let $=lX(f);if(!$)return null;return ru.jsx("marker",{className:"react-flow__arrowhead",id:u,markerWidth:`${r}`,markerHeight:`${n}`,viewBox:"-10 -10 20 20",markerUnits:i,orient:_,refX:"0",refY:"0",children:ru.jsx($,{color:l,strokeWidth:y})})},GW=({defaultColor:u,rfId:f})=>{let l=ff((i)=>i.edges),r=ff((i)=>i.defaultEdgeOptions),n=yu.useMemo(()=>{return AN(l,{id:f,defaultColor:u,defaultMarkerStart:r?.markerStart,defaultMarkerEnd:r?.markerEnd})},[l,r,f,u]);if(!n.length)return null;return ru.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:ru.jsx("defs",{children:n.map((i)=>ru.jsx(rX,{id:i.id,type:i.type,color:i.color,width:i.width,height:i.height,markerUnits:i.markerUnits,strokeWidth:i.strokeWidth,orient:i.orient},i.id))})})};GW.displayName="MarkerDefinitions";var nX=yu.memo(GW);function zW({x:u,y:f,label:l,labelStyle:r,labelShowBg:n=!0,labelBgStyle:i,labelBgPadding:y=[2,4],labelBgBorderRadius:_=2,children:$,className:A,...c}){let[j,F]=yu.useState({x:1,y:0,width:0,height:0}),U=Yf(["react-flow__edge-textwrapper",A]),Q=yu.useRef(null);if(yu.useEffect(()=>{if(Q.current){let L=Q.current.getBBox();F({x:L.x,y:L.y,width:L.width,height:L.height})}},[l]),!l)return null;return ru.jsxs("g",{transform:`translate(${u-j.width/2} ${f-j.height/2})`,className:U,visibility:j.width?"visible":"hidden",...c,children:[n&&ru.jsx("rect",{width:j.width+2*y[0],x:-y[0],y:-y[1],height:j.height+2*y[1],className:"react-flow__edge-textbg",style:i,rx:_,ry:_}),ru.jsx("text",{className:"react-flow__edge-text",y:j.height/2,dy:"0.3em",ref:Q,style:r,children:l}),$]})}zW.displayName="EdgeText";var iX=yu.memo(zW);function cy({path:u,labelX:f,labelY:l,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:_,labelBgBorderRadius:$,interactionWidth:A=20,...c}){return ru.jsxs(ru.Fragment,{children:[ru.jsx("path",{...c,d:u,fill:"none",className:Yf(["react-flow__edge-path",c.className])}),A?ru.jsx("path",{d:u,fill:"none",strokeOpacity:0,strokeWidth:A,className:"react-flow__edge-interaction"}):null,r&&Er(f)&&Er(l)?ru.jsx(iX,{x:f,y:l,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:_,labelBgBorderRadius:$}):null]})}function rW({pos:u,x1:f,y1:l,x2:r,y2:n}){if(u===Lu.Left||u===Lu.Right)return[0.5*(f+r),l];return[f,0.5*(l+n)]}function TW({sourceX:u,sourceY:f,sourcePosition:l=Lu.Bottom,targetX:r,targetY:n,targetPosition:i=Lu.Top}){let[y,_]=rW({pos:l,x1:u,y1:f,x2:r,y2:n}),[$,A]=rW({pos:i,x1:r,y1:n,x2:u,y2:f}),[c,j,F,U]=I6({sourceX:u,sourceY:f,targetX:r,targetY:n,sourceControlX:y,sourceControlY:_,targetControlX:$,targetControlY:A});return[`M${u},${f} C${y},${_} ${$},${A} ${r},${n}`,c,j,F,U]}function EW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,sourcePosition:y,targetPosition:_,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,interactionWidth:J})=>{let[N,q,W]=TW({sourceX:l,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:_}),z=u.isInternal?void 0:f;return ru.jsx(cy,{id:z,path:N,labelX:q,labelY:W,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,interactionWidth:J})})}var yX=EW({isInternal:!1}),ZW=EW({isInternal:!0});yX.displayName="SimpleBezierEdge";ZW.displayName="SimpleBezierEdgeInternal";function OW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,sourcePosition:U=Lu.Bottom,targetPosition:Q=Lu.Top,markerEnd:L,markerStart:w,pathOptions:J,interactionWidth:N})=>{let[q,W,z]=E$({sourceX:l,sourceY:r,sourcePosition:U,targetX:n,targetY:i,targetPosition:Q,borderRadius:J?.borderRadius,offset:J?.offset,stepPosition:J?.stepPosition}),Z=u.isInternal?void 0:f;return ru.jsx(cy,{id:Z,path:q,labelX:W,labelY:z,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,markerEnd:L,markerStart:w,interactionWidth:N})})}var HW=OW({isInternal:!1}),BW=OW({isInternal:!0});HW.displayName="SmoothStepEdge";BW.displayName="SmoothStepEdgeInternal";function VW(u){return yu.memo(({id:f,...l})=>{let r=u.isInternal?void 0:f;return ru.jsx(HW,{...l,id:r,pathOptions:yu.useMemo(()=>({borderRadius:0,offset:l.pathOptions?.offset}),[l.pathOptions?.offset])})})}var _X=VW({isInternal:!1}),DW=VW({isInternal:!0});_X.displayName="StepEdge";DW.displayName="StepEdgeInternal";function XW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,markerEnd:U,markerStart:Q,interactionWidth:L})=>{let[w,J,N]=s6({sourceX:l,sourceY:r,targetX:n,targetY:i}),q=u.isInternal?void 0:f;return ru.jsx(cy,{id:q,path:w,labelX:J,labelY:N,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,markerEnd:U,markerStart:Q,interactionWidth:L})})}var $X=XW({isInternal:!1}),YW=XW({isInternal:!0});$X.displayName="StraightEdge";YW.displayName="StraightEdgeInternal";function SW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,sourcePosition:y=Lu.Bottom,targetPosition:_=Lu.Top,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,pathOptions:J,interactionWidth:N})=>{let[q,W,z]=g6({sourceX:l,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:_,curvature:J?.curvature}),Z=u.isInternal?void 0:f;return ru.jsx(cy,{id:Z,path:q,labelX:W,labelY:z,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,interactionWidth:N})})}var tX=SW({isInternal:!1}),pW=SW({isInternal:!0});tX.displayName="BezierEdge";pW.displayName="BezierEdgeInternal";var nW={default:pW,straight:YW,step:DW,smoothstep:BW,simplebezier:ZW},iW={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null},AX=(u,f,l)=>{if(l===Lu.Left)return u-f;if(l===Lu.Right)return u+f;return u},cX=(u,f,l)=>{if(l===Lu.Top)return u-f;if(l===Lu.Bottom)return u+f;return u},yW="react-flow__edgeupdater";function _W({position:u,centerX:f,centerY:l,radius:r=10,onMouseDown:n,onMouseEnter:i,onMouseOut:y,type:_}){return ru.jsx("circle",{onMouseDown:n,onMouseEnter:i,onMouseOut:y,className:Yf([yW,`${yW}-${_}`]),cx:AX(f,r,u),cy:cX(l,r,u),r,stroke:"transparent",fill:"transparent"})}function jX({isReconnectable:u,reconnectRadius:f,edge:l,sourceX:r,sourceY:n,targetX:i,targetY:y,sourcePosition:_,targetPosition:$,onReconnect:A,onReconnectStart:c,onReconnectEnd:j,setReconnecting:F,setUpdateHover:U}){let Q=Ef(),L=(W,z)=>{if(W.button!==0)return;let{autoPanOnConnect:Z,domNode:H,connectionMode:E,connectionRadius:D,lib:h,onConnectStart:V,cancelConnection:Y,nodeLookup:p,rfId:O,panBy:m,updateConnection:X}=Q.getState(),v=z.type==="target",T=(I,b)=>{F(!1),j?.(I,l,z.type,b)},S=(I)=>A?.(l,I),k=(I,b)=>{F(!0),c?.(W,l,z.type),V?.(I,b)};e6.onPointerDown(W.nativeEvent,{autoPanOnConnect:Z,connectionMode:E,connectionRadius:D,domNode:H,handleId:z.id,nodeId:z.nodeId,nodeLookup:p,isTarget:v,edgeUpdaterType:z.type,lib:h,flowId:O,cancelConnection:Y,panBy:m,isValidConnection:(...I)=>Q.getState().isValidConnection?.(...I)??!0,onConnect:S,onConnectStart:k,onConnectEnd:(...I)=>Q.getState().onConnectEnd?.(...I),onReconnectEnd:T,updateConnection:X,getTransform:()=>Q.getState().transform,getFromHandle:()=>Q.getState().connection.fromHandle,dragThreshold:Q.getState().connectionDragThreshold,handleDomNode:W.currentTarget})},w=(W)=>L(W,{nodeId:l.target,id:l.targetHandle??null,type:"target"}),J=(W)=>L(W,{nodeId:l.source,id:l.sourceHandle??null,type:"source"}),N=()=>U(!0),q=()=>U(!1);return ru.jsxs(ru.Fragment,{children:[(u===!0||u==="source")&&ru.jsx(_W,{position:_,centerX:r,centerY:n,radius:f,onMouseDown:w,onMouseEnter:N,onMouseOut:q,type:"source"}),(u===!0||u==="target")&&ru.jsx(_W,{position:$,centerX:i,centerY:y,radius:f,onMouseDown:J,onMouseEnter:N,onMouseOut:q,type:"target"})]})}function FX({id:u,edgesFocusable:f,edgesReconnectable:l,elementsSelectable:r,onClick:n,onDoubleClick:i,onContextMenu:y,onMouseEnter:_,onMouseMove:$,onMouseLeave:A,reconnectRadius:c,onReconnect:j,onReconnectStart:F,onReconnectEnd:U,rfId:Q,edgeTypes:L,noPanClassName:w,onError:J,disableKeyboardA11y:N}){let q=ff((P)=>P.edgeLookup.get(u)),W=ff((P)=>P.defaultEdgeOptions);q=W?{...W,...q}:q;let z=q.type||"default",Z=L?.[z]||nW[z];if(Z===void 0)J?.("011",Fr.error011(z)),z="default",Z=L?.default||nW.default;let H=!!(q.focusable||f&&typeof q.focusable>"u"),E=typeof j<"u"&&(q.reconnectable||l&&typeof q.reconnectable>"u"),D=!!(q.selectable||r&&typeof q.selectable>"u"),h=yu.useRef(null),[V,Y]=yu.useState(!1),[p,O]=yu.useState(!1),m=Ef(),{zIndex:X,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b}=ff(yu.useCallback((P)=>{let e=P.nodeLookup.get(q.source),uu=P.nodeLookup.get(q.target);if(!e||!uu)return{zIndex:q.zIndex,...iW};let wu=tN({id:u,sourceNode:e,targetNode:uu,sourceHandle:q.sourceHandle||null,targetHandle:q.targetHandle||null,connectionMode:P.connectionMode,onError:J});return{zIndex:_N({selected:q.selected,zIndex:q.zIndex,sourceNode:e,targetNode:uu,elevateOnSelect:P.elevateEdgesOnSelect,zIndexMode:P.zIndexMode}),...wu||iW}},[q.source,q.target,q.sourceHandle,q.targetHandle,q.selected,q.zIndex]),Gf),o=yu.useMemo(()=>q.markerStart?`url('#${a6(q.markerStart,Q)}')`:void 0,[q.markerStart,Q]),g=yu.useMemo(()=>q.markerEnd?`url('#${a6(q.markerEnd,Q)}')`:void 0,[q.markerEnd,Q]);if(q.hidden||v===null||T===null||S===null||k===null)return null;let x=(P)=>{let{addSelectedEdges:e,unselectNodesAndEdges:uu,multiSelectionActive:wu}=m.getState();if(D)if(m.setState({nodesSelectionActive:!1}),q.selected&&wu)uu({nodes:[],edges:[q]}),h.current?.blur();else e([u]);if(n)n(P,q)},fu=i?(P)=>{i(P,{...q})}:void 0,$u=y?(P)=>{y(P,{...q})}:void 0,tu=_?(P)=>{_(P,{...q})}:void 0,ju=$?(P)=>{$(P,{...q})}:void 0,Gu=A?(P)=>{A(P,{...q})}:void 0,qu=(P)=>{if(!N&&mc.includes(P.key)&&D){let{unselectNodesAndEdges:e,addSelectedEdges:uu}=m.getState();if(P.key==="Escape")h.current?.blur(),e({edges:[q]});else uu([u])}};return ru.jsx("svg",{style:{zIndex:X},children:ru.jsxs("g",{className:Yf(["react-flow__edge",`react-flow__edge-${z}`,q.className,w,{selected:q.selected,animated:q.animated,inactive:!D&&!n,updating:V,selectable:D}]),onClick:x,onDoubleClick:fu,onContextMenu:$u,onMouseEnter:tu,onMouseMove:ju,onMouseLeave:Gu,onKeyDown:H?qu:void 0,tabIndex:H?0:void 0,role:q.ariaRole??(H?"group":"img"),"aria-roledescription":"edge","data-id":u,"data-testid":`rf__edge-${u}`,"aria-label":q.ariaLabel===null?void 0:q.ariaLabel||`Edge from ${q.source} to ${q.target}`,"aria-describedby":H?`${FW}-${Q}`:void 0,ref:h,...q.domAttributes,children:[!p&&ru.jsx(Z,{id:u,source:q.source,target:q.target,type:q.type,selected:q.selected,animated:q.animated,selectable:D,deletable:q.deletable??!0,label:q.label,labelStyle:q.labelStyle,labelShowBg:q.labelShowBg,labelBgStyle:q.labelBgStyle,labelBgPadding:q.labelBgPadding,labelBgBorderRadius:q.labelBgBorderRadius,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b,data:q.data,style:q.style,sourceHandleId:q.sourceHandle,targetHandleId:q.targetHandle,markerStart:o,markerEnd:g,pathOptions:"pathOptions"in q?q.pathOptions:void 0,interactionWidth:q.interactionWidth}),E&&ru.jsx(jX,{edge:q,isReconnectable:E,reconnectRadius:c,onReconnect:j,onReconnectStart:F,onReconnectEnd:U,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b,setUpdateHover:Y,setReconnecting:O})]})})}var JX=yu.memo(FX),UX=(u)=>({edgesFocusable:u.edgesFocusable,edgesReconnectable:u.edgesReconnectable,elementsSelectable:u.elementsSelectable,connectionMode:u.connectionMode,onError:u.onError});function mW({defaultMarkerColor:u,onlyRenderVisibleElements:f,rfId:l,edgeTypes:r,noPanClassName:n,onReconnect:i,onEdgeContextMenu:y,onEdgeMouseEnter:_,onEdgeMouseMove:$,onEdgeMouseLeave:A,onEdgeClick:c,reconnectRadius:j,onEdgeDoubleClick:F,onReconnectStart:U,onReconnectEnd:Q,disableKeyboardA11y:L}){let{edgesFocusable:w,edgesReconnectable:J,elementsSelectable:N,onError:q}=ff(UX,Gf),W=eD(f);return ru.jsxs("div",{className:"react-flow__edges",children:[ru.jsx(nX,{defaultColor:u,rfId:l}),W.map((z)=>{return ru.jsx(JX,{id:z,edgesFocusable:w,edgesReconnectable:J,elementsSelectable:N,noPanClassName:n,onReconnect:i,onContextMenu:y,onMouseEnter:_,onMouseMove:$,onMouseLeave:A,onClick:c,reconnectRadius:j,onDoubleClick:F,onReconnectStart:U,onReconnectEnd:Q,rfId:l,onError:q,edgeTypes:r,disableKeyboardA11y:L},z)})]})}mW.displayName="EdgeRenderer";var QX=yu.memo(mW),qX=(u)=>`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]})`;function NX({children:u}){let f=ff(qX);return ru.jsx("div",{className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:f},children:u})}function WX(u){let f=F9(),l=yu.useRef(!1);yu.useEffect(()=>{if(!l.current&&f.viewportInitialized&&u)setTimeout(()=>u(f),1),l.current=!0},[u,f.viewportInitialized])}var LX=(u)=>u.panZoom?.syncViewport;function wX(u){let f=ff(LX),l=Ef();return yu.useEffect(()=>{if(u)f?.(u),l.setState({transform:[u.x,u.y,u.zoom]})},[u,f]),null}function $W(u){return u.connection.inProgress?{...u.connection,to:_y(u.connection.to,u.transform)}:{...u.connection}}function KX(u){if(u)return(l)=>{let r=$W(l);return u(r)};return $W}function GX(u){let f=KX(u);return ff(f,Gf)}var zX=(u)=>({nodesConnectable:u.nodesConnectable,isValid:u.connection.isValid,inProgress:u.connection.inProgress,width:u.width,height:u.height});function TX({containerStyle:u,style:f,type:l,component:r}){let{nodesConnectable:n,width:i,height:y,isValid:_,inProgress:$}=ff(zX,Gf);if(!(i&&n&&$))return null;return ru.jsx("svg",{style:u,width:i,height:y,className:"react-flow__connectionline react-flow__container",children:ru.jsx("g",{className:Yf(["react-flow__connection",Cc(_)]),children:ru.jsx(PW,{style:f,type:l,CustomComponent:r,isValid:_})})})}var PW=({style:u,type:f=t0.Bezier,CustomComponent:l,isValid:r})=>{let{inProgress:n,from:i,fromNode:y,fromHandle:_,fromPosition:$,to:A,toNode:c,toHandle:j,toPosition:F,pointer:U}=GX();if(!n)return;if(l)return ru.jsx(l,{connectionLineType:f,connectionLineStyle:u,fromNode:y,fromHandle:_,fromX:i.x,fromY:i.y,toX:A.x,toY:A.y,fromPosition:$,toPosition:F,connectionStatus:Cc(r),toNode:c,toHandle:j,pointer:U});let Q="",L={sourceX:i.x,sourceY:i.y,sourcePosition:$,targetX:A.x,targetY:A.y,targetPosition:F};switch(f){case t0.Bezier:[Q]=g6(L);break;case t0.SimpleBezier:[Q]=TW(L);break;case t0.Step:[Q]=E$({...L,borderRadius:0});break;case t0.SmoothStep:[Q]=E$(L);break;default:[Q]=s6(L)}return ru.jsx("path",{d:Q,fill:"none",className:"react-flow__connection-path",style:u})};PW.displayName="ConnectionLine";var EX={};function tW(u=EX){let f=yu.useRef(u),l=Ef();yu.useEffect(()=>{},[u])}function ZX(){let u=Ef(),f=yu.useRef(!1);yu.useEffect(()=>{},[])}function MW({nodeTypes:u,edgeTypes:f,onInit:l,onNodeClick:r,onEdgeClick:n,onNodeDoubleClick:i,onEdgeDoubleClick:y,onNodeMouseEnter:_,onNodeMouseMove:$,onNodeMouseLeave:A,onNodeContextMenu:c,onSelectionContextMenu:j,onSelectionStart:F,onSelectionEnd:U,connectionLineType:Q,connectionLineStyle:L,connectionLineComponent:w,connectionLineContainerStyle:J,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,deleteKeyCode:E,onlyRenderVisibleElements:D,elementsSelectable:h,defaultViewport:V,translateExtent:Y,minZoom:p,maxZoom:O,preventScrolling:m,defaultMarkerColor:X,zoomOnScroll:v,zoomOnPinch:T,panOnScroll:S,panOnScrollSpeed:k,panOnScrollMode:I,zoomOnDoubleClick:b,panOnDrag:o,onPaneClick:g,onPaneMouseEnter:x,onPaneMouseMove:fu,onPaneMouseLeave:$u,onPaneScroll:tu,onPaneContextMenu:ju,paneClickDistance:Gu,nodeClickDistance:qu,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:wu,reconnectRadius:s,onReconnect:Qu,onReconnectStart:zu,onReconnectEnd:Ou,noDragClassName:bu,noWheelClassName:eu,noPanClassName:pu,disableKeyboardA11y:Ff,nodeExtent:Fl,rfId:Tl,viewport:fl,onViewportChange:of}){return tW(u),tW(f),ZX(),WX(l),wX(fl),ru.jsx(hD,{onPaneClick:g,onPaneMouseEnter:x,onPaneMouseMove:fu,onPaneMouseLeave:$u,onPaneContextMenu:ju,onPaneScroll:tu,paneClickDistance:Gu,deleteKeyCode:E,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,onSelectionStart:F,onSelectionEnd:U,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,elementsSelectable:h,zoomOnScroll:v,zoomOnPinch:T,zoomOnDoubleClick:b,panOnScroll:S,panOnScrollSpeed:k,panOnScrollMode:I,panOnDrag:o,defaultViewport:V,translateExtent:Y,minZoom:p,maxZoom:O,onSelectionContextMenu:j,preventScrolling:m,noDragClassName:bu,noWheelClassName:eu,noPanClassName:pu,disableKeyboardA11y:Ff,onViewportChange:of,isControlledViewport:!!fl,children:ru.jsxs(NX,{children:[ru.jsx(QX,{edgeTypes:f,onEdgeClick:n,onEdgeDoubleClick:y,onReconnect:Qu,onReconnectStart:zu,onReconnectEnd:Ou,onlyRenderVisibleElements:D,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:wu,reconnectRadius:s,defaultMarkerColor:X,noPanClassName:pu,disableKeyboardA11y:Ff,rfId:Tl}),ru.jsx(TX,{style:L,type:Q,component:w,containerStyle:J}),ru.jsx("div",{className:"react-flow__edgelabel-renderer"}),ru.jsx(dD,{nodeTypes:u,onNodeClick:r,onNodeDoubleClick:i,onNodeMouseEnter:_,onNodeMouseMove:$,onNodeMouseLeave:A,onNodeContextMenu:c,nodeClickDistance:qu,onlyRenderVisibleElements:D,noPanClassName:pu,noDragClassName:bu,disableKeyboardA11y:Ff,nodeExtent:Fl,rfId:Tl}),ru.jsx("div",{className:"react-flow__viewport-portal"})]})})}MW.displayName="GraphView";var OX=yu.memo(MW),AW=({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$=0.5,maxZoom:A=2,nodeOrigin:c,nodeExtent:j,zIndexMode:F="basic"}={})=>{let U=new Map,Q=new Map,L=new Map,w=new Map,J=r??f??[],N=l??u??[],q=c??[0,0],W=j??ry;y9(L,w,J);let{nodesInitialized:z}=o6(N,U,Q,{nodeOrigin:q,nodeExtent:W,zIndexMode:F}),Z=[0,0,1];if(y&&n&&i){let H=ny(U,{filter:(V)=>!!((V.width||V.initialWidth)&&(V.height||V.initialHeight))}),{x:E,y:D,zoom:h}=T$(H,n,i,$,A,_?.padding??0.1);Z=[E,D,h]}return{rfId:"1",width:n??0,height:i??0,transform:Z,nodes:N,nodesInitialized:z,nodeLookup:U,parentLookup:Q,edges:J,edgeLookup:w,connectionLookup:L,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:l!==void 0,hasDefaultEdges:r!==void 0,panZoom:null,minZoom:$,maxZoom:A,translateExtent:ry,nodeExtent:W,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:Yn.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:q,nodeDragThreshold:1,connectionDragThreshold:1,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesReconnectable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,elevateEdgesOnSelect:!0,selectNodesOnDrag:!0,multiSelectionActive:!1,fitViewQueued:y??!1,fitViewOptions:_,fitViewResolver:null,connection:{...Mc},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:Ic,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:Pc,zIndexMode:F,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},HX=({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$,maxZoom:A,nodeOrigin:c,nodeExtent:j,zIndexMode:F})=>RN((U,Q)=>{async function L(){let{nodeLookup:w,panZoom:J,fitViewOptions:N,fitViewResolver:q,width:W,height:z,minZoom:Z,maxZoom:H}=Q();if(!J)return;await fN({nodes:w,width:W,height:z,panZoom:J,minZoom:Z,maxZoom:H},N),q?.resolve(!0),U({fitViewResolver:null})}return{...AW({nodes:u,edges:f,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$,maxZoom:A,nodeOrigin:c,nodeExtent:j,defaultNodes:l,defaultEdges:r,zIndexMode:F}),setNodes:(w)=>{let{nodeLookup:J,parentLookup:N,nodeOrigin:q,elevateNodesOnSelect:W,fitViewQueued:z,zIndexMode:Z,nodesSelectionActive:H}=Q(),{nodesInitialized:E,hasSelectedNodes:D}=o6(w,J,N,{nodeOrigin:q,nodeExtent:j,elevateNodesOnSelect:W,checkEquality:!0,zIndexMode:Z}),h=H&&D;if(z&&E)L(),U({nodes:w,nodesInitialized:E,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:h});else U({nodes:w,nodesInitialized:E,nodesSelectionActive:h})},setEdges:(w)=>{let{connectionLookup:J,edgeLookup:N}=Q();y9(J,N,w),U({edges:w})},setDefaultNodesAndEdges:(w,J)=>{if(w){let{setNodes:N}=Q();N(w),U({hasDefaultNodes:!0})}if(J){let{setEdges:N}=Q();N(J),U({hasDefaultEdges:!0})}},updateNodeInternals:(w)=>{let{triggerNodeChanges:J,nodeLookup:N,parentLookup:q,domNode:W,nodeOrigin:z,nodeExtent:Z,debug:H,fitViewQueued:E,zIndexMode:D}=Q(),{changes:h,updatedInternals:V}=JN(w,N,q,W,z,Z,D);if(!V)return;if(jN(N,q,{nodeOrigin:z,nodeExtent:Z,zIndexMode:D}),E)L(),U({fitViewQueued:!1,fitViewOptions:void 0});else U({});if(h?.length>0){if(H)console.log("React Flow: trigger node changes",h);J?.(h)}},updateNodePositions:(w,J=!1)=>{let N=[],q=[],{nodeLookup:W,triggerNodeChanges:z,connection:Z,updateConnection:H,onNodesChangeMiddlewareMap:E}=Q();for(let[D,h]of w){let V=W.get(D),Y=!!(V?.expandParent&&V?.parentId&&h?.position),p={id:D,type:"position",position:Y?{x:Math.max(0,h.position.x),y:Math.max(0,h.position.y)}:h.position,dragging:J};if(V&&Z.inProgress&&Z.fromNode.id===V.id){let O=pn(V,Z.fromHandle,Lu.Left,!0);H({...Z,from:O})}if(Y&&V.parentId)N.push({id:D,parentId:V.parentId,rect:{...h.internals.positionAbsolute,width:h.measured.width??0,height:h.measured.height??0}});q.push(p)}if(N.length>0){let{parentLookup:D,nodeOrigin:h}=Q(),V=d6(N,W,D,h);q.push(...V)}for(let D of E.values())q=D(q);z(q)},triggerNodeChanges:(w)=>{let{onNodesChange:J,setNodes:N,nodes:q,hasDefaultNodes:W,debug:z}=Q();if(w?.length){if(W){let Z=JD(w,q);N(Z)}if(z)console.log("React Flow: trigger node changes",w);J?.(w)}},triggerEdgeChanges:(w)=>{let{onEdgesChange:J,setEdges:N,edges:q,hasDefaultEdges:W,debug:z}=Q();if(w?.length){if(W){let Z=UD(w,q);N(Z)}if(z)console.log("React Flow: trigger edge changes",w);J?.(w)}},addSelectedNodes:(w)=>{let{multiSelectionActive:J,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(J){let Z=w.map((H)=>M1(H,!0));W(Z);return}W(Ay(q,new Set([...w]),!0)),z(Ay(N))},addSelectedEdges:(w)=>{let{multiSelectionActive:J,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(J){let Z=w.map((H)=>M1(H,!0));z(Z);return}z(Ay(N,new Set([...w]))),W(Ay(q,new Set,!0))},unselectNodesAndEdges:({nodes:w,edges:J}={})=>{let{edges:N,nodes:q,nodeLookup:W,triggerNodeChanges:z,triggerEdgeChanges:Z}=Q(),H=w?w:q,E=J?J:N,D=[];for(let V of H){if(!V.selected)continue;let Y=W.get(V.id);if(Y)Y.selected=!1;D.push(M1(V.id,!1))}let h=[];for(let V of E){if(!V.selected)continue;h.push(M1(V.id,!1))}z(D),Z(h)},setMinZoom:(w)=>{let{panZoom:J,maxZoom:N}=Q();J?.setScaleExtent([w,N]),U({minZoom:w})},setMaxZoom:(w)=>{let{panZoom:J,minZoom:N}=Q();J?.setScaleExtent([N,w]),U({maxZoom:w})},setTranslateExtent:(w)=>{Q().panZoom?.setTranslateExtent(w),U({translateExtent:w})},resetSelectedElements:()=>{let{edges:w,nodes:J,triggerNodeChanges:N,triggerEdgeChanges:q,elementsSelectable:W}=Q();if(!W)return;let z=J.reduce((H,E)=>E.selected?[...H,M1(E.id,!1)]:H,[]),Z=w.reduce((H,E)=>E.selected?[...H,M1(E.id,!1)]:H,[]);N(z),q(Z)},setNodeExtent:(w)=>{let{nodes:J,nodeLookup:N,parentLookup:q,nodeOrigin:W,elevateNodesOnSelect:z,nodeExtent:Z,zIndexMode:H}=Q();if(w[0][0]===Z[0][0]&&w[0][1]===Z[0][1]&&w[1][0]===Z[1][0]&&w[1][1]===Z[1][1])return;o6(J,N,q,{nodeOrigin:W,nodeExtent:w,elevateNodesOnSelect:z,checkEquality:!1,zIndexMode:H}),U({nodeExtent:w})},panBy:(w)=>{let{transform:J,width:N,height:q,panZoom:W,translateExtent:z}=Q();return UN({delta:w,panZoom:W,transform:J,translateExtent:z,width:N,height:q})},setCenter:async(w,J,N)=>{let{width:q,height:W,maxZoom:z,panZoom:Z}=Q();if(!Z)return Promise.resolve(!1);let H=typeof N?.zoom<"u"?N.zoom:z;return await Z.setViewport({x:q/2-w*H,y:W/2-J*H,zoom:H},{duration:N?.duration,ease:N?.ease,interpolate:N?.interpolate}),Promise.resolve(!0)},cancelConnection:()=>{U({connection:{...Mc}})},updateConnection:(w)=>{U({connection:w})},reset:()=>U({...AW()})}},Object.is);function BX({initialNodes:u,initialEdges:f,defaultNodes:l,defaultEdges:r,initialWidth:n,initialHeight:i,initialMinZoom:y,initialMaxZoom:_,initialFitViewOptions:$,fitView:A,nodeOrigin:c,nodeExtent:j,zIndexMode:F,children:U}){let[Q]=yu.useState(()=>HX({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:A,minZoom:y,maxZoom:_,fitViewOptions:$,nodeOrigin:c,nodeExtent:j,zIndexMode:F}));return ru.jsx(gV,{value:Q,children:ru.jsx(ND,{children:U})})}function VX({children:u,nodes:f,edges:l,defaultNodes:r,defaultEdges:n,width:i,height:y,fitView:_,fitViewOptions:$,minZoom:A,maxZoom:c,nodeOrigin:j,nodeExtent:F,zIndexMode:U}){if(yu.useContext(i8))return ru.jsx(ru.Fragment,{children:u});return ru.jsx(BX,{initialNodes:f,initialEdges:l,defaultNodes:r,defaultEdges:n,initialWidth:i,initialHeight:y,fitView:_,initialFitViewOptions:$,initialMinZoom:A,initialMaxZoom:c,nodeOrigin:j,nodeExtent:F,zIndexMode:U,children:u})}var DX={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function XX({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,className:n,nodeTypes:i,edgeTypes:y,onNodeClick:_,onEdgeClick:$,onInit:A,onMove:c,onMoveStart:j,onMoveEnd:F,onConnect:U,onConnectStart:Q,onConnectEnd:L,onClickConnectStart:w,onClickConnectEnd:J,onNodeMouseEnter:N,onNodeMouseMove:q,onNodeMouseLeave:W,onNodeContextMenu:z,onNodeDoubleClick:Z,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onNodesDelete:h,onEdgesDelete:V,onDelete:Y,onSelectionChange:p,onSelectionDragStart:O,onSelectionDrag:m,onSelectionDragStop:X,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:S,onBeforeDelete:k,connectionMode:I,connectionLineType:b=t0.Bezier,connectionLineStyle:o,connectionLineComponent:g,connectionLineContainerStyle:x,deleteKeyCode:fu="Backspace",selectionKeyCode:$u="Shift",selectionOnDrag:tu=!1,selectionMode:ju=p1.Full,panActivationKeyCode:Gu="Space",multiSelectionKeyCode:qu=$y()?"Meta":"Control",zoomActivationKeyCode:P=$y()?"Meta":"Control",snapToGrid:e,snapGrid:uu,onlyRenderVisibleElements:wu=!1,selectNodesOnDrag:s,nodesDraggable:Qu,autoPanOnNodeFocus:zu,nodesConnectable:Ou,nodesFocusable:bu,nodeOrigin:eu=JW,edgesFocusable:pu,edgesReconnectable:Ff,elementsSelectable:Fl=!0,defaultViewport:Tl=_D,minZoom:fl=0.5,maxZoom:of=2,translateExtent:El=ry,preventScrolling:pl=!0,nodeExtent:cu,defaultMarkerColor:Iu="#b1b1b7",zoomOnScroll:Jl=!0,zoomOnPinch:Su=!0,panOnScroll:ll=!1,panOnScrollSpeed:rl=0.5,panOnScrollMode:el=R0.Free,zoomOnDoubleClick:nl=!0,panOnDrag:Zl=!0,onPaneClick:Q0,onPaneMouseEnter:ur,onPaneMouseMove:v0,onPaneMouseLeave:Jf,onPaneScroll:h1,onPaneContextMenu:lu,paneClickDistance:Hu=1,nodeClickDistance:Yu=0,children:gu,onReconnect:_f,onReconnectStart:Pf,onReconnectEnd:rf,onEdgeContextMenu:Ul,onEdgeDoubleClick:Dr,onEdgeMouseEnter:Ly,onEdgeMouseMove:Zf,onEdgeMouseLeave:h$,reconnectRadius:X8=10,onNodesChange:zf,onEdgesChange:l7,noDragClassName:vf="nodrag",noWheelClassName:fr="nowheel",noPanClassName:b1="nopan",fitView:wy,fitViewOptions:v1,connectOnClick:b$,attributionPosition:Ky,proOptions:v$,defaultEdgeOptions:ml,elevateNodesOnSelect:sr=!0,elevateEdgesOnSelect:k$=!1,disableKeyboardA11y:Gy=!1,autoPanOnConnect:zy,autoPanOnNodeDrag:I$,autoPanSpeed:ar,connectionRadius:g$,isValidConnection:pf,onError:Y8,style:s$,id:qr,nodeDragThreshold:sn,connectionDragThreshold:an,viewport:k1,onViewportChange:on,width:Ty,height:r7,colorMode:I1="light",debug:n7,onScroll:Ey,ariaLabelConfig:S8,zIndexMode:a$="basic",...p8},k0){let I0=qr||"1",dn=cD(I1),Pl=yu.useCallback((Zy)=>{Zy.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),Ey?.(Zy)},[Ey]);return ru.jsx("div",{"data-testid":"rf__wrapper",...p8,onScroll:Pl,style:{...s$,...DX},ref:k0,className:Yf(["react-flow",n,dn]),id:qr,role:"application",children:ru.jsxs(VX,{nodes:u,edges:f,width:Ty,height:r7,fitView:wy,fitViewOptions:v1,minZoom:fl,maxZoom:of,nodeOrigin:eu,nodeExtent:cu,zIndexMode:a$,children:[ru.jsx(AD,{nodes:u,edges:f,defaultNodes:l,defaultEdges:r,onConnect:U,onConnectStart:Q,onConnectEnd:L,onClickConnectStart:w,onClickConnectEnd:J,nodesDraggable:Qu,autoPanOnNodeFocus:zu,nodesConnectable:Ou,nodesFocusable:bu,edgesFocusable:pu,edgesReconnectable:Ff,elementsSelectable:Fl,elevateNodesOnSelect:sr,elevateEdgesOnSelect:k$,minZoom:fl,maxZoom:of,nodeExtent:cu,onNodesChange:zf,onEdgesChange:l7,snapToGrid:e,snapGrid:uu,connectionMode:I,translateExtent:El,connectOnClick:b$,defaultEdgeOptions:ml,fitView:wy,fitViewOptions:v1,onNodesDelete:h,onEdgesDelete:V,onDelete:Y,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onSelectionDrag:m,onSelectionDragStart:O,onSelectionDragStop:X,onMove:c,onMoveStart:j,onMoveEnd:F,noPanClassName:b1,nodeOrigin:eu,rfId:I0,autoPanOnConnect:zy,autoPanOnNodeDrag:I$,autoPanSpeed:ar,onError:Y8,connectionRadius:g$,isValidConnection:pf,selectNodesOnDrag:s,nodeDragThreshold:sn,connectionDragThreshold:an,onBeforeDelete:k,debug:n7,ariaLabelConfig:S8,zIndexMode:a$}),ru.jsx(OX,{onInit:A,onNodeClick:_,onEdgeClick:$,onNodeMouseEnter:N,onNodeMouseMove:q,onNodeMouseLeave:W,onNodeContextMenu:z,onNodeDoubleClick:Z,nodeTypes:i,edgeTypes:y,connectionLineType:b,connectionLineStyle:o,connectionLineComponent:g,connectionLineContainerStyle:x,selectionKeyCode:$u,selectionOnDrag:tu,selectionMode:ju,deleteKeyCode:fu,multiSelectionKeyCode:qu,panActivationKeyCode:Gu,zoomActivationKeyCode:P,onlyRenderVisibleElements:wu,defaultViewport:Tl,translateExtent:El,minZoom:fl,maxZoom:of,preventScrolling:pl,zoomOnScroll:Jl,zoomOnPinch:Su,zoomOnDoubleClick:nl,panOnScroll:ll,panOnScrollSpeed:rl,panOnScrollMode:el,panOnDrag:Zl,onPaneClick:Q0,onPaneMouseEnter:ur,onPaneMouseMove:v0,onPaneMouseLeave:Jf,onPaneScroll:h1,onPaneContextMenu:lu,paneClickDistance:Hu,nodeClickDistance:Yu,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:S,onReconnect:_f,onReconnectStart:Pf,onReconnectEnd:rf,onEdgeContextMenu:Ul,onEdgeDoubleClick:Dr,onEdgeMouseEnter:Ly,onEdgeMouseMove:Zf,onEdgeMouseLeave:h$,reconnectRadius:X8,defaultMarkerColor:Iu,noDragClassName:vf,noWheelClassName:fr,noPanClassName:b1,rfId:I0,disableKeyboardA11y:Gy,nodeExtent:cu,viewport:k1,onViewportChange:on}),ru.jsx(yD,{onSelectionChange:p}),gu,ru.jsx(fD,{proOptions:v$,position:Ky}),ru.jsx(uD,{rfId:I0,disableKeyboardA11y:Gy})]})})}var CW=QW(XX);var Fb=Fr.error014();function YX({dimensions:u,lineWidth:f,variant:l,className:r}){return ru.jsx("path",{strokeWidth:f,d:`M${u[0]/2} 0 V${u[1]} M0 ${u[1]/2} H${u[0]}`,className:Yf(["react-flow__background-pattern",l,r])})}function SX({radius:u,className:f}){return ru.jsx("circle",{cx:u,cy:u,r:u,className:Yf(["react-flow__background-pattern","dots",f])})}var Pn;(function(u){u.Lines="lines",u.Dots="dots",u.Cross="cross"})(Pn||(Pn={}));var pX={[Pn.Dots]:1,[Pn.Lines]:1,[Pn.Cross]:6},mX=(u)=>({transform:u.transform,patternId:`pattern-${u.rfId}`});function RW({id:u,variant:f=Pn.Dots,gap:l=20,size:r,lineWidth:n=1,offset:i=0,color:y,bgColor:_,style:$,className:A,patternClassName:c}){let j=yu.useRef(null),{transform:F,patternId:U}=ff(mX,Gf),Q=r||pX[f],L=f===Pn.Dots,w=f===Pn.Cross,J=Array.isArray(l)?l:[l,l],N=[J[0]*F[2]||1,J[1]*F[2]||1],q=Q*F[2],W=Array.isArray(i)?i:[i,i],z=w?[q,q]:N,Z=[W[0]*F[2]||1+z[0]/2,W[1]*F[2]||1+z[1]/2],H=`${U}${u?u:""}`;return ru.jsxs("svg",{className:Yf(["react-flow__background",A]),style:{...$,..._8,"--xy-background-color-props":_,"--xy-background-pattern-color-props":y},ref:j,"data-testid":"rf__background",children:[ru.jsx("pattern",{id:H,x:F[0]%N[0],y:F[1]%N[1],width:N[0],height:N[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${Z[0]},-${Z[1]})`,children:L?ru.jsx(SX,{radius:q/2,className:c}):ru.jsx(YX,{dimensions:z,lineWidth:n,variant:f,className:c})}),ru.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${H})`})]})}RW.displayName="Background";var xW=yu.memo(RW);function PX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:ru.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function MX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:ru.jsx("path",{d:"M0 0h32v4.2H0z"})})}function CX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:ru.jsx("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"})})}function RX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:ru.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"})})}function xX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:ru.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"})})}function r8({children:u,className:f,...l}){return ru.jsx("button",{type:"button",className:Yf(["react-flow__controls-button",f]),...l,children:u})}var hX=(u)=>({isInteractive:u.nodesDraggable||u.nodesConnectable||u.elementsSelectable,minZoomReached:u.transform[2]<=u.minZoom,maxZoomReached:u.transform[2]>=u.maxZoom,ariaLabelConfig:u.ariaLabelConfig});function hW({style:u,showZoom:f=!0,showFitView:l=!0,showInteractive:r=!0,fitViewOptions:n,onZoomIn:i,onZoomOut:y,onFitView:_,onInteractiveChange:$,className:A,children:c,position:j="bottom-left",orientation:F="vertical","aria-label":U}){let Q=Ef(),{isInteractive:L,minZoomReached:w,maxZoomReached:J,ariaLabelConfig:N}=ff(hX,Gf),{zoomIn:q,zoomOut:W,fitView:z}=F9(),Z=()=>{q(),i?.()},H=()=>{W(),y?.()},E=()=>{z(n),_?.()},D=()=>{Q.setState({nodesDraggable:!L,nodesConnectable:!L,elementsSelectable:!L}),$?.(!L)};return ru.jsxs(y8,{className:Yf(["react-flow__controls",F==="horizontal"?"horizontal":"vertical",A]),position:j,style:u,"data-testid":"rf__controls","aria-label":U??N["controls.ariaLabel"],children:[f&&ru.jsxs(ru.Fragment,{children:[ru.jsx(r8,{onClick:Z,className:"react-flow__controls-zoomin",title:N["controls.zoomIn.ariaLabel"],"aria-label":N["controls.zoomIn.ariaLabel"],disabled:J,children:ru.jsx(PX,{})}),ru.jsx(r8,{onClick:H,className:"react-flow__controls-zoomout",title:N["controls.zoomOut.ariaLabel"],"aria-label":N["controls.zoomOut.ariaLabel"],disabled:w,children:ru.jsx(MX,{})})]}),l&&ru.jsx(r8,{className:"react-flow__controls-fitview",onClick:E,title:N["controls.fitView.ariaLabel"],"aria-label":N["controls.fitView.ariaLabel"],children:ru.jsx(CX,{})}),r&&ru.jsx(r8,{className:"react-flow__controls-interactive",onClick:D,title:N["controls.interactive.ariaLabel"],"aria-label":N["controls.interactive.ariaLabel"],children:L?ru.jsx(xX,{}):ru.jsx(RX,{})}),c]})}hW.displayName="Controls";var bW=yu.memo(hW);function bX({id:u,x:f,y:l,width:r,height:n,style:i,color:y,strokeColor:_,strokeWidth:$,className:A,borderRadius:c,shapeRendering:j,selected:F,onClick:U}){let{background:Q,backgroundColor:L}=i||{},w=y||Q||L;return ru.jsx("rect",{className:Yf(["react-flow__minimap-node",{selected:F},A]),x:f,y:l,rx:c,ry:c,width:r,height:n,style:{fill:w,stroke:_,strokeWidth:$},shapeRendering:j,onClick:U?(J)=>U(J,u):void 0})}var vX=yu.memo(bX),kX=(u)=>u.nodes.map((f)=>f.id),A9=(u)=>u instanceof Function?u:()=>u;function IX({nodeStrokeColor:u,nodeColor:f,nodeClassName:l="",nodeBorderRadius:r=5,nodeStrokeWidth:n,nodeComponent:i=vX,onClick:y}){let _=ff(kX,Gf),$=A9(f),A=A9(u),c=A9(l),j=typeof window>"u"||!!window.chrome?"crispEdges":"geometricPrecision";return ru.jsx(ru.Fragment,{children:_.map((F)=>ru.jsx(sX,{id:F,nodeColorFunc:$,nodeStrokeColorFunc:A,nodeClassNameFunc:c,nodeBorderRadius:r,nodeStrokeWidth:n,NodeComponent:i,onClick:y,shapeRendering:j},F))})}function gX({id:u,nodeColorFunc:f,nodeStrokeColorFunc:l,nodeClassNameFunc:r,nodeBorderRadius:n,nodeStrokeWidth:i,shapeRendering:y,NodeComponent:_,onClick:$}){let{node:A,x:c,y:j,width:F,height:U}=ff((Q)=>{let L=Q.nodeLookup.get(u);if(!L)return{node:void 0,x:0,y:0,width:0,height:0};let w=L.internals.userNode,{x:J,y:N}=L.internals.positionAbsolute,{width:q,height:W}=A0(w);return{node:w,x:J,y:N,width:q,height:W}},Gf);if(!A||A.hidden||!gc(A))return null;return ru.jsx(_,{x:c,y:j,width:F,height:U,style:A.style,selected:!!A.selected,className:r(A),color:f(A),borderRadius:n,strokeColor:l(A),strokeWidth:i,shapeRendering:y,onClick:$,id:A.id})}var sX=yu.memo(gX),aX=yu.memo(IX),oX=200,dX=150,eX=(u)=>!u.hidden,uY=(u)=>{let f={x:-u.transform[0]/u.transform[2],y:-u.transform[1]/u.transform[2],width:u.width/u.transform[2],height:u.height/u.transform[2]};return{viewBB:f,boundingRect:u.nodeLookup.size>0?vc(ny(u.nodeLookup,{filter:eX}),f):f,rfId:u.rfId,panZoom:u.panZoom,translateExtent:u.translateExtent,flowWidth:u.width,flowHeight:u.height,ariaLabelConfig:u.ariaLabelConfig}},fY="react-flow__minimap-desc";function vW({style:u,className:f,nodeStrokeColor:l,nodeColor:r,nodeClassName:n="",nodeBorderRadius:i=5,nodeStrokeWidth:y,nodeComponent:_,bgColor:$,maskColor:A,maskStrokeColor:c,maskStrokeWidth:j,position:F="bottom-right",onClick:U,onNodeClick:Q,pannable:L=!1,zoomable:w=!1,ariaLabel:J,inversePan:N,zoomStep:q=1,offsetScale:W=5}){let z=Ef(),Z=yu.useRef(null),{boundingRect:H,viewBB:E,rfId:D,panZoom:h,translateExtent:V,flowWidth:Y,flowHeight:p,ariaLabelConfig:O}=ff(uY,Gf),m=u?.width??oX,X=u?.height??dX,v=H.width/m,T=H.height/X,S=Math.max(v,T),k=S*m,I=S*X,b=W*S,o=H.x-(k-H.width)/2-b,g=H.y-(I-H.height)/2-b,x=k+b*2,fu=I+b*2,$u=`${fY}-${D}`,tu=yu.useRef(0),ju=yu.useRef();tu.current=S,yu.useEffect(()=>{if(Z.current&&h)return ju.current=KN({domNode:Z.current,panZoom:h,getTransform:()=>z.getState().transform,getViewScale:()=>tu.current}),()=>{ju.current?.destroy()}},[h]),yu.useEffect(()=>{ju.current?.update({translateExtent:V,width:Y,height:p,inversePan:N,pannable:L,zoomStep:q,zoomable:w})},[L,w,N,q,V,Y,p]);let Gu=U?(e)=>{let[uu,wu]=ju.current?.pointer(e)||[0,0];U(e,{x:uu,y:wu})}:void 0,qu=Q?yu.useCallback((e,uu)=>{let wu=z.getState().nodeLookup.get(uu).internals.userNode;Q(e,wu)},[]):void 0,P=J??O["minimap.ariaLabel"];return ru.jsx(y8,{position:F,style:{...u,"--xy-minimap-background-color-props":typeof $==="string"?$:void 0,"--xy-minimap-mask-background-color-props":typeof A==="string"?A:void 0,"--xy-minimap-mask-stroke-color-props":typeof c==="string"?c:void 0,"--xy-minimap-mask-stroke-width-props":typeof j==="number"?j*S:void 0,"--xy-minimap-node-background-color-props":typeof r==="string"?r:void 0,"--xy-minimap-node-stroke-color-props":typeof l==="string"?l:void 0,"--xy-minimap-node-stroke-width-props":typeof y==="number"?y:void 0},className:Yf(["react-flow__minimap",f]),"data-testid":"rf__minimap",children:ru.jsxs("svg",{width:m,height:X,viewBox:`${o} ${g} ${x} ${fu}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":$u,ref:Z,onClick:Gu,children:[P&&ru.jsx("title",{id:$u,children:P}),ru.jsx(aX,{onClick:qu,nodeColor:r,nodeStrokeColor:l,nodeBorderRadius:i,nodeClassName:n,nodeStrokeWidth:y,nodeComponent:_}),ru.jsx("path",{className:"react-flow__minimap-mask",d:`M${o-b},${g-b}h${x+b*2}v${fu+b*2}h${-x-b*2}z + M${E.x},${E.y}h${E.width}v${E.height}h${-E.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}vW.displayName="MiniMap";var Jb=yu.memo(vW),lY=(u)=>(f)=>u?`${Math.max(1/f.transform[2],1)}`:void 0,rY={[mn.Line]:"right",[mn.Handle]:"bottom-right"};function nY({nodeId:u,position:f,variant:l=mn.Handle,className:r,style:n=void 0,children:i,color:y,minWidth:_=10,minHeight:$=10,maxWidth:A=Number.MAX_VALUE,maxHeight:c=Number.MAX_VALUE,keepAspectRatio:j=!1,resizeDirection:F,autoScale:U=!0,shouldResize:Q,onResizeStart:L,onResize:w,onResizeEnd:J}){let N=LW(),q=typeof u==="string"?u:N,W=Ef(),z=yu.useRef(null),Z=l===mn.Handle,H=ff(yu.useCallback(lY(Z&&U),[Z,U]),Gf),E=yu.useRef(null),D=f??rY[l];yu.useEffect(()=>{if(!z.current||!q)return;if(!E.current)E.current=ZN({domNode:z.current,nodeId:q,getStoreItems:()=>{let{nodeLookup:V,transform:Y,snapGrid:p,snapToGrid:O,nodeOrigin:m,domNode:X}=W.getState();return{nodeLookup:V,transform:Y,snapGrid:p,snapToGrid:O,nodeOrigin:m,paneDomNode:X}},onChange:(V,Y)=>{let{triggerNodeChanges:p,nodeLookup:O,parentLookup:m,nodeOrigin:X}=W.getState(),v=[],T={x:V.x,y:V.y},S=O.get(q);if(S&&S.expandParent&&S.parentId){let k=S.origin??X,I=V.width??S.measured.width??0,b=V.height??S.measured.height??0,o={id:S.id,parentId:S.parentId,rect:{width:I,height:b,...sc({x:V.x??S.position.x,y:V.y??S.position.y},{width:I,height:b},S.parentId,O,k)}},g=d6([o],O,m,X);v.push(...g),T.x=V.x?Math.max(k[0]*I,V.x):void 0,T.y=V.y?Math.max(k[1]*b,V.y):void 0}if(T.x!==void 0&&T.y!==void 0){let k={id:q,type:"position",position:{...T}};v.push(k)}if(V.width!==void 0&&V.height!==void 0){let I={id:q,type:"dimensions",resizing:!0,setAttributes:!F?!0:F==="horizontal"?"width":"height",dimensions:{width:V.width,height:V.height}};v.push(I)}for(let k of Y){let I={...k,type:"position"};v.push(I)}p(v)},onEnd:({width:V,height:Y})=>{let p={id:q,type:"dimensions",resizing:!1,dimensions:{width:V,height:Y}};W.getState().triggerNodeChanges([p])}});return E.current.update({controlPosition:D,boundaries:{minWidth:_,minHeight:$,maxWidth:A,maxHeight:c},keepAspectRatio:j,resizeDirection:F,onResizeStart:L,onResize:w,onResizeEnd:J,shouldResize:Q}),()=>{E.current?.destroy()}},[D,_,$,A,c,j,L,w,J,Q]);let h=D.split("-");return ru.jsx("div",{className:Yf(["react-flow__resize-control","nodrag",...h,l,r]),ref:z,style:{...n,scale:H,...y&&{[Z?"backgroundColor":"borderColor"]:y}},children:i})}var Ub=yu.memo(nY);var G=xn.default.createElement,{useEffect:F0}=xn.default,sl=xn.default.useState,Rn=xn.default.useRef,X$=[{id:"in-left",side:"left",position:Lu.Left,style:{top:"50%"}},{id:"in-top-left",side:"top",slot:"left",slotIndex:-1,position:Lu.Top,style:{left:"28%"}},{id:"in-top-mid",side:"top",slot:"mid",slotIndex:0,position:Lu.Top,style:{left:"50%"}},{id:"in-top-right",side:"top",slot:"right",slotIndex:1,position:Lu.Top,style:{left:"72%"}},{id:"in-bottom-left",side:"bottom",slot:"left",slotIndex:-1,position:Lu.Bottom,style:{left:"28%"}},{id:"in-bottom-mid",side:"bottom",slot:"mid",slotIndex:0,position:Lu.Bottom,style:{left:"50%"}},{id:"in-bottom-right",side:"bottom",slot:"right",slotIndex:1,position:Lu.Bottom,style:{left:"72%"}}],B$=[{id:"out-right",position:Lu.Right,style:{top:"50%"}}],kW=["#4eb7a8","#d7a13a","#69aee8","#e0835f","#b7d86b","#d98bd2","#5fc6bf"],Fy=236,Jy=88,IW=15000,iY=10,U9=96,c0=72,Q9=64,gW=12;function $8(){return typeof document>"u"||document.visibilityState!=="hidden"}function sW(u,f){let l=Number.parseFloat(String(u||""));return Number.isFinite(l)?l/100:f}function yY(u,f,l){let r=String(u.side||"");if(r!=="top"&&r!=="bottom")return 0;let n=Number(u.slotIndex||0),i=r==="top"?"in-top-mid":"in-bottom-mid",y=f.get(u.id)||0,_=f.get(i)||0;if(n===0)return _===0?-26:28+y*74;let $=l===0?Math.abs(n)*2:Math.sign(l)===Math.sign(n)?-3:3;if(_>0&&y===0)return-14+$;return 8+y*74+$}function t8(u){let f=u.filter((i,y)=>{let _=u[y-1];return!_||Math.abs(_.x-i.x)>0.5||Math.abs(_.y-i.y)>0.5});if(f.length<2)return"";let l=`M ${f[0].x},${f[0].y}`,r=f[0];for(let i=1;i0.5||Math.abs(F.y-r.y)>0.5)l+=` L ${F.x},${F.y}`;l+=` Q ${_.x},${_.y} ${U.x},${U.y}`,r=U}let n=f[f.length-1];return`${l} L ${n.x},${n.y}`}function FL(u,f,l,r,n,i,y=""){let _=l>=u,$=Math.max(1,Math.abs(l-u)),A=Math.abs(r-f),c=Math.max(34,Math.min(118,$*0.26)),j=Math.min(280,Math.abs(i));if(_&&n===Lu.Left&&j<4&&A<28&&$<420)return`M ${u},${f} C ${u+c},${f} ${l-c},${r} ${l},${r}`;if(_&&n===Lu.Left&&(y==="direct-forward-left"||$<=260&&A<=210)){let J=Math.max(42,Math.min(140,$*0.48)),N=Math.max(-28,Math.min(28,i*0.18));return`M ${u},${f} C ${u+J},${f+N} ${l-J},${r} ${l},${r}`}if(_){let J=u+c;if(n===Lu.Top||n===Lu.Bottom){let W=n===Lu.Top?-1:1,z=r+W*(54+j*0.42);return t8([{x:u,y:f},{x:J,y:f},{x:J+Math.min(120,$*0.18),y:z},{x:l,y:z},{x:l,y:r+W*34},{x:l,y:r}])}let N=l-c,q=(f+r)/2+i;return t8([{x:u,y:f},{x:J,y:f},{x:J+Math.min(110,$*0.16),y:q},{x:N-Math.min(90,$*0.12),y:q},{x:N,y:r},{x:l,y:r}])}let Q=n===Lu.Bottom?1:n===Lu.Top?-1:i>=0?1:-1,L=Math.max(u,l)+92+Math.min(180,j*0.52),w=Q<0?Math.min(f,r)-84-j*0.62:Math.max(f,r)+84+j*0.62;if(n===Lu.Top||n===Lu.Bottom)return t8([{x:u,y:f},{x:u+c,y:f},{x:L,y:w},{x:l,y:w},{x:l,y:r+Q*38},{x:l,y:r}]);return t8([{x:u,y:f},{x:u+c,y:f},{x:L,y:w},{x:l-c,y:w},{x:l-c,y:r},{x:l,y:r}])}function _Y({data:u}){return G("div",{className:"pipeline-flow-node-body"},X$.map((f)=>G(C1,{key:f.id,id:f.id,type:"target",position:f.position,isConnectable:!1,className:`pipeline-flow-handle input ${f.side} slot-${f.slot||"mid"}`,style:f.style})),B$.map((f)=>G(C1,{key:f.id,id:f.id,type:"source",position:f.position,isConnectable:!1,className:"pipeline-flow-handle output right",style:f.style})),u?.label)}function $Y({id:u,sourceX:f,sourceY:l,targetX:r,targetY:n,targetPosition:i,markerEnd:y,markerStart:_,style:$,data:A}){let c=Number(A?.laneOffset||0),j=FL(f,l,r,n,i,c,String(A?.routeMode||""));return G(cy,{id:u,path:j,markerEnd:y,markerStart:_,style:$,interactionWidth:28})}var tY={pipelineCurve:$Y},AY={pipelineNode:_Y};function F8(u){if(!u)return"--";let f=new Date(u);if(Number.isNaN(f.getTime()))return"--";return $f(f)}function Hr(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.round(f/1000);if(l<60)return`${l}s`;if(l<3600)return`${Math.floor(l/60)}m ${l%60}s`;return`${Math.floor(l/3600)}h ${Math.floor(l%3600/60)}m`}function q9(u){let f=Number(u);if(!Number.isFinite(f))return"--";return f.toLocaleString("zh-CN")}function aW(u){let f=Number(u);if(!Number.isFinite(f))return"--";return`${Math.round(Math.max(0,Math.min(1,f))*100)}%`}function Du(u){return typeof u==="object"&&u!==null&&!Array.isArray(u)}function Vu(u){return Array.isArray(u)?u:[]}function ku(u){if(!u)return null;let f=new Date(u);return Number.isNaN(f.getTime())?null:f.getTime()}function Y$(u){return Number.isFinite(Number(u))?new Date(Number(u)).toISOString():""}function m$(...u){for(let f of u){let l=ku(f);if(l!==null)return new Date(l).toISOString()}return""}function D9(...u){let f=u.map(ku).filter((l)=>l!==null);return f.length>0?new Date(Math.max(...f)).toISOString():""}function X9(u){return["succeeded","failed","skipped","cancelled","canceled","completed"].includes(String(u||"").toLowerCase())}function JL(u){let f=qL(u).toLowerCase();return["running","active","in-progress","in_progress"].includes(f)}function oW(u,f="status"){return u.reduce((l,r)=>{let n=String(r?.[f]||"unknown").toLowerCase();return l[n]=(l[n]||0)+1,l},{})}function UL(u){if(!u||typeof u!=="string")return null;try{let f=JSON.parse(u);return Du(f)?f:null}catch{return null}}function N9(u){let f=u.map(UL).filter((i)=>Boolean(i)),l=f.flatMap((i)=>[i.timestamp,i.createdAt,i.updatedAt]).filter(Boolean),r=D9(...l),n=Array.from(new Set(f.map((i)=>String(i.event||i.action||i.type||"")).filter(Boolean))).slice(0,3);return{total:u.length,parsed:f.length,lastAt:r,eventKinds:n}}function J8(u){if(u===null||u===void 0)return"--";if(typeof u==="boolean")return u?"是":"否";if(typeof u==="number")return String(u);if(typeof u==="string")return u.length>80?`${u.slice(0,77)}...`:u;if(Array.isArray(u))return`${u.length} 项`;if(typeof u==="object")return`${Object.keys(u).length} 字段`;return String(u)}function QL(u,f=280){if(u===null||u===void 0)return"";let r=(typeof u==="string"?u:String(u)).replace(/\r\n/gu,` +`).trim();return r.length>f?`${r.slice(0,Math.max(0,f-1))}...`:r}function qL(u){if(typeof u==="string")return u;if(Du(u))return String(u.status||u.state||u.phase||"unknown");return"unknown"}function cY(u){return u.filter((f)=>f&&f.value!==void 0&&f.value!==null&&String(f.value)!=="")}function z9({items:u}){let f=cY(Vu(u));return G("div",{className:"pipeline-kv-grid"},f.map((l)=>G("span",{key:l.label},G("b",null,l.label),G("span",null,l.value))))}function Y9({items:u}){let f=Vu(u).map((l)=>String(l||"")).filter(Boolean);if(f.length===0)return null;return G("div",{className:"pipeline-chip-row"},f.map((l,r)=>G("span",{key:`${r}-${l}`},l)))}function T9(u,f){let l=String(f?.procedureRunId||""),r=Vu(u?.procedureRuns);return r.find((n)=>String(Br(n))===l)||r.at(-1)||null}function jY(u,f){let l=String(f||"");if(!l)return null;return Vu(u?.procedureRuns).find((r)=>Br(r)===l)||null}function W9(u){return Vu(u?.attempts).length}function dW(u){return Vu(u?.attempts).reduce((f,l)=>f+w8(l).length,0)}function w8(u){return Vu(u?.opencodeMessages?.steps).filter(Du)}function NL(u){let f=String(u?.status||"").toLowerCase();if(["error","failed","failure"].includes(f))return"failed";if(["completed","succeeded","success"].includes(f))return"succeeded";if(["running","started","in_progress"].includes(f))return"running";return"unknown"}function FY(u,f){let l=Z9(u.map((i)=>i?.agent)).slice(0,3),r=Z9(u.map((i)=>i?.model)).slice(0,3),n=f.length<=2?f.map((i)=>`session ${i}`):[`sessions ${f.length}`,...f.slice(0,2).map((i)=>`session ${i}`)];return[...l.map((i)=>`agent ${i}`),...r.map((i)=>`model ${i}`),...n]}function V$(u,f=0){return String(u?.messageId||u?.index||"")||`step-${f}`}function JY({steps:u,sessionIds:f,sessionFacts:l,matchedStepKey:r}){let n=Vu(u),i=n.findIndex((w,J)=>V$(w,J)===r),y=i>=0?n[i]:null,_=n.flatMap((w)=>[ku(w?.createdAt),ku(w?.completedAt)]).filter((w)=>w!==null),$=_.length>0?Math.min(..._):null,A=_.length>0?Math.max(..._):null,c=$!==null&&A!==null?Math.max(0,A-$):null,j=n.reduce((w,J)=>w+Vu(J?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool").length,0),F=n.reduce((w,J)=>w+Vu(J?.parts).filter((N)=>["text","reasoning"].includes(String(N?.type||"").toLowerCase())).length,0),U=n.reduce((w,J)=>w+Vu(J?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool"&&NL(N)==="failed").length,0),Q=[`${n.length} steps`,`${f.length} sessions`,`${F} messages`,`${j} tools`,c!==null?`duration ${Hr(c)}`:"",U>0?`${U} failed tools`:""].filter(Boolean),L=y?[`Step ${y?.index??i+1}`,String(y?.role||"role --"),y?.model?`model ${y.model}`:"",y?.finish?`finish ${y.finish}`:"",y?.durationMs!==void 0&&y?.durationMs!==null?`duration ${Hr(y.durationMs)}`:""].filter(Boolean):[];return G("section",{className:"pipeline-trace-timeline","data-testid":"pipeline-step-timeline"},G("div",{className:"pipeline-trace-head"},G("div",null,G("b",null,"OpenCode Trace"),G("span",null,"Trace 使用 Code Queue 统一样式展示完整 agent loop;Pipeline 旧 step/message/tool 卡片样式已废弃。")),G("div",{className:"pipeline-trace-session-head","data-testid":"pipeline-step-timeline-session"},G("span",null,Q.join(" / ")||"Trace"),l.length>0?G(Y9,{items:l}):null)),y?G("div",{className:"pipeline-trace-focus","data-testid":"pipeline-trace-matched-step"},G("span",{className:"codex-output-channel"},"Matched"),G("strong",null,`Gantt selection -> ${L.join(" / ")}`),G("time",null,`${F8(y?.createdAt)} -> ${F8(y?.completedAt)}`)):null,G(pt,{port:MU,input:n,className:"codex-transcript pipeline-trace",testId:"pipeline-opencode-step-trace",emptyText:"暂无 OpenCode Trace 输出",keepRecentToolCalls:3}))}function E9(u){return Vu(u).flatMap((f)=>{if(Du(f))return[f];let l=UL(f);return l?[l]:[]})}function Ir(u){return String(u?.event||u?.action||u?.requestedAction||u?.type||"").toLowerCase()}function jy(u){return m$(u?.timestamp,u?.createdAt,u?.updatedAt,u?.startedAt,u?.finishedAt)}function UY(u){return ku(jy(u))}function K8(u){return String(u?.attempt||u?.id||"")}function Z9(u){let f=new Set,l=[];for(let r of u){let n=String(r||"");if(!n||f.has(n))continue;f.add(n),l.push(n)}return l}function eW(u){switch(String(u||"").toLowerCase()){case"monitor":return"monitor";case"webui":return"webui";case"cli":return"cli";case"system":return"runner";default:return String(u||"--")}}function R1(u){return String(u?.requestedAction||u?.action||"").toLowerCase()}function D$(u){switch(R1(u)){case"guide":return"引导";case"modify":return"修改";case"approve":return"审核通过";case"restart":return"重启";case"redo":return"重做";default:return String(u?.requestedAction||u?.action||"控制")}}function uL(u){switch(Ir(u)){case"initial-prompt-delivered":return"初始 prompt";case"append-prompt-delivered":return"追加 prompt";case"append-prompt-queued":return"追加 prompt 已排队";case"monitor-prompt-delivered":return"Monitor prompt";case"node-long-running-observation":return"长任务观察";case"node-finished":return"节点完成";case"oa-policy-downstream-evaluated":return"OA 下游策略";case"control-command-queued":return`${D$(u)} 已发起`;case"control-command-applied":return`${D$(u)} 已生效`;case"control-command-ignored":return`${D$(u)} 已忽略`;default:return String(u?.event||u?.action||u?.requestedAction||"event")}}function fL(u){return QL(u?.promptPreview||u?.reasonPreview||u?.prompt||u?.reason||"",240)}function QY(u){let f=String(u?.prompt||""),l=String(u?.reason||u?.restartReason||""),r=f?"":String(u?.promptPreview||""),n=l?"":String(u?.reasonPreview||"");return[f||r?{label:f?"prompt":"prompt preview",value:f||r}:null,l||n?{label:l?"reason":"reason preview",value:l||n}:null,Vu(u?.resetNodeIds).length>0?{label:"reset nodes",value:Vu(u.resetNodeIds).join(", ")}:null,Vu(u?.runningResetNodeIds).length>0?{label:"interrupted running nodes",value:Vu(u.runningResetNodeIds).join(", ")}:null,Vu(u?.interruptedProcedureRunIds).length>0?{label:"interrupted procedures",value:Vu(u.interruptedProcedureRunIds).join(", ")}:null,u?.interruptedProcedureRunId?{label:"interrupted procedure",value:String(u.interruptedProcedureRunId)}:null].filter(Boolean)}function L9(u){let f=w8(u),l=f.map(($)=>ku($?.createdAt)).filter(($)=>$!==null),r=f.map(($)=>ku($?.completedAt)??ku($?.createdAt)).filter(($)=>$!==null),n=E9(u?.controlEventRecords).map(($)=>UY($)).filter(($)=>$!==null),i=Vu(u?.assistantOutputs).map(($)=>ku($?.updatedAt)).filter(($)=>$!==null),y=l[0]??n[0]??i[0]??null,_=r.at(-1)??n.at(-1)??i.at(-1)??y;return{startMs:y,endMs:_}}function qY(u,f,l,r,n=""){let i=Vu(u?.procedureRuns).filter((_)=>G8(_,f)===l);if(i.length===0)return null;if(n){let _=i.find(($)=>Br($)===n);if(_)return _}if(r===null)return i.at(-1)||null;let y=i.find((_)=>{let $=ku(A8(_,u)),A=ku(c8(_,u))??$;return $!==null&&A!==null&&r>=$-1000&&r<=A+1000});if(y)return y;return i.slice().sort((_,$)=>{let A=ku(A8(_,u))??r,c=ku(c8(_,u))??A,j=ku(A8($,u))??r,F=ku(c8($,u))??j,U=Math.min(Math.abs(A-r),Math.abs(c-r)),Q=Math.min(Math.abs(j-r),Math.abs(F-r));return U-Q})[0]||null}function WL(u,f){let l=Vu(u?.attempts).filter(Du);if(l.length===0)return null;let r=String(f?.attempt||"");if(r){let y=l.find((_)=>K8(_)===r);if(y)return y}let n=Number.isFinite(Number(f?.ms))?Number(f.ms):null;if(n===null)return l.at(-1)||null;let i=l.find((y)=>{let _=L9(y);return Number.isFinite(_.startMs)&&Number.isFinite(_.endMs)&&n>=Number(_.startMs)-1000&&n<=Number(_.endMs)+1000});if(i)return i;return l.slice().sort((y,_)=>{let $=L9(y),A=L9(_),c=Math.min(Math.abs(Number($.startMs??n)-n),Math.abs(Number($.endMs??n)-n)),j=Math.min(Math.abs(Number(A.startMs??n)-n),Math.abs(Number(A.endMs??n)-n));return c-j})[0]||l.at(-1)||null}function LL(u,f){let l=w8(u);if(l.length===0)return{step:null,stepIndex:-1,stepKey:""};if(f===null){let i=l[0];return{step:i,stepIndex:0,stepKey:V$(i,0)}}for(let i=0;i=_-1000&&f<=$+1000)return{step:y,stepIndex:i,stepKey:V$(y,i)}}let r=l.findIndex((i)=>{let y=ku(i?.createdAt)??ku(i?.completedAt);return y!==null&&y>=f});if(r>=0){let i=l[r];return{step:i,stepIndex:r,stepKey:V$(i,r)}}let n=Math.max(0,l.length-1);return{step:l[n],stepIndex:n,stepKey:V$(l[n],n)}}function NY(u,f){let l=String(f?.runId||u?.runId||"");if(String(f?.mode||"")==="interval"){let A=f?.interval||{},c=T9(u,A)||A.raw||{};return{mode:"interval",runId:l,interval:A,marker:null,nodeId:String(A?.nodeId||G8(c,l)||""),procedure:c,attempt:null,matchedStep:null,matchedStepIndex:-1,matchedStepKey:""}}let r=Du(f?.marker)?f.marker:{},n=Number.isFinite(Number(r?.ms))?Number(r.ms):null,i=String(r?.nodeId||""),y=i?qY(u,l,i,n,String(r?.procedureRunId||"")):null,_=y?WL(y,r):null,$=_?LL(_,n):{step:null,stepIndex:-1,stepKey:""};return{mode:"event",runId:l,interval:null,marker:r,nodeId:i,procedure:y,attempt:_,matchedStep:$.step,matchedStepIndex:$.stepIndex,matchedStepKey:$.stepKey}}function WY({procedure:u,matchedStepKey:f="",matchedAttemptId:l=""}){let r=Vu(u?.attempts);if(r.length===0)return G(Ur,{title:"暂无 attempt 详情",text:"当前 procedure 还没有可展示的 attempt / OpenCode Trace;若刚点击甘特线,请等待 node 详情抓取完成。"});return r.map((n,i)=>{let y=n?.opencodeMessages||{},_=w8(n),$=Vu(y.sessionIds).map((F)=>String(F)).filter(Boolean),A=FY(_,$),c=K8(n)||`attempt-${i+1}`,j=_.reduce((F,U)=>F+Vu(U?.parts).filter((Q)=>String(Q?.type||"").toLowerCase()==="tool"&&NL(Q)==="failed").length,0);return G("article",{key:c,className:`pipeline-attempt-card ${l===c?"matched":""}`},G("div",{className:"pipeline-attempt-head"},G("div",null,G("strong",null,c),G("span",null,y.source||"opencode")),G("div",{className:"pipeline-attempt-badges"},G("span",null,`${_.length} steps`),G("span",null,`${y.toolCallCount??"--"} tools`),j>0?G("span",{className:"danger"},`${j} failed`):null)),G(z9,{items:[{label:"messages",value:y.messageCount??"--"},{label:"steps",value:y.stepCount??"--"},{label:"tools",value:y.toolCallCount??"--"},{label:"updated",value:Nu(y.updatedAt)},{label:"sessions",value:$.join(", ")||"--"}]}),_.length===0?G("p",{className:"muted paragraph"},"当前 attempt 尚未返回 OpenCode Trace;请确认 D601 pipeline-control 已重建并重新抓取。"):G(JY,{steps:_,sessionIds:$,sessionFacts:A,matchedStepKey:f}))})}function w9(u,f){return`${u}::${f}`}function U8(u,f,l){if(!Du(u))return null;return String(u.runId||"")===f&&String(u.nodeId||"")===l?u:null}function LY(u,f){let l=Du(u)?u:{};if(!Du(f))return l;let r=Vu(f.attempts),n=Vu(l.attempts);return{...l,...f,attempts:r.length>0?r:n}}function wY(u,f,l,r){if(!U8(f,l,r))return u;let n=Vu(f.procedureRuns),i=Du(u)?u:{};return{...i,...f,controlEvents:Vu(f.controlEvents).length>0?f.controlEvents:i.controlEvents,procedureRuns:n.length>0?n:i.procedureRuns}}function KY({selection:u,runDetails:f,nodeDetails:l,nodeDetailsState:r,onRaw:n,onCollapse:i}){if(!u?.mode)return G("aside",{className:"pipeline-gantt-detail-panel empty","data-testid":"pipeline-gantt-detail-panel"},G("div",{className:"pipeline-gantt-detail-head"},G("div",null,G("span",{className:"panel-eyebrow"},"Gantt Detail"),G(nf,{title:"未选择元素",level:3})),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起")),G(Ur,{title:"选择一条执行线或一个控制点",text:"点击甘特图中的 node 执行线、prompt 点或控制点,在这里查看结构化过程和 OpenCode step。"}));let y=String(u?.runId||""),_=String(u?.interval?.nodeId||u?.marker?.nodeId||""),$=f?.runId===y?f.details:null,A=U8(l,y,_),c=String(r?.runId||"")===y&&String(r?.nodeId||"")===_,j=wY($,A,y,_),F=(String(f?.runId||"")!==y||Boolean(f?.loading))&&!j,U=String(f?.runId||"")===y?String(f?.error||""):"",Q=c?String(r?.error||""):"",L=j?NY(j,u):null,w=L?.interval||u?.interval||null,J=L?.marker||u?.marker||null,N=String(w?.procedureRunId||J?.procedureRunId||""),q=A?jY(A,N)||T9(A,w||{procedureRunId:N}):null,W=L?.procedure||(j?T9(j,w||{procedureRunId:N}):null)||w?.raw||{};if(q&&(W9(W)===0||dW(q)>=dW(W)))W=LY(W,q);let z=L?.attempt||null,Z=String(L?.matchedStepKey||"");if(!z&&J&&W9(W)>0)z=WL(W,J),Z=String(LL(z,Number.isFinite(Number(J?.ms))?Number(J.ms):null).stepKey||"");let H=K8(z),E=W9(W)>0,D=c&&Boolean(r?.loading)&&!E,h=Boolean(F||D),V=[E?"":U,Q].filter(Boolean).join(" / "),Y=c&&r?.fetchedAt?r.fetchedAt:f?.fetchedAt,p=qL(W?.status||w?.status||J?.status||J?.event),O=u?.mode==="event"?J?.label||uL(J?.raw||J)||"event":L?.nodeId||w?.nodeId||"node",m=J?QY(J?.raw||J):[],X=J?[Ir(J?.raw||J)?`event ${Ir(J?.raw||J)}`:"",J?.promptEvent?`prompt ${J.promptEvent}`:"",J?.action?`action ${J.action}`:"",J?.sourceKind?`source ${eW(J.sourceKind)}`:"",J?.sourceNodeId?`from ${J.sourceNodeId}`:"",J?.targetNodeId?`to ${J.targetNodeId}`:"",J?.snapReason?`draw ${J.snapReason}`:""].filter(Boolean):[];return G("aside",{className:"pipeline-gantt-detail-panel","data-testid":"pipeline-gantt-detail-panel"},G("div",{className:"pipeline-gantt-detail-head"},G("div",null,G("span",{className:"panel-eyebrow"},u?.mode==="event"?"Gantt Event Detail":"Gantt Line Detail"),G(nf,{title:O,level:3,loading:h})),G("div",{className:"pipeline-gantt-detail-head-actions"},G(hn,{status:p},p),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起"))),J?G("article",{className:"pipeline-event-card"},G("div",{className:"pipeline-event-card-head"},G("strong",null,J?.label||uL(J?.raw||J)),G(Y9,{items:X})),G(z9,{items:[{label:"event time",value:Nu(J?.timestampIso||J?.timestamp||"--")},J?.snapped?{label:"drawn time",value:Nu(J?.renderedTimestampIso||J?.ms)}:null,{label:"node",value:J?.nodeId||"--"},{label:"procedure",value:J?.procedureRunId||Br(W)||"--"},{label:"attempt",value:J?.attempt||H||"--"},{label:"source kind",value:J?.sourceKind?eW(J.sourceKind):"--"},{label:"source node",value:J?.sourceNodeId||"--"},{label:"target node",value:J?.targetNodeId||"--"},{label:"command",value:J?.commandId||J?.eventId||"--"},J?.snapReason?{label:"placement",value:J.snapReason}:null]}),m.length>0?G("div",{className:"pipeline-event-blocks"},m.map((v,T)=>G("section",{key:`${v.label}-${T}`,className:"pipeline-event-text-block"},G("b",null,v.label),G("p",null,v.value)))):null,fL(J?.raw||J)?G("p",{className:"pipeline-text-preview"},fL(J?.raw||J)):null):null,G(z9,{items:[{label:"epoch",value:y||w?.runId||"--"},{label:"node",value:L?.nodeId||w?.nodeId||J?.nodeId||"--"},{label:"procedure",value:w?.procedureRunId||J?.procedureRunId||Br(W)||"--"},{label:"started",value:Nu(w?.startedAt||W?.startedAt)},{label:"finished",value:Nu(w?.finishedAt||W?.finishedAt)},{label:"duration",value:Hr(w?.durationMs||W?.durationMs)},{label:"fetched",value:Y?$f(Y):"--"},L?.matchedStep?{label:"matched step",value:`Step ${L.matchedStep.index??L.matchedStepIndex+1}`}:null]}),G(yf,{error:V}),G("div",{className:"pipeline-gantt-detail-actions"},G(gr,{title:`Procedure ${w?.procedureRunId||J?.procedureRunId||L?.nodeId||"node"}`,data:W,onOpen:n,testId:"raw-pipeline-gantt-procedure"}),J?G(gr,{title:`Pipeline event ${J?.id||J?.commandId||J?.eventId||L?.nodeId||"event"}`,data:J?.raw||J,onOpen:n,testId:"raw-pipeline-gantt-event"}):null,j?G(gr,{title:`Pipeline run ${y||"--"}`,data:j,onOpen:n,testId:"raw-pipeline-gantt-node-details"}):null),!h&&!Br(W)&&!J?G(Ur,{title:"暂无过程详情",text:"当前选择还没有可匹配的 procedure 运行记录。"}):null,!h&&Br(W)?G(WY,{procedure:W,matchedStepKey:Z,matchedAttemptId:H}):null)}function GY({value:u}){let l=String(u||"--").split(/([_-])/u);return G(xn.default.Fragment,null,l.map((r,n)=>r==="-"||r==="_"?G(xn.default.Fragment,{key:n},r,G("wbr",null)):G(xn.default.Fragment,{key:n},r)))}async function Mn(u,f={}){return Eu(u,{invalidJsonPrefix:"Pipeline 返回了无效 JSON",...f})}function hn({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return G("span",{className:`status-badge ${l}`},f||u||"unknown")}function Sl({label:u,value:f,hint:l,tone:r}){return G("article",{className:`metric-card ${r||""}`},G("div",{className:"metric-label"},u),G("div",{className:"metric-value"},f),G("div",{className:"metric-hint"},l))}function j0({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return G("section",{className:`panel ${n||""}`},G("div",{className:"panel-head"},G("div",null,f?G("p",{className:"panel-eyebrow"},f):null,G(nf,{title:u,loading:i})),l?G("div",{className:"panel-actions"},l):null),G("div",{className:"panel-body"},r))}function gr({title:u,data:f,onOpen:l,testId:r}){return G("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function Or({title:u,subtitle:f,facts:l,data:r,onRaw:n,testId:i}){let y=Vu(l).map((_)=>String(_||"")).filter(Boolean);return G("article",{className:"pipeline-evidence-row"},G("div",{className:"pipeline-evidence-main"},G("strong",null,u),f?G("span",null,f):null),G("div",{className:"pipeline-evidence-facts"},y.map((_,$)=>G("span",{key:`${$}-${_.slice(0,16)}`},_))),r!==void 0?G(gr,{title:u,data:r,onOpen:n,testId:i}):null)}function Ur({title:u,text:f}){return G("div",{className:"empty-state"},G("strong",null,u),G("span",null,f))}function zY(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function TY(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function EY(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function ZY(u){return{components:Array.isArray(u?.registry?.components)?u.registry.components:[],pipelines:Array.isArray(u?.pipelines)?u.pipelines:[],runs:Array.isArray(u?.runs)?u.runs:[]}}function lL(u,f,l){let r=u?._unidesk?.arrayLimits?.[f],n=Number(r?.originalLength);return Number.isFinite(n)?n:l}function wL(u){if(!u||typeof u!=="object"||Array.isArray(u))return"--";return`${u.componentClass||"--"}/${u.id||"--"}`}function Q8(u){if(!u||typeof u!=="object"||Array.isArray(u))return"";let f=String(u.componentClass||"").trim(),l=String(u.id||"").trim();return f&&l?`${f}/${l}`:""}function S9(u){return u?.config&&typeof u.config==="object"&&!Array.isArray(u.config)?u.config:{}}function KL(u){let f=S9(u),l=Array.isArray(f.nodes)?f.nodes:Array.isArray(u?.nodes)?u.nodes:[],r=new Map;for(let y of l){let _=String(y?.id||y?.nodeId||"");if(_)r.set(_,{...y,id:_})}let n=p9(u),i=(y)=>{if(y&&!r.has(y))r.set(y,{id:y})};for(let y of m9(u))S$(y).forEach(i);for(let y of n)i(String(y?.from||y?.source||"")),i(String(y?.to||y?.target||""));return Array.from(r.values())}function p9(u){let f=S9(u);return Array.isArray(f.edges)?f.edges:Array.isArray(u?.edges)?u.edges:[]}function m9(u){let f=S9(u);return Array.isArray(f.topologicalBatches)?f.topologicalBatches:Array.isArray(u?.topologicalBatches)?u.topologicalBatches:[]}function OY(u){let f=new Map;for(let l of u){let r=Q8(l);if(r)f.set(r,l);let n=Array.isArray(l?.refs)?l.refs:[];for(let i of n){let y=Q8(i);if(y)f.set(y,l)}}return f}function rL(u,f){let l=f.get(Q8(u?.componentRef));if(l)return l;let r=Q8({componentClass:u?.kind,id:u?.id});return r?f.get(r)||null:null}function nL(u,f){let l=GL(u,f);return String(l?.status||"pending")}function GL(u,f){return(Array.isArray(u?.nodes)?u.nodes:[]).find((r)=>r?.nodeId===f||r?.id===f)||null}function HY(u){return u.reduce((f,l)=>{let r=String(l?.status||"unknown").toLowerCase();return f[r]=(f[r]||0)+1,f},{})}function BY(u){if(Array.isArray(u?.scorers))return u.scorers.filter(Du);if(Array.isArray(u?.summary?.scorers))return u.summary.scorers.filter(Du);if(Array.isArray(u?.artifact?.summary?.scorers))return u.artifact.summary.scorers.filter(Du);return[]}function VY(u){if(Du(u?.run))return u.run;if(Du(u?.runSummary))return u.runSummary;return null}function DY(u,f){if(!Du(u)&&!Du(f))return null;if(!Du(u))return f;if(!Du(f))return u;return{...u,...f,request:Du(u.request)||Du(f.request)?{...Du(u.request)?u.request:{},...Du(f.request)?f.request:{}}:f.request??u.request,artifact:Du(u.artifact)||Du(f.artifact)?{...Du(u.artifact)?u.artifact:{},...Du(f.artifact)?f.artifact:{}}:f.artifact??u.artifact,summary:Du(u.summary)||Du(f.summary)?{...Du(u.summary)?u.summary:{},...Du(f.summary)?f.summary:{}}:f.summary??u.summary}}function q8(u){let f=BY(u),l=f.find((c)=>Du(c?.score))||f[0]||null,r=Du(l?.score)?l.score:{},n=Number(r.passed),i=Number(r.total),y=Number(r.ratio),_=Number.isFinite(y)?y:Number.isFinite(n)&&Number.isFinite(i)&&i>0?n/i:null,$=_===null?null:Math.round(Math.max(0,Math.min(100,_<=1?_*100:_))),A=String(r.text||(Number.isFinite(n)&&Number.isFinite(i)?`${n}/${i}`:""));return{scorer:l,scorers:f,score:r,passed:Number.isFinite(n)?n:null,total:Number.isFinite(i)?i:null,percent:$,text:A}}function O9(u){let f=q8(u);return f.text||(f.scorers.length>0?String(f.scorer?.status||"pending"):"--")}function P9(u){let f=q8(u);if(f.total>0&&f.passed===f.total)return"succeeded";if(f.total>0&&f.passed>0)return"running";if(f.scorers.length>0)return"failed";return"pending"}function XY(u){return Array.isArray(u?.items)?u.items.filter(Du):[]}function YY({run:u}){let f=O9(u);return G("span",{className:`pipeline-score-badge ${P9(u)}`},`score ${f}`)}function SY({run:u,onRaw:f}){let r=q8(u).scorers;if(!u)return G(Ur,{title:"暂无评分",text:"选择一个 epoch 后会显示 scorer 结果。"});if(r.length===0)return G("div",{className:"pipeline-score-empty"},G("strong",null,"评分器等待中"),G("span",null,"DAG 完成后,Pipeline control backend 会把 scorer summary 追加到 run artifact,并通过 UniDesk 显示。"));return G("div",{className:"pipeline-score-board","data-testid":"pipeline-score-board"},r.map((n,i)=>{let y=q8({scorers:[n]}),_=XY(n),$=y.percent??0;return G("article",{key:`${n.scorerId||n.component||i}`,className:`pipeline-score-card ${P9({scorers:[n]})}`},G("div",{className:"pipeline-score-head"},G("div",null,G("span",null,n.scorerId||n.component||"scorer"),G("strong",null,y.text||n.status||"--")),G(hn,{status:n.status||"unknown"},n.status||"unknown")),G("div",{className:"pipeline-score-meter","aria-label":`score ${$}%`},G("span",{style:{width:`${$}%`}})),G("div",{className:"pipeline-score-facts"},G("span",null,`${$}%`),G("span",null,n.component||"--"),G("span",null,n.applicationCheckoutRef||"--")),_.length>0?G("div",{className:"pipeline-score-items"},_.map((A)=>G("span",{key:`${A.id||A.filter}`,className:`pipeline-score-item ${String(A.status||"").toLowerCase()}`,title:`${A.filter||"--"} / ran=${A.ran??"?"}`},G("b",null,A.id||"--"),G("small",null,A.status||"--")))):G("p",{className:"muted paragraph"},"当前 scorer 尚未返回 item 级结果。"),n.error?G("p",{className:"pipeline-score-error"},QL(n.error,360)):null,G("div",{className:"panel-actions inline-actions"},G(gr,{title:`Scorer ${n.scorerId||i}`,data:n,onOpen:f,testId:"raw-pipeline-score"})))}))}function pY(u){let f=u.reduce((l,r)=>{let n=String(r?.componentClass||"unknown");return l[n]=(l[n]||0)+1,l},{});return Object.entries(f).map(([l,r])=>({name:l,count:Number(r)})).sort((l,r)=>r.count-l.count||l.name.localeCompare(r.name))}function S$(u){if(Array.isArray(u))return u.map((f)=>typeof f==="string"?f:String(f?.id||f?.nodeId||"")).filter(Boolean);if(Array.isArray(u?.nodes))return S$(u.nodes);if(Array.isArray(u?.nodeIds))return S$(u.nodeIds);return[]}function mY(u){return Du(u?.instanceInputs?.monitor)?u.instanceInputs.monitor:{}}function zL(u,f){if(String(u?.kind||"").toLowerCase()!=="procedure")return!1;let l=mY(u);if(u?.instanceInputs?.monitorMode===!0||l.enabled===!0)return!0;let r=wL(u?.componentRef);return String(f?.id||f?.config?.id||r||"").toLowerCase().includes("monitor")}function PY(u){return u.filter((f)=>zL(f)).map((f)=>String(f?.id||"")).filter(Boolean)}function MY(u,f){if(f.length===0)return u;let l=new Set(f),r=f.filter((n)=>u.includes(n));if(r.length===0)return u;return[...r,...u.filter((n)=>!l.has(n))]}function CY(u,f){if(f.length===0)return u;let l=new Set(f),r=f.filter((i)=>u.some((y)=>y.includes(i)));if(r.length===0)return u;let n=u.map((i)=>i.filter((y)=>!l.has(y))).filter((i)=>i.length>0);return[r,...n]}function RY(u,f,l){let n=m9(u).map(S$).filter((F)=>F.length>0);if(n.length>0)return n;let i=f.map((F)=>String(F?.id||"")).filter(Boolean),y=new Set(i),_=new Map(i.map((F)=>[F,0])),$=new Map(i.map((F)=>[F,[]]));for(let F of l){let U=String(F?.from||F?.source||""),Q=String(F?.to||F?.target||"");if(!y.has(U)||!y.has(Q))continue;$.get(U)?.push(Q),_.set(Q,(_.get(Q)||0)+1)}let A=new Map,c=i.filter((F)=>(_.get(F)||0)===0);for(let F of c)A.set(F,0);while(c.length>0){let F=c.shift(),U=(A.get(F)||0)+1;for(let Q of $.get(F)||[])if(_.set(Q,Math.max(0,(_.get(Q)||0)-1)),A.set(Q,Math.max(A.get(Q)||0,U)),(_.get(Q)||0)===0)c.push(Q)}i.forEach((F)=>{if(!A.has(F))A.set(F,0)});let j=Math.max(0,...Array.from(A.values()));return Array.from({length:j+1},(F,U)=>i.filter((Q)=>A.get(Q)===U)).filter((F)=>F.length>0)}function xY(u,f,l){let n=m9(u).map(S$).filter((_)=>_.length>0),i=n.length>0?n.flatMap((_)=>_):(()=>{let _=f.map((L)=>String(L?.id||"")).filter(Boolean),$=new Set(_),A=l.filter((L)=>String(L?.edgeType||"").toLowerCase()!=="rework"),c=new Map(_.map((L)=>[L,0])),j=new Map(_.map((L)=>[L,[]]));for(let L of A){let w=String(L?.from||L?.source||""),J=String(L?.to||L?.target||"");if(!$.has(w)||!$.has(J))continue;j.get(w)?.push(J),c.set(J,(c.get(J)||0)+1)}let F=new Map,U=_.filter((L)=>(c.get(L)||0)===0);for(let L of U)F.set(L,0);while(U.length>0){let L=U.shift(),w=(F.get(L)||0)+1;for(let J of j.get(L)||[])if(c.set(J,Math.max(0,(c.get(J)||0)-1)),F.set(J,Math.max(F.get(J)||0,w)),(c.get(J)||0)===0)U.push(J)}_.forEach((L)=>{if(!F.has(L))F.set(L,0)});let Q=Math.max(0,...Array.from(F.values()));return Array.from({length:Q+1},(L,w)=>_.filter((J)=>F.get(J)===w)).flatMap((L)=>L)})(),y=new Set(i);for(let _ of f){let $=String(_?.id||"");if(!$||y.has($))continue;i.push($),y.add($)}return MY(i,PY(f))}function O$(u){return`${u.source}->${u.target}-${u.index}`}function iL(u,f,l){let r=KL(u),n=p9(u),i=OY(l),y=new Map(r.map((p)=>[String(p?.id||""),p])),_=r.filter((p)=>zL(p,rL(p,i))).map((p)=>String(p?.id||"")).filter(Boolean),$=CY(RY(u,r,n),_),A=[],c=new Map,j=330,F=122;$.forEach((p,O)=>{let m=p.length*122;p.forEach((X,v)=>{let T=y.get(X)||{id:X},S=rL(T,i),k=nL(f,X).toLowerCase(),I=String(T.kind||S?.componentClass||"node").toLowerCase(),b=wL(T.componentRef||S),o=String(S?.config?.version||S?.version||""),g=String(S?.config?.description||S?.description||""),x=v*122-Math.floor(m/2);c.set(X,{column:O,row:v,y:x}),A.push({id:X,type:"pipelineNode",position:{x:O*330,y:x},data:{exportLabel:{id:X,kind:I,componentRef:b,componentVersion:o,componentDescription:g,status:k},label:G("div",{className:"flow-node-label"},G("strong",null,X),G("span",null,I),G("code",{title:g||b},o?`${b}@${o}`:b),G(hn,{status:k},k))},className:`pipeline-flow-node ${I} ${k}`})})});let U=n.flatMap((p,O)=>{let m=String(p?.from||p?.source||""),X=String(p?.to||p?.target||"");if(!y.has(m)||!y.has(X))return[];return[{source:m,target:X,index:O,condition:p?.condition,edgeType:p?.edgeType}]}),Q=U.reduce((p,O)=>p.set(O.source,(p.get(O.source)||0)+1),new Map),L=U.reduce((p,O)=>p.set(O.target,(p.get(O.target)||0)+1),new Map),w=U.reduce((p,O)=>{let m=`${O.source}->${O.target}`;return p.set(m,(p.get(m)||0)+1)},new Map),J=new Map,N=new Map,q=new Map,W=new Map,z=new Map,Z=new Map,H=U.reduce((p,O)=>{let m=c.get(O.source),X=c.get(O.target),v=(X?.column||0)-(m?.column||0);if(v<=0||String(O.edgeType||"").toLowerCase()==="rework"||v!==1)return p;let S=`${O.source}->column:${X?.column??""}`,k=p.get(S)||[];return k.push(O),p.set(S,k),p},new Map);for(let p of H.values()){if(p.length<2)continue;p.slice().sort((O,m)=>{let X=c.get(O.target),v=c.get(m.target);return(X?.y||0)-(v?.y||0)||O.index-m.index}).forEach((O,m,X)=>{Z.set(O$(O),{slot:m-(X.length-1)/2,count:X.length})})}[...U].sort((p,O)=>{let m=c.get(p.source),X=c.get(p.target),v=c.get(O.source),T=c.get(O.target),S=Math.abs((X?.column||0)-(m?.column||0))*330+Math.abs((X?.y||0)-(m?.y||0)),k=Math.abs((T?.column||0)-(v?.column||0))*330+Math.abs((T?.y||0)-(v?.y||0));return S-k||p.index-O.index}).forEach((p)=>{let O=c.get(p.source)||{column:0,row:0,y:0},m=c.get(p.target)||{column:0,row:0,y:0},X=m.column-O.column,v=Math.max(0,X),T=X<=0||String(p.edgeType||"").toLowerCase()==="rework",S=O.y-m.y,k=L.get(p.target)||1,I=Z.has(O$(p)),b=!T&&v<=1&&(I||k===1),o=z.get(p.target)||new Map;z.set(p.target,o);let g=X$.slice().sort((x,fu)=>{let $u=(qu)=>{let P=String(qu.side),e=0;if(T){if(P==="left")e+=86;if(P==="top")e+=m.y<=0?-22:12;if(P==="bottom")e+=m.y>=0?-22:12;if(Math.abs(m.y)<12&&P!=="left")e+=p.index%2===0?P==="top"?-6:6:P==="bottom"?-6:6;return e}if(b){if(P==="left")e-=I?72:44;if(P!=="left")e+=I?72:44;return e+Math.abs(S)*0.02}if(P==="left")e+=v<=1?0:24;if(P==="top")e+=S<-36?-18:42;if(P==="bottom")e+=S>36?-18:42;if(v<=1&&Math.abs(S)<=82&&P!=="left")e+=38;if(v>1&&P!=="left")e-=10;return e},tu=O.y-m.y,ju=tu!==0?tu:p.index%2===0?-1:1,Gu=(qu)=>{let P=o.get(qu.id)||0;return $u(qu)+P*64+yY(qu,o,ju)};return Gu(x)-Gu(fu)||String(x.id).localeCompare(String(fu.id))})[0];o.set(g.id,(o.get(g.id)||0)+1),W.set(O$(p),g)});let D=U.map((p)=>{let O=nL(f,p.target).toLowerCase(),m=`${p.source}->${p.target}`,X=J.get(p.source)||0,v=N.get(p.target)||0,T=q.get(m)||0;J.set(p.source,X+1),N.set(p.target,v+1),q.set(m,T+1);let S=X-((Q.get(p.source)||1)-1)/2,k=v-((L.get(p.target)||1)-1)/2,I=T-((w.get(m)||1)-1)/2,b=c.get(p.source),o=c.get(p.target),g=(o?.column||0)-(b?.column||0),x=Math.max(1,Math.abs(g)),fu=g<=0||String(p.edgeType||"").toLowerCase()==="rework",$u=Math.abs((o?.y||0)-(b?.y||0)),tu=Z.get(O$(p)),ju=!fu&&g===1&&(L.get(p.target)||0)>1,Gu=tu?tu.slot:I*2+S+k*0.45,qu=Gu===0?p.index%2===0?-1:1:Math.sign(Gu),P=W.get(O$(p))||X$[1],e=P.side==="top"?-1:P.side==="bottom"?1:qu,uu=fu||x>1||$u>96||Math.abs(Gu)>0.2||P.side!=="left",wu=fu?118+x*18:22+x*16,s=P.side==="left"?0:28,Qu=uu?Math.max(-280,Math.min(280,e*Math.min(180,wu+s+$u*0.22)+Gu*28)):0,zu=Math.max(0,Math.min(B$.length-1,Math.round(S+(B$.length-1)/2))),Ou=B$[zu]||B$[1],bu=O==="succeeded"?"var(--accent-2)":O==="running"?"var(--accent)":O==="failed"?"var(--danger)":"rgba(129, 147, 159, 0.78)",eu=b?.column||0,pu=o?.column||0,Ff=Qu===0?0:Math.sign(Qu),Fl=fu?`feedback:${eu}->${pu}:${Ff}`:tu?`fanout:${eu}->${pu}:${p.source}`:ju?`fanin:${eu}->${pu}:${p.target}`:P.side!=="left"||x>1?`corridor:${eu}->${pu}:${P.side}:${Ff}:${Math.round(Math.abs(Qu)/56)}`:"";return{id:`${p.source}->${p.target}-${p.index}`,source:p.source,target:p.target,sourceHandle:Ou.id,targetHandle:P.id,type:"pipelineCurve",zIndex:12,animated:O==="running",data:{baseEdgeColor:bu,laneOffset:Qu,routeMode:tu&&P.side==="left"?"direct-forward-left":"",targetSide:P.side,isFeedback:fu,overlapGroup:Fl},targetStatus:O}}),h=D.reduce((p,O)=>{let m=String(O.data?.overlapGroup||"");return m?p.set(m,(p.get(m)||0)+1):p},new Map),V=new Map,Y=D.map((p)=>{let O=String(p.targetStatus||"pending"),m={...p};delete m.targetStatus;let X=String(p.data?.overlapGroup||""),v=X?h.get(X)||0:0,T=v>1?V.get(X)||0:-1;if(v>1)V.set(X,T+1);let S=T>=0?kW[T%kW.length]:String(p.data.baseEdgeColor),k={stroke:S};if(p.data.isFeedback)k.strokeDasharray="9 7";return{...m,data:{...p.data,edgeColor:S,overlapSlot:T,overlapCount:v},style:k,markerEnd:{type:Sn.ArrowClosed,color:S},className:`pipeline-flow-edge ${O} ${p.data.isFeedback?"feedback":""} ${T>=0?"overlap-colored":""}`}});return{nodes:A,edges:Y}}function al(u){return String(u??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function yL(u){let f=String(u||"");if(f.includes("--accent-2"))return"#4eb7a8";if(f.includes("--accent"))return"#d7a13a";if(f.includes("--danger"))return"#cf6a54";return f.startsWith("#")?f:"#81939f"}function N8(u){return`arrow-${u.replace(/[^a-zA-Z0-9_-]+/g,"")}`}function TL(u,f="pipeline"){return String(u||f).replace(/[^a-zA-Z0-9_-]+/g,"-").replace(/^-|-$/g,"")||f}function _L(u,f){let l=u.position.x,r=u.position.y,n=X$.find((i)=>i.id===f);if(n?.side==="top")return{x:l+Fy*sW(n.style?.left,0.5),y:r,position:Lu.Top};if(n?.side==="bottom")return{x:l+Fy*sW(n.style?.left,0.5),y:r+Jy,position:Lu.Bottom};return{x:l,y:r+Jy/2,position:Lu.Left}}function hY(u){return{x:u.position.x+Fy,y:u.position.y+Jy/2}}function bY(u,f){let l=Math.min(...u.nodes.map((L)=>L.position.x),0)-220,r=Math.min(...u.nodes.map((L)=>L.position.y),0)-220,n=Math.max(...u.nodes.map((L)=>L.position.x+Fy),1)+220,i=Math.max(...u.nodes.map((L)=>L.position.y+Jy),1)+220,y=Math.ceil(n-l),_=Math.ceil(i-r),$=new Map(u.nodes.map((L)=>[L.id,L])),A=u.edges.map((L)=>yL(L.data?.edgeColor||L.style?.stroke)),j=Array.from(new Set(["#4eb7a8","#d7a13a","#cf6a54","#81939f",...A])).map((L)=>``).join(""),F=u.edges.flatMap((L)=>{let w=$.get(L.source),J=$.get(L.target);if(!w||!J)return[];let N=hY(w),q=_L(J,String(L.targetHandle||"in-left")),W=FL(N.x,N.y,q.x,q.y,q.position,Number(L.data?.laneOffset||0),String(L.data?.routeMode||"")),z=yL(L.data?.edgeColor||L.style?.stroke),Z=L.data?.isFeedback?' stroke-dasharray="9 7"':"";return``}).join(` +`),U=u.nodes.map((L)=>{let w=L.data?.exportLabel||{},J=String(w.status||"pending").toLowerCase(),N=J==="succeeded"?"#4eb7a8":J==="running"?"#d7a13a":J==="failed"?"#cf6a54":"#81939f",q=L.position.x,W=L.position.y,z=X$.map((Z)=>{let H=_L(L,Z.id);if(Z.side==="top"||Z.side==="bottom")return``;return``}).join(` `);return` - + ${z} - - ${sl(w.id||L.id)} - ${sl(w.kind||"node")} - ${sl(w.componentRef||"--")} - ${sl(J)} + + ${al(w.id||L.id)} + ${al(w.kind||"node")} + ${al(w.componentRef||"--")} + ${al(J)} `}).join(` `);return{svg:` ${j} - ${sl(f)} + ${al(f)} ${U}${F} - `,width:y,height:_}}function hY(u){let f=String(u||"").toLowerCase();if(f==="succeeded"||f==="completed")return"#4eb7a8";if(f==="failed")return"#cf6a54";if(jL(f))return"#69aee8";return"#d7a13a"}function bY(u){let f=String(u?.kind||""),l=String(u?.tone||u?.status||"").toLowerCase();if(f==="prompt"&&l==="initial")return"#d7a13a";if(f==="prompt"&&l==="monitor")return"#69aee8";if(f==="prompt")return"#4eb7a8";if(l==="modify")return"#e0b95a";if(l==="approve"||l==="guide"||l==="monitor")return"#4eb7a8";if(l==="restart"||l==="redo")return"#d7a13a";if(l==="ignored")return"#81939f";if(l==="webui")return"#69aee8";if(l==="cli")return"#d7a13a";return"#a7bac5"}function yL(u){let f=String(u?.sourceKind||"").toLowerCase(),l=String(u?.action||"").toLowerCase(),r=String(u?.status||"").toLowerCase();if(l==="observe"||r==="observation"||f==="monitor")return"#4eb7a8";if(f==="webui")return"#69aee8";if(f==="cli")return"#d7a13a";if(r.includes("ignored"))return"#81939f";return"#8aa0ad"}function vY(u,f,l){let r=bY(u),n=String(u?.kind||"");if(n==="control-source")return``;if(n==="control-target"){let y=String(u?.tone||"").toLowerCase()==="approve"?"rgba(78,183,168,0.22)":"#081118";return``}return``}function kY(u){let f=Vu(u.visibleNodeIds).map((T)=>String(T||"")).filter(Boolean),l=Vu(u.intervals).filter(Du),r=Vu(u.markers).filter(Du),n=Vu(u.arrows).filter(Du),i=Vu(u.ticks).filter(Du),y=Du(u.bounds)?u.bounds:{},_=Du(u.backendLayout)?u.backendLayout:null,$=Math.max(240,Math.round(Number(u.chartHeight||360))),A=Math.max(A0,108),c=128,j=24,F=58,U=56,Q=128+Math.max(1,f.length)*A,L=Math.max(760,Q+48),w=114+$+24,J=24,N=58,q=114,W=(T)=>152+T*A,z=(T)=>W(T)+A/2,Z=Vu(u.meta).map((T)=>String(T||"")).filter(Boolean).slice(0,4).join(" · "),H=new Map(r.map((T)=>[String(T.id||""),T])),D=Array.from(new Set(["#4eb7a8","#69aee8","#d7a13a","#cf6a54","#8aa0ad",...n.map(yL)])).map((T)=>``).join(""),h=i.map((T)=>{let S=114+VL(T,y,$,_);return` + `,width:y,height:_}}function vY(u){let f=String(u||"").toLowerCase();if(f==="succeeded"||f==="completed")return"#4eb7a8";if(f==="failed")return"#cf6a54";if(JL(f))return"#69aee8";return"#d7a13a"}function kY(u){let f=String(u?.kind||""),l=String(u?.tone||u?.status||"").toLowerCase();if(f==="prompt"&&l==="initial")return"#d7a13a";if(f==="prompt"&&l==="monitor")return"#69aee8";if(f==="prompt")return"#4eb7a8";if(l==="modify")return"#e0b95a";if(l==="approve"||l==="guide"||l==="monitor")return"#4eb7a8";if(l==="restart"||l==="redo")return"#d7a13a";if(l==="ignored")return"#81939f";if(l==="webui")return"#69aee8";if(l==="cli")return"#d7a13a";return"#a7bac5"}function $L(u){let f=String(u?.sourceKind||"").toLowerCase(),l=String(u?.action||"").toLowerCase(),r=String(u?.status||"").toLowerCase();if(l==="observe"||r==="observation"||f==="monitor")return"#4eb7a8";if(f==="webui")return"#69aee8";if(f==="cli")return"#d7a13a";if(r.includes("ignored"))return"#81939f";return"#8aa0ad"}function IY(u,f,l){let r=kY(u),n=String(u?.kind||"");if(n==="control-source")return``;if(n==="control-target"){let y=String(u?.tone||"").toLowerCase()==="approve"?"rgba(78,183,168,0.22)":"#081118";return``}return``}function gY(u){let f=Vu(u.visibleNodeIds).map((T)=>String(T||"")).filter(Boolean),l=Vu(u.intervals).filter(Du),r=Vu(u.markers).filter(Du),n=Vu(u.arrows).filter(Du),i=Vu(u.ticks).filter(Du),y=Du(u.bounds)?u.bounds:{},_=Du(u.backendLayout)?u.backendLayout:null,$=Math.max(240,Math.round(Number(u.chartHeight||360))),A=Math.max(c0,108),c=128,j=24,F=58,U=56,Q=128+Math.max(1,f.length)*A,L=Math.max(760,Q+48),w=114+$+24,J=24,N=58,q=114,W=(T)=>152+T*A,z=(T)=>W(T)+A/2,Z=Vu(u.meta).map((T)=>String(T||"")).filter(Boolean).slice(0,4).join(" · "),H=new Map(r.map((T)=>[String(T.id||""),T])),D=Array.from(new Set(["#4eb7a8","#69aee8","#d7a13a","#cf6a54","#8aa0ad",...n.map($L)])).map((T)=>``).join(""),h=i.map((T)=>{let S=114+XL(T,y,$,_);return` - ${sl(Nu(T.ms))} - +${sl(Hr(Number(T.offsetMs??Number(T.ms)-Number(y.startMs))))} + ${al(Nu(T.ms))} + +${al(Hr(Number(T.offsetMs??Number(T.ms)-Number(y.startMs))))} `}).join(` `),V=['','TIME',...f.map((T,S)=>{let k=W(S),I=T.length>18?`${T.slice(0,16)}…`:T;return` - ${sl(I)} + ${al(I)} node ${S+1} `})].join(` `),Y=f.map((T,S)=>{return``}).join(` -`),p=l.map((T)=>{let S=f.indexOf(String(T.nodeId||""));if(S<0)return"";let k=114+N8(T,y,$,_),I=Math.max(2,BL(T,y,$,_)),b=hY(T.status),o=z(S)-3.5,s=T.live?``:"",x=I>=28?`${sl(String(T.status||"working"))} - ${sl(Hr(T.durationMs))}`:"";return` +`),p=l.map((T)=>{let S=f.indexOf(String(T.nodeId||""));if(S<0)return"";let k=114+L8(T,y,$,_),I=Math.max(2,DL(T,y,$,_)),b=vY(T.status),o=z(S)-3.5,g=T.live?``:"",x=I>=28?`${al(String(T.status||"working"))} + ${al(Hr(T.durationMs))}`:"";return` - ${s} + ${g} ${x} `}).join(` -`),O=r.map((T)=>{let S=f.indexOf(String(T.nodeId||""));if(S<0)return"";let k=114+Jr(T,y,$,_);return vY(T,z(S),k)}).join(` -`),m=n.map((T)=>{let S=H.get(String(T.targetMarkerId||""));if(!S)return"";let k=H.get(String(T.sourceMarkerId||"")),I=String(k?.nodeId||T.sourceNodeId||""),b=String(S.nodeId||T.targetNodeId||""),o=f.indexOf(I),s=f.indexOf(b);if(o<0||s<0)return"";let x=z(o)-24-128,fu=z(s)-24-128,$u=Jy(_)?Vf(T.sourceY??T.y1)??(k?Jr(k,y,$,_):Jr(S,y,$,_)):k?Jr(k,y,$,_):Jr(S,y,$,_),tu=Jy(_)?Vf(T.targetY??T.y2)??Jr(S,y,$,_):Jr(S,y,$,_),ju=yL(T),Gu=String(T.action||"").toLowerCase()==="observe"?"3 4":"6 5",qu=sl(DL(x,$u,fu,tu));return` - `}).join(` +`),O=r.map((T)=>{let S=f.indexOf(String(T.nodeId||""));if(S<0)return"";let k=114+Jr(T,y,$,_);return IY(T,z(S),k)}).join(` +`),m=n.map((T)=>{let S=H.get(String(T.targetMarkerId||""));if(!S)return"";let k=H.get(String(T.sourceMarkerId||"")),I=String(k?.nodeId||T.sourceNodeId||""),b=String(S.nodeId||T.targetNodeId||""),o=f.indexOf(I),g=f.indexOf(b);if(o<0||g<0)return"";let x=z(o)-24-128,fu=z(g)-24-128,$u=Uy(_)?Vf(T.sourceY??T.y1)??(k?Jr(k,y,$,_):Jr(S,y,$,_)):k?Jr(k,y,$,_):Jr(S,y,$,_),tu=Uy(_)?Vf(T.targetY??T.y2)??Jr(S,y,$,_):Jr(S,y,$,_),ju=$L(T),Gu=String(T.action||"").toLowerCase()==="observe"?"3 4":"6 5",qu=al(YL(x,$u,fu,tu));return` + `}).join(` `),X=f.length===0?'No visible Gantt nodes':"";return{svg:` ${D} - ${sl(u.title||"Pipeline Epoch Gantt")} - ${sl(Z)} + ${al(u.title||"Pipeline Epoch Gantt")} + ${al(Z)} ${V} ${Y} @@ -286,4 +286,4 @@ html,body{width:${r}px!important;min-height:${n}px!important;overflow:hidden!imp ${m} ${O} ${X} - `,width:L,height:w}}function q8(u,f){let l=URL.createObjectURL(u),r=document.createElement("a");r.href=l,r.download=f,r.click(),setTimeout(()=>URL.revokeObjectURL(l),1000)}async function zL(u,f){let l=GL(f,"pipeline"),{svg:r,width:n,height:i}=xY(u,f),y=new Blob([r],{type:"image/svg+xml;charset=utf-8"}),_=URL.createObjectURL(y);try{let $=new Image;await new Promise((F,U)=>{$.onload=()=>F(),$.onerror=()=>U(Error("svg image load failed")),$.src=_});let A=document.createElement("canvas");A.width=n,A.height=i;let c=A.getContext("2d");if(!c)throw Error("canvas unavailable");c.drawImage($,0,0);let j=await new Promise((F)=>A.toBlob(F,"image/png"));if(!j)throw Error("png export failed");q8(j,`${l}.png`)}catch{q8(y,`${l}.svg`)}finally{URL.revokeObjectURL(_)}}async function IY(u){let f=GL(String(u?.title||"pipeline-gantt"),"pipeline-gantt"),{svg:l,width:r,height:n}=kY(u),i=new Blob([l],{type:"image/svg+xml;charset=utf-8"}),y=URL.createObjectURL(i);try{let _=new Image;await new Promise((j,F)=>{_.onload=()=>j(),_.onerror=()=>F(Error("gantt svg image load failed")),_.src=y});let $=document.createElement("canvas");$.width=r,$.height=n;let A=$.getContext("2d");if(!A)throw Error("canvas unavailable");A.drawImage(_,0,0);let c=await new Promise((j)=>$.toBlob(j,"image/png"));if(!c)throw Error("gantt png export failed");q8(c,`${f}.png`)}catch{q8(i,`${f}.svg`)}finally{URL.revokeObjectURL(y)}}async function gY(u){for(let f of u){if(f.flow.nodes.length===0)continue;await zL(f.flow,f.title),await new Promise((l)=>setTimeout(l,750))}}function _L(u,f){return u.find((l)=>String(l?.pipelineId||"")===f)||null}function $L(u){return vu(u?.startedAt)??vu(u?.artifact?.startedAt)??vu(u?.request?.createdAt)??vu(u?.updatedAt)??0}function sY(u,f){return u.filter((l)=>String(l?.pipelineId||"")===f).slice().sort((l,r)=>$L(l)-$L(r)||String(l?.runId||"").localeCompare(String(r?.runId||"")))}function Z9(u,f){let l=String(f?.runId||""),r=u.findIndex((y)=>String(y?.runId||"")===l),n=r>=0?r+1:u.length,i=String(f?.status||"--");return`Epoch ${n} / ${l||"--"} / ${i}`}function Br(u){return String(u?.procedureRunId||u?.runId||"")}function w8(u,f){let l=String(u?.nodeId||u?.request?.nodeId||"");if(l)return l;let r=Br(u),n=`${f}__`;if(r.startsWith(n))return r.slice(n.length).replace(/__\d+$/u,"");return""}function $8(u,f){let l=Du(u?.artifact)?u.artifact:{},r=Du(u?.request)?u.request:{};return Y$(u?.startedAt,l.startedAt,r.createdAt,r.startedAt,u?.createdAt,u?.updatedAt,f?.startedAt,f?.request?.createdAt)}function t8(u,f){let l=String(u?.status?.status||u?.artifact?.status||u?.status||"").toLowerCase(),r=Du(u?.artifact)?u.artifact:{},n=V9(l);return Y$(u?.finishedAt,r.finishedAt,u?.completedAt,n?u?.updatedAt:void 0,n?r.updatedAt:void 0,n?f?.updatedAt:void 0)}function TL(u,f,l=Date.now()){let r=String(u?.runId||""),n=new Set(f.map((i)=>String(i?.id||"")).filter(Boolean));return Vu(u?.procedureRuns).flatMap((i)=>{let y=w8(i,r);if(!y)return[];let _=String(i?.status?.status||i?.artifact?.status||i?.status||"unknown").toLowerCase(),$=$8(i,u),A=vu($);if(A===null)return[];let c=t8(i,u),j=vu(c)??(V9(_)?vu(i?.updatedAt)??A+1000:l),F=Math.max(A+1000,j);return[{nodeId:y,knownNode:n.has(y),procedureRunId:Br(i),status:_,startMs:A,endMs:F,startedAt:V$(A),finishedAt:V$(F),durationMs:F-A,runId:r,raw:i}]}).sort((i,y)=>i.startMs-y.startMs||i.endMs-y.endMs||i.nodeId.localeCompare(y.nodeId))}function aY(u,f,l=[]){let r=f.map((c)=>Number(c.startMs)).filter(Number.isFinite),n=f.map((c)=>Number(c.endMs)).filter(Number.isFinite);for(let c of l){let j=Vf(c?.eventMs??c?.ms);if(j!==null)r.push(j),n.push(j)}let i=vu(u?.startedAt)??vu(u?.artifact?.startedAt)??vu(u?.request?.createdAt),y=vu(u?.finishedAt)??vu(u?.artifact?.finishedAt)??vu(u?.updatedAt);if(i!==null)r.push(i);if(y!==null)n.push(y);let _=Date.now(),$=r.length>0?Math.min(...r):_-60000,A=Math.max($+60000,n.length>0?Math.max(...n):_);return{startMs:$,endMs:A,durationMs:A-$}}var A8=12,EL=20,O9=100,oY=!1;function Rn(u){let f=Number(u);if(!Number.isFinite(f))return 0;return Math.max(0,Math.min(100,Math.round(f*100)/100))}function dY(u){let f=Math.max(A8,Number(u||A8)),l=Math.log(f/A8)/Math.log(EL);return Rn(l*100)}var X$=dY(O9);function m9(u){let f=Rn(u)/100,l=A8*Math.pow(EL,f),r=f<0.24?"全局":f<0.64?"均衡":"细节";return{value:Rn(f*100),pxPerMinute:l,label:r}}function L9(u){let f=Math.round(Number(u));return Math.abs(f-O9)<=1?O9:f}function eY(u,f=X$){let l=Math.max(1,Number(u.durationMs||0)/60000),r=m9(f);return Math.round(Math.max(360,Math.min(7200,l*Number(r.pxPerMinute||48))))}function uS(u,f=7){let l=Math.max(1,Number(u.endMs||0)-Number(u.startMs||0));return Array.from({length:f},(r,n)=>{let i=f===1?0:n/(f-1);return{ms:Number(u.startMs)+l*i,percent:i*100}})}function fS(u,f){let l=Math.max(1,Number(f.endMs)-Number(f.startMs));return Math.max(0,Math.min(100,(u-Number(f.startMs))/l*100))}function Vf(u){let f=Number(u);return Number.isFinite(f)?f:null}function P9(u){return jL(u?.status)&&!V9(u?.status)}function ZL(u,f,l,r){let n=Math.max(1,l-f),i=Math.max(0,Math.min(1,(u-f)/n));return Number((i*r).toFixed(3))}function tL(u,f){if(!f)return null;let l=Vf(f?.startMs),r=Vf(f?.endMs),n=Vf(f?.chartHeight);if(l===null||r===null||n===null)return null;return ZL(u,l,r,n)}function OL(u,f){let l=Vf(u?.rawStartMs??u?.startMs)??Vf(u?.startMs)??f,r=Vf(u?.endMs)??l+1000;if(!P9(u))return Math.max(l+1000,r);return Math.max(l+1000,r,f)}function lS(u,f,l,r){let n=Vf(u?.startMs)??r-60000,i=Vf(u?.endMs)??r,y=l.reduce((Q,L)=>Math.max(Q,OL(L,r)),i),_=Math.max(n+60000,i,y),$=Math.max(1,_-n),A={startMs:n,endMs:_,durationMs:$},c=eY(A,f),j=m9(f),F=Math.max(5,Math.min(18,Math.round(c/150))),U=uS(A,F).map((Q)=>{let L=Number(Q.ms),w=ZL(L,n,_,c);return{...Q,y:w,timestamp:V$(L),offsetMs:L-n}});return{source:"frontend-y",startMs:n,endMs:_,durationMs:$,chartHeight:c,scale:Rn(f),normalizedScale:Number((Rn(f)/100).toFixed(3)),pxPerMinute:Number(Number(j.pxPerMinute||0).toFixed(3)),ticks:U}}function rS(u,f,l){if(!P9(u))return u;let r=Vf(u?.rawStartMs??u?.startMs)??Vf(u?.startMs)??l,n=OL(u,l),i=tL(r,f),y=tL(n,f),_=Vf(i??u?.y1??u?.startY)??0,$=Vf(y??u?.y2??u?.endY)??_+10,A=Math.max(24,$-_);return{...u,live:!0,startMs:r,endMs:n,durationMs:Math.max(1000,n-r),finishedAt:V$(n),y1:_,y2:$,startY:_,endY:$,height:A}}function M9(u,f,l){return fS(u,f)/100*l}function Jy(u){return Boolean(u&&String(u?.source||"")!=="frontend-y")}function HL(u,f,l,r,n){if(Jy(r))for(let y of n){let _=Vf(u?.[y]);if(_!==null)return _}let i=Vf(u?.ms??u?.eventMs??u?.startMs);return M9(i??Number(f.startMs),f,l)}function N8(u,f,l,r){return HL(u,f,l,r,["y1","startY"])}function H9(u,f,l,r){if(Jy(r)){let i=Vf(u?.y2??u?.endY);if(i!==null)return i}let n=Vf(u?.endMs)??Number(f.endMs);return M9(n,f,l)}function BL(u,f,l,r){if(Jy(r)){let i=Vf(u?.height);if(i!==null)return Math.max(1,i)}let n=u?.live?24:10;return Math.max(n,H9(u,f,l,r)-N8(u,f,l,r))}function Jr(u,f,l,r){return HL(u,f,l,r,["y","timeAxisY"])}function VL(u,f,l,r){if(Jy(r)||String(r?.source||"")==="frontend-y"){let y=Vf(u?.y);if(y!==null)return y}let n=Vf(u?.percent);if(n!==null)return n/100*l;let i=Vf(u?.ms)??Number(f.startMs);return M9(i,f,l)}function nS(u){let f=String(u?.promptEvent||u?.raw?.promptEvent||u?.event||"").toLowerCase();if(!["node-long-running-observation","node-finished"].includes(f))return"";let l=String(u?.sourceNodeId||u?.raw?.sourceNodeId||u?.raw?.detail?.nodeId||""),r=String(u?.nodeId||u?.targetNodeId||"");return l&&l!==r?l:""}function iS(u,f){let l=new Set(f.map((n)=>[String(n.sourceNodeId||""),String(n.targetNodeId||""),String(n.targetMarkerId||""),String(n.action||"")].join(":"))),r=[...f];for(let n of u){let i=nS(n),y=String(n?.nodeId||""),_=String(n?.id||"");if(!i||!y||!_)continue;let $=[i,y,_,"observe"].join(":");if(l.has($))continue;l.add($),r.push({id:`observation-arrow:${_}:${i}:${y}`,commandId:String(n?.commandId||n?.eventId||_),sourceNodeId:i,targetNodeId:y,sourceMarkerId:"",targetMarkerId:_,sourceKind:"monitor",action:"observe",status:"observation"})}return{markers:u,arrows:r}}function yS(u){let f=Ir(u),l=String(u?.promptEvent||"");if(f==="initial-prompt-delivered")return"initial";if(l==="node-finished"||l==="node-long-running-observation"||l.startsWith("monitor-"))return"monitor";if(f==="monitor-prompt-delivered"||String(u?.sourceKind||"").toLowerCase()==="monitor")return"monitor";return"append"}function _S(u){return Vu(u?.tags||u?.raw?.tags).map((f)=>String(f||"")).filter(Boolean)}function $S(u){let f=Ir(u),l=String(u?.promptEvent||"");if(f==="initial-prompt-delivered")return"初始 prompt";if(l==="node-long-running-observation")return"长任务观察";if(l==="node-finished")return _S(u).includes("monitor.audit")?"节点完成 / OA 审核":"节点完成";if(l==="monitor-interval")return"Monitor observation";if(l==="monitor-start")return"Monitor start";if(l==="monitor-stop")return"Monitor stop";if(f==="monitor-prompt-delivered")return"Monitor prompt";if(f==="append-prompt-queued")return"追加 prompt 已排队";return"追加 prompt"}function AL(u){let f=Ir(u);if(f==="control-command-applied")return 3;if(f==="control-command-ignored")return 2;if(f==="control-command-queued")return 1;return 0}function tS(u,f){let l=String(u?.commandId||"");if(l)return`command:${l}`;return["control-event",cy(u)||Y$(u?.createdAt,u?.timestamp)||`index-${f}`,String(u?.sourceKind||""),String(u?.sourceNodeId||""),String(u?.targetNodeId||""),P1(u)].join(":")}function AS(u){return T9([u?.targetNodeId,...Vu(u?.resetNodeIds)])}function cS(u,f){let l=H$(u),r=Ir(u),n=String(u?.targetNodeId||""),i=Boolean(n)&&f!==n;if(r==="control-command-applied")return i?`${l} 波及`:`${l} 生效`;if(r==="control-command-ignored")return`${l} 忽略`;if(r==="control-command-queued")return`${l} 已发起`;return i?`${l} 波及`:l}function jS(u){if(Ir(u)==="control-command-ignored")return"ignored";let l=P1(u);if(l==="restart"||l==="redo")return"restart";if(l==="modify")return"modify";if(l==="approve")return"approve";if(l==="guide")return"guide";return"pending"}function FS(u){let f=String(u?.sourceKind||"").toLowerCase();if(f==="monitor")return"monitor";if(f==="webui")return"webui";if(f==="cli")return"cli";return"system"}function JS(u,f,l,r){let n=u.filter((A)=>String(A.nodeId||"")===f).sort((A,c)=>Number(A.startMs)-Number(c.startMs)),i=n.find((A)=>l>=Number(A.startMs)-1000&&l<=Number(A.endMs)+1000);if(i)return{ms:l,onInterval:!0,snapReason:"inside-interval",procedureRunId:String(i.procedureRunId||"")};let y=P1(r),_=n.slice().reverse().find((A)=>Number(A.endMs)<=l+1000);if(_&&y==="approve")return{ms:Number(_.endMs),onInterval:!0,snapReason:"previous-interval-end",procedureRunId:String(_.procedureRunId||"")};let $=n.find((A)=>Number(A.startMs)>=l-1000);if($&&["guide","modify","restart","redo"].includes(y))return{ms:Number($.startMs),onInterval:!0,snapReason:"next-interval-start",procedureRunId:String($.procedureRunId||"")};return{ms:l,onInterval:!1,snapReason:"event-time",procedureRunId:String(r?.procedureRunId||"")}}function DL(u,f,l,r){let n=Math.hypot(l-u,r-f),i=n>kW?kW:0,y=i>0?l-(l-u)/n*i:l,_=i>0?r-(r-f)/n*i:r,$=y-u,A=Math.max(16,Math.min(42,Math.abs($)*0.45+12)),c=$===0?1:Math.sign($);return`M ${u},${f} C ${u+c*A},${f} ${y-c*A},${_} ${y},${_}`}function US(u,f){let l=String(u?.runId||f?.runId||""),r=TL({...Du(f)?f:{},...Du(u)?u:{},runId:l,procedureRuns:Vu(u?.procedureRuns).length>0?u.procedureRuns:f?.procedureRuns},[]),n=[],i=[],y=[],_=new Set,$=new Map,A=(F,U)=>{if(!F.nodeId||!Number.isFinite(Number(F.ms)))return;if(_.has(F.id))return;_.add(F.id),U.push(F)};for(let F of Vu(u?.procedureRuns)){let U=w8(F,l),Q=Br(F);if(!U)continue;for(let L of Vu(F?.attempts)){let w=L8(L);for(let J of z9(L?.controlEventRecords)){let N=Ir(J);if(!["initial-prompt-delivered","append-prompt-delivered","monitor-prompt-delivered"].includes(N))continue;let q=cy(J),W=vu(q);if(W===null)continue;let z=String(J?.eventId||"");A({id:`prompt:${z||`${Q}:${w}:${N}:${W}`}`,runId:l,nodeId:U,procedureRunId:Q,attempt:w,kind:"prompt",tone:yS(J),status:"delivered",label:$S(J),ms:W,timestampIso:q,sourceKind:String(J?.sourceKind||""),sourceNodeId:String(J?.sourceNodeId||""),targetNodeId:U,action:"",eventId:z,commandId:String(J?.commandId||""),raw:J},n)}}}let c=new Map;z9(u?.controlEvents).forEach((F,U)=>{let Q=tS(F,U),L=c.get(Q)||{key:Q,events:[]};L.events.push(F),c.set(Q,L)});for(let F of c.values()){let U=Vu(F.events).slice().sort((V,Y)=>AL(Y)-AL(V)),Q=Vu(F.events).find((V)=>Ir(V)==="control-command-queued")||null,L=U[0]||Q;if(!Q&&!L)continue;let w=String(Q?.sourceNodeId||L?.sourceNodeId||""),J=String(Q?.sourceKind||L?.sourceKind||""),N=cy(Q)||cy(L)||Y$(Q?.createdAt,L?.createdAt),q=vu(N),W=String(L?.commandId||Q?.commandId||F.key),z=(Ir(L)||"control-command-queued").replace(/^control-command-/u,""),Z="";if(w&&q!==null)Z=`control-source:${W}:${w}`,$.set(W,Z),A({id:Z,runId:l,nodeId:w,procedureRunId:String(Q?.procedureRunId||L?.procedureRunId||""),attempt:"",kind:"control-source",tone:FS(Q||L),status:z,label:`${H$(Q||L)} 发起`,ms:q,timestampIso:N,action:P1(Q||L),sourceKind:J,sourceNodeId:w,targetNodeId:String(L?.targetNodeId||Q?.targetNodeId||""),commandId:W,raw:Q||L},i);let H=L||Q,E=cy(H)||N,D=vu(E);if(D===null)continue;let h=AS(H);for(let V of h){let Y=JS(r,V,D,H),p=`control-target:${W}:${V}`;if(A({id:p,runId:l,nodeId:V,procedureRunId:Y.procedureRunId,attempt:"",kind:"control-target",tone:jS(H),status:z,label:cS(H,V),ms:Y.ms,eventMs:D,onInterval:Y.onInterval,snapReason:Y.snapReason,snapped:Number(Y.ms)!==D,timestampIso:E,renderedTimestampIso:V$(Number(Y.ms)),action:P1(H),sourceKind:J,sourceNodeId:w,targetNodeId:V,commandId:W,raw:H},i),Z&&w&&w!==V)y.push({id:`control-arrow:${W}:${w}:${V}`,commandId:W,sourceNodeId:w,targetNodeId:V,sourceMarkerId:Z,targetMarkerId:p,sourceKind:J,action:P1(H),status:z})}}let j=[...n,...i].sort((F,U)=>Number(F.ms)-Number(U.ms)||String(F.nodeId).localeCompare(String(U.nodeId))||String(F.id).localeCompare(String(U.id)));return{...iS(j,y),sourceMarkerByCommand:$}}function QS({details:u,selectedNodeId:f,selectedNodeRuntime:l,control:r,onRaw:n}){if(!u)return G("span",{className:"muted"},"点击“抓取过程”读取 node 运行材料;主界面只显示结构化摘要,完整内容需点开原始 JSON。");let i=Vu(u.procedureRuns),y=i.at(-1)||{},_=Vu(y.attempts),$=_.at(-1)||{},A=Vu(y.workerLogTail),c=Vu($.controlEventsTail),j=Vu($.controlPromptsTail),F=Vu($.monitorPromptsTail),U=Q9(c),Q=Q9(j),L=Q9(F),w=$.opencodeMessages||{};return G("div",{className:"pipeline-evidence-list compact"},G(Or,{title:"Node runtime",subtitle:f||"--",facts:[`status ${l?.status||"pending"}`,`attempts ${l?.attempts??_.length}`,`procedure ${l?.currentProcedureRunId||Br(y)||"--"}`,r.fetchedAt?`fetched ${tf(r.fetchedAt)}`:"not fetched"],data:u.node||u,onRaw:n,testId:"raw-pipeline-node-runtime"}),G(Or,{title:"Procedure runs",subtitle:`${i.length} groups`,facts:[`latest ${y.status?.status||y.status||"--"}`,`steps ${Vu(y.recentSteps).length}`,`duration ${Hr(vu(y.finishedAt)&&vu(y.startedAt)?Number(vu(y.finishedAt))-Number(vu(y.startedAt)):y.durationMs)}`],data:i,onRaw:n,testId:"raw-pipeline-node-procedures"}),G(Or,{title:"OpenCode messages",subtitle:String(w.exists?"available":"not indexed"),facts:[`messages ${j8(w.messageCount)}`,`size ${j8(w.size)}`,`updated ${Nu(w.updatedAt)}`],data:w,onRaw:n,testId:"raw-pipeline-node-messages"}),G(Or,{title:"Control prompts",subtitle:"manual / monitor append queues",facts:[`manual tail ${Q.total}`,`monitor tail ${L.total}`,`last ${Nu(B9(Q.lastAt,L.lastAt))}`],data:{controlPromptsTail:j,monitorPromptsTail:F},onRaw:n,testId:"raw-pipeline-node-prompts"}),G(Or,{title:"Control events",subtitle:U.eventKinds.length>0?U.eventKinds.join(", "):"event tail",facts:[`tail ${U.total}`,`parsed ${U.parsed}`,`last ${Nu(U.lastAt)}`],data:c,onRaw:n,testId:"raw-pipeline-node-events"}),G(Or,{title:"Worker log",subtitle:"tail is hidden on main canvas",facts:[`tail ${A.length} lines`,"raw only via button",`procedure ${Br(y)||"--"}`],data:A,onRaw:n,testId:"raw-pipeline-node-worker-log"}))}function qS({activeRun:u,onRaw:f}){if(!u)return G(Ur,{title:"暂无运行材料",text:"没有 Pipeline epoch 时不会展示运行材料索引。"});let l=Vu(u.nodes),r=Vu(u.procedureRuns),n=Vu(u.submissions),i=Vu(u.workerLogTail),y=sW(l),_=sW(r),$=r.filter((c)=>String(c?.status||"").toLowerCase()==="failed"),A=B9(...r.flatMap((c)=>[c.updatedAt,c.finishedAt,c.startedAt]));return G("div",{className:"pipeline-evidence-list"},G(Or,{title:"Epoch overview",subtitle:u.runId||"--",facts:[`pipeline ${u.pipelineId||"--"}`,`status ${u.status||"--"}`,`started ${Nu(u.startedAt)}`,`updated ${Nu(u.updatedAt)}`],data:u,onRaw:f,testId:"raw-pipeline-run"}),G(Or,{title:"Node states",subtitle:`${l.length} nodes`,facts:[`running ${y.running||0}`,`succeeded ${y.succeeded||0}`,`failed ${y.failed||0}`,`pending ${y.pending||0}`],data:l,onRaw:f,testId:"raw-pipeline-run-nodes"}),G(Or,{title:"Procedure run index",subtitle:`${r.length} procedure records`,facts:[`succeeded ${_.succeeded||0}`,`failed ${_.failed||0}`,`latest ${Nu(A)}`,`errors ${$.length}`],data:r,onRaw:f,testId:"raw-pipeline-run-procedures"}),G(Or,{title:"OA submissions",subtitle:`${n.length} submission files`,facts:[`records ${n.length}`,`task ${j8(u.task)}`,"raw grouped by run"],data:n,onRaw:f,testId:"raw-pipeline-run-submissions"}),G(Or,{title:"Worker log tail",subtitle:"hidden from main interface",facts:[`tail ${i.length} lines`,"display raw only after click",`updated ${Nu(u.updatedAt)}`],data:i,onRaw:f,testId:"raw-pipeline-run-worker-log"}))}function NS({diagnostics:u,onRaw:f}){let l=Vu(u?.runs).filter(Du),r=Vu(u?.forbiddenResiduals),n=Du(u?.guarantees)?u.guarantees:{},i=u?.hasNeutralNodeFinishedEvidence===!0&&u?.hasNoAuditPolicyEvidence===!0&&u?.hasAuditPolicyEvidence===!0,y=u?.ok===!0&&i&&r.length===0,_=l[0]||null,$=[{label:"中性完成事实",ok:n.neutralNodeFinished===!0,hint:"node-finished 不携带流程策略"},{label:"Config 策略判定",ok:n.auditPolicyFromConfig===!0,hint:"OA backend 读取当前 epoch 配置"},{label:"控制命令来自 OA",ok:n.runnerConsumesControlCommandsFromOaEvents===!0,hint:"runner 只消费 OA control.command"},{label:"无独立审核事件",ok:n.noIndependentAuditRequestEvent===!0,hint:"审核由 node-finished + policy 派生"},{label:"无批次门禁",ok:n.noBatchFinishedControlGate===!0,hint:"下游启动由每个 node 完成驱动"}];return G("div",{className:"pipeline-oa-panel","data-testid":"pipeline-oa-event-flow-panel"},G("div",{className:"metric-grid compact"},G(Yl,{label:"OA Flow",value:y?"100%":"--",hint:String(u?.mode||"waiting diagnostics"),tone:y?"ok":"warn"}),G(Yl,{label:"禁止残留",value:r.length,hint:r.length===0?"source scan clean":"needs cleanup",tone:r.length===0?"ok":"warn"}),G(Yl,{label:"No-audit",value:u?.hasNoAuditPolicyEvidence?"OK":"--",hint:"OA 下游策略证据",tone:u?.hasNoAuditPolicyEvidence?"ok":"warn"}),G(Yl,{label:"Monitor 审核",value:u?.hasAuditPolicyEvidence?"OK":"--",hint:"OA 控制事件闭环",tone:u?.hasAuditPolicyEvidence?"ok":"warn"})),G("div",{className:"pipeline-oa-guarantees"},$.map((A)=>G("article",{key:A.label,className:`pipeline-oa-guarantee ${A.ok?"ok":"warn"}`},G(Cn,{status:A.ok?"online":"warn"},A.ok?"OK":"MISS"),G("div",null,G("strong",null,A.label),G("span",null,A.hint))))),G("div",{className:"pipeline-evidence-list compact"},l.slice(0,6).map((A)=>G(Or,{key:A.runId,title:String(A.runId||"--"),subtitle:[Number(A.monitorAuditNodeFinishedCount||0)>0?"monitor audit":"",Number(A.noAuditPolicyCount||0)>0?"no-audit policy":""].filter(Boolean).join(" / ")||"event evidence",facts:[`events ${A.eventCount||0}`,`node-finished ${A.nodeFinishedCount||0}`,`policy-in-detail ${A.nodeFinishedWithPolicyCount||0}`,`queued ${A.controlQueuedCount||0}`,`applied ${A.controlAppliedCount||0}`],data:A,onRaw:f,testId:`raw-pipeline-oa-run-${String(A.runId||"run").replace(/[^a-zA-Z0-9_.-]+/g,"-")}`}))),_?G("p",{className:"muted paragraph"},`最新证据 ${_.runId}: ${_.nodeFinishedCount||0} 个 node-finished,${_.controlAppliedCount||0} 个控制结果。`):G(Ur,{title:"暂无 OA 事件流证据",text:"等待 Pipeline backend 暴露 diagnostics。"}),u?G("div",{className:"panel-actions inline-actions"},G(gr,{title:"Pipeline OA Event Flow Diagnostics",data:u,onOpen:f,testId:"raw-pipeline-oa-event-flow"})):null)}function WS({quota:u,onRaw:f}){let l=Du(u?.summary)?u.summary:{},r=Du(u?.target)?u.target:{},n=Du(u?.cache)?u.cache:{},i=u?.ok===!0,y=String(u?.modelId||l.modelName||r.modelName||"MiniMax-M2.7"),_=l.totalCount??r.currentIntervalTotalCount,$=l.usageCount??r.currentIntervalUsageCount,A=l.remainingCount??r.currentIntervalRemainingCount,c=l.remainingRatio??(Number.isFinite(Number(_))&&Number(_)>0&&Number.isFinite(Number(A))?Number(A)/Number(_):void 0),j=l.usageRatio??(Number.isFinite(Number(_))&&Number(_)>0&&Number.isFinite(Number($))?Number($)/Number(_):void 0),F=l.resetAt||r.endAt,U=l.remainsMs??r.remainsMs,Q=Number(A),L=!i||Number.isFinite(Q)&&Q<=0?"warn":"ok",w=[i?`endpoint ${u?.endpoint||"--"}`:"quota unavailable",`fetched ${c8(u?.fetchedAt)}`,n.hit?`cache ${Hr(n.ageMs)}`:"live quota"];return G("div",{className:"pipeline-minimax-quota-panel","data-testid":"pipeline-minimax-quota-panel"},G("div",{className:"metric-grid compact"},G(Yl,{label:"MiniMax",value:i?y:"--",hint:u?.modelComponent||u?.error||"model/minimax-m27",tone:L}),G(Yl,{label:"当前窗口",value:`${U9($)}/${U9(_)}`,hint:`已用 ${gW(j)}`,tone:L}),G(Yl,{label:"剩余额度",value:U9(A),hint:`剩余 ${gW(c)}`,tone:L}),G(Yl,{label:"重置时间",value:c8(F),hint:U!==void 0?`约 ${Hr(U)}`:Nu(F),tone:L})),G(D9,{items:w}),i?G("p",{className:"muted paragraph"},`MiniMax 限额来自 D601 Pipeline 后端实时查询;当前模型匹配 ${l.modelName||r.modelName||y}。`):G(yf,{error:u?.error||"MiniMax 限额查询失败"}),u?G("div",{className:"panel-actions inline-actions"},G(gr,{title:"Pipeline MiniMax Quota",data:u,onOpen:f,testId:"raw-pipeline-minimax-quota"})):null)}function LS({epochs:u,activeRun:f,activePipeline:l,pipelineNodes:r,pipelineEdges:n,runDetails:i,nodeDetails:y,nodeDetailsState:_,ganttScale:$=X$,onGanttScaleChange:A,onRunChange:c,onIntervalSelect:j,onMarkerSelect:F,selection:U,detailOpen:Q,onDetailOpenChange:L,onRaw:w}){let[J,N]=gl(oY),[q,W]=gl({startY:0,endY:0,startMs:0,endMs:0}),[z,Z]=gl(Date.now()),H=Pn(null),E=String(f?.runId||""),D=Boolean(Q),h=(cu)=>{if(typeof L==="function")L(cu)},V=Rn($??X$),Y=String(i?.runId||"")===E?i?.details:null,p=Y?{...Du(f)?f:{},...Du(Y)?Y:{},runId:E,procedureRuns:Vu(Y?.procedureRuns).length>0?Y.procedureRuns:f?.procedureRuns}:f,O=TL(p,r,z),m=Y?US(Y,p):{markers:[],arrows:[]},X=Vu(m.markers),v=aY(p,O,X),T=lS(v,V,O,z),S=String(T.source||"frontend-y"),k=O.map((cu)=>rS(cu,T,z)),I={startMs:Number(T.startMs),endMs:Number(T.endMs),durationMs:Math.max(1,Number(T.durationMs??Number(T.endMs)-Number(T.startMs)))},b=m9(V),o={...b,pxPerMinute:Number(T.pxPerMinute??b.pxPerMinute)},s=Math.round(Number(T.chartHeight||360)),x=O.some(P9);j0(()=>{if(!E||!x)return;let cu=window.setInterval(()=>Z(Date.now()),1000);return()=>window.clearInterval(cu)},[E,x]);let fu=CY(l,r,Array.isArray(n)?n:[]),$u=r.map((cu)=>String(cu?.id||"")).filter(Boolean),tu=k.map((cu)=>String(cu.nodeId||"")).filter(Boolean),ju=X.map((cu)=>String(cu.nodeId||"")).filter(Boolean),Gu=Array.from(new Set([...fu,...$u,...tu,...ju])),qu={startY:0,endY:s,startMs:Number(I.startMs),endMs:Number(I.endMs)},P=Number(q?.endY||0)>0?q:qu,e=(cu)=>{return N8(cu,I,s,T)<=Number(P.endY)&&H9(cu,I,s,T)>=Number(P.startY)},uu=(cu)=>{let ku=Jr(cu,I,s,T);return ku>=Number(P.startY)&&ku<=Number(P.endY)},Wu=new Set(Gu.filter((cu)=>k.some((ku)=>ku.nodeId===cu&&e(ku))||X.some((ku)=>ku.nodeId===cu&&uu(ku)))),g=J?Gu.filter((cu)=>Wu.has(cu)):Gu,Qu=`${F9}px ${g.length>0?g.map(()=>`${A0}px`).join(" "):"minmax(160px, 1fr)"}`,Tu=Vu(T.ticks).filter(Du),Zu=String(U?.mode==="interval"?U?.interval?.procedureRunId||"":""),Xu=String(U?.mode==="event"?U?.marker?.id||"":""),uf=()=>{let cu=H.current;if(!cu){W(qu);return}let ku=Math.max(0,cu.scrollTop-J9),Tl=Math.max(120,cu.clientHeight-J9),pu=Math.min(s,ku+Tl),rl={startY:ku,endY:pu,startMs:Number(I.startMs),endMs:Number(I.endMs)},El=Math.max(0,Math.min(1,ku/s)),Jl=Math.max(El,Math.min(1,pu/s)),nl=Math.max(1,Number(I.endMs)-Number(I.startMs));rl.startMs=Number(I.startMs)+nl*El,rl.endMs=Number(I.startMs)+nl*Jl,W(rl)};j0(()=>{let cu=H.current,ku=window.setTimeout(uf,0);return cu?.addEventListener("scroll",uf),window.addEventListener("resize",uf),()=>{window.clearTimeout(ku),cu?.removeEventListener("scroll",uf),window.removeEventListener("resize",uf)}},[E,I.startMs,I.endMs,s]);let _f=Math.max(0,Gu.length-g.length),Jf=new Set(X.filter((cu)=>g.includes(String(cu.nodeId||""))&&uu(cu)).map((cu)=>String(cu.id))),Pf=new Map(X.map((cu)=>[String(cu.id),cu])),Sl=Vu(m.arrows).filter((cu)=>{if(!Jf.has(String(cu.targetMarkerId||"")))return!1;if(String(cu.action||"")==="observe")return g.includes(String(cu.sourceNodeId||""));return Jf.has(String(cu.sourceMarkerId||""))}),vf=F9+Math.max(1,g.length)*A0,ll=(cu)=>{let ku=Rn(cu.target.value);if(typeof A==="function")A(ku);window.setTimeout(uf,0)},dl=()=>IY({title:`${l?.id||"pipeline"}-${E||"epoch"}-gantt`,meta:[`run ${E||"--"}`,`${Nu(I.startMs)} -> ${Nu(I.endMs)}`,`duration ${Hr(I.durationMs)}`,`${o.label} / ${L9(o.pxPerMinute)} px/min`,`${g.length}/${Gu.length} nodes`,`${X.length} markers`],visibleNodeIds:g,intervals:k,markers:X.filter((cu)=>g.includes(String(cu.nodeId||""))),arrows:Sl,ticks:Tu,bounds:I,chartHeight:s,backendLayout:T}),el=Du(Y?.gantt?.diagnostics)?Y.gantt.diagnostics:null;return G(c0,{title:"Epoch 甘特图",eyebrow:`${l?.id||"pipeline"} / ${u.length} epochs`,className:"pipeline-wide-panel",loading:i?.loading,actions:G("div",{className:"pipeline-gantt-actions"},G("select",{value:E,disabled:u.length===0,onChange:(cu)=>c(cu.target.value),"data-testid":"pipeline-epoch-select"},u.map((cu)=>G("option",{key:cu.runId,value:cu.runId},Z9(u,cu)))),G("label",{className:"pipeline-gantt-toggle"},G("input",{type:"checkbox","data-testid":"pipeline-gantt-auto-hide-idle",checked:J,onChange:(cu)=>{N(Boolean(cu.target.checked)),window.setTimeout(uf,0)}}),G("span",null,"自动隐藏空闲列")),G("label",{className:"pipeline-gantt-scale"},G("span",null,G("b",null,"时间尺度"),G("em",{"data-testid":"pipeline-gantt-scale-label"},`${o.label} · ${L9(o.pxPerMinute)} px/min`)),G("input",{type:"range",min:0,max:100,step:0.01,value:V,onChange:ll,"aria-label":"调整甘特图时间尺度","data-testid":"pipeline-gantt-time-scale"}),G("small",null,G("span",null,"全局"),G("span",null,"细节"))),f?G("button",{type:"button",className:"ghost-btn",onClick:dl,disabled:g.length===0,"data-testid":"pipeline-export-gantt"},"导出甘特图"):null,f?G(gr,{title:`Pipeline Epoch ${f.runId}`,data:f,onOpen:w,testId:"raw-pipeline-epoch-gantt"}):null)},!f?G(Ur,{title:"暂无 Epoch",text:"当前 pipeline 还没有完整运行记录。"}):k.length===0?G(Ur,{title:"暂无时间区间",text:"等待 D601 Pipeline backend 在 procedure summary 中返回 startedAt / finishedAt。"}):G("div",{className:"pipeline-gantt-wrap"},G("div",{className:`pipeline-gantt-detail-layout ${D?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-gantt-detail-layout","data-sidebar-open":D?"true":"false"},G("div",{className:"pipeline-gantt-main"},G("div",{className:"pipeline-gantt-main-head"},G("div",{className:"pipeline-gantt-meta"},G("span",null,`time ${Nu(I.startMs)} -> ${Nu(I.endMs)}`),G("span",null,`duration ${Hr(I.durationMs)}`),G("span",null,`scale ${o.label} / ${L9(o.pxPerMinute)} px/min`),G("span",null,`layout ${S}`),el?G("span",null,`align ${el.timeAxisAlignmentOk===!1?"check":"ok"}`):null,G("span",null,`visible ${g.length}/${Gu.length} nodes`),Y?G("span",null,`markers ${X.length}`):null,J&&_f>0?G("span",null,`hidden idle ${_f}`):null),!D?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!U?.mode,onClick:()=>h(!0),"data-testid":"pipeline-gantt-sidebar-toggle"},U?.mode?"展开详情":"点击甘特图元素展开详情"):null),G("div",{className:"pipeline-gantt-viewport",ref:H,"data-testid":"pipeline-epoch-gantt","data-pipeline-id":l?.id||"","data-run-id":E,"data-layout-source":S,"data-start-ms":String(I.startMs),"data-end-ms":String(I.endMs),"data-chart-height":String(s)},G("div",{className:"pipeline-gantt-board",style:{gridTemplateColumns:Qu,minWidth:`${vf}px`}},G("div",{className:"pipeline-gantt-head time"},"Time"),g.length===0?G("div",{className:"pipeline-gantt-head empty"},"当前时间窗无工作节点"):g.map((cu)=>G("div",{key:`head-${cu}`,className:"pipeline-gantt-head node",title:cu,"data-testid":"pipeline-gantt-head-node","data-node-id":cu},G(wY,{value:cu}))),G("div",{className:"pipeline-gantt-time-axis",style:{height:`${s}px`}},Tu.map((cu)=>{let ku=VL(cu,I,s,T);return G("div",{key:`tick-${cu.ms}-${ku}`,className:"pipeline-gantt-tick",style:{top:`${ku}px`},"data-testid":"pipeline-gantt-tick","data-ms":String(cu.ms),"data-y":String(ku)},G("b",null,Nu(cu.ms)),G("span",null,`+${Hr(Number(cu.offsetMs??Number(cu.ms)-Number(I.startMs)))}`))})),g.length>0?G("svg",{className:"pipeline-gantt-arrow-layer",width:g.length*A0,height:s,viewBox:`0 0 ${g.length*A0} ${s}`,style:{left:`${F9}px`,top:`${J9}px`,width:`${g.length*A0}px`,height:`${s}px`},"aria-hidden":"true"},G("defs",null,G("marker",{id:"pipeline-gantt-arrowhead",viewBox:"0 0 10 10",refX:9,refY:5,markerWidth:6,markerHeight:6,orient:"auto-start-reverse"},G("path",{d:"M 0 0 L 10 5 L 0 10 z",fill:"context-stroke"}))),Sl.map((cu)=>{let ku=Pf.get(String(cu.targetMarkerId||""));if(!ku)return null;let Tl=Pf.get(String(cu.sourceMarkerId||"")),pu=String(Tl?.nodeId||cu.sourceNodeId||""),rl=g.indexOf(pu),El=g.indexOf(String(ku.nodeId||""));if(rl<0||El<0)return null;let Jl=rl*A0+A0/2,nl=El*A0+A0/2,pl=Tl?Jr(Tl,I,s,T):Jr(ku,I,s,T),qr=Jr(ku,I,s,T);return G("path",{key:cu.id,className:`pipeline-gantt-arrow ${String(cu.sourceKind||"").toLowerCase()} ${String(cu.status||"").toLowerCase()} ${String(cu.action||"").toLowerCase()}`,d:DL(Jl,pl,nl,qr),markerEnd:"url(#pipeline-gantt-arrowhead)","data-testid":String(cu.action||"")==="observe"?"pipeline-gantt-observation-arrow":"pipeline-gantt-arrow","data-source-node-id":String(cu.sourceNodeId||""),"data-target-node-id":String(cu.targetNodeId||""),"data-target-marker-id":String(cu.targetMarkerId||""),"data-action":String(cu.action||""),"data-source-y":String(pl),"data-target-y":String(qr)})})):null,g.length===0?G("div",{className:"pipeline-gantt-empty-col",style:{height:`${s}px`}},"滚动到有活动的时间段后,相关 node 列会自动出现。"):g.map((cu)=>{let ku=k.filter((pu)=>pu.nodeId===cu),Tl=X.filter((pu)=>String(pu.nodeId||"")===cu);return G("div",{key:`col-${cu}`,className:"pipeline-gantt-node-col",style:{height:`${s}px`}},ku.map((pu)=>{let rl=N8(pu,I,s,T),El=H9(pu,I,s,T),Jl=BL(pu,I,s,T),nl=String(pu.procedureRunId||`${cu}-${pu.startMs}`);return G("button",{key:nl,type:"button",className:`pipeline-gantt-bar ${pu.status} ${pu.live?"live":""} ${Zu===nl?"selected":""}`,style:{top:`${rl}px`,height:`${Jl}px`},title:`${cu} ${pu.status} ${Nu(pu.startedAt||pu.startMs)} -> ${Nu(pu.finishedAt||pu.endMs)}`,onClick:()=>j(pu),"data-testid":"pipeline-gantt-line","data-node-id":cu,"data-procedure-run-id":String(pu.procedureRunId||""),"data-status":String(pu.status||""),"data-live":pu.live?"true":"false","data-start-ms":String(pu.startMs||""),"data-end-ms":String(pu.endMs||""),"data-y1":String(rl),"data-y2":String(El),"data-natural-height":String(Math.max(0,El-rl))},G("strong",null,pu.status||"working"),G("span",null,Hr(pu.durationMs)))}),Tl.map((pu)=>G("button",{key:pu.id,type:"button",className:`pipeline-gantt-marker ${pu.kind} ${pu.tone||""} ${pu.status||""} ${Xu===String(pu.id)?"selected":""}`,style:{top:`${Jr(pu,I,s,T)}px`},title:`${pu.label||"event"} / ${Nu(pu.timestampIso||pu.timestamp||pu.ms)}`,onClick:()=>F(pu),"data-testid":pu.kind==="prompt"?"pipeline-gantt-prompt-marker":"pipeline-gantt-control-marker","data-marker-id":String(pu.id||""),"data-ms":String(pu.ms??pu.eventMs??""),"data-y":String(Jr(pu,I,s,T))})))})))),D?G(LY,{selection:U,runDetails:i,nodeDetails:y,nodeDetailsState:_,onRaw:w,onCollapse:()=>h(!1)}):null)))}function R0(){return{loading:!1,actionLoading:"",error:"",message:"",details:null,fetchedAt:null,appendPrompt:"",guidePrompt:"",modifyPrompt:"",approveReason:"",redoReason:""}}function mn(){return{mode:"",runId:"",interval:null,marker:null}}function w9(){return{runId:"",loading:!1,error:"",details:null,fetchedAt:null}}function E$(u,f){return`${u}/microservices/pipeline/proxy${f}`}function wS({activeRun:u,pipelineRuns:f,selectedRunId:l,onRunChange:r,selectedNodeId:n,selectedNodeConfig:i,selectedNodeRuntime:y,control:_,onControlChange:$,onFetch:A,onAction:c,onRaw:j,onCollapse:F}){let U=String(u?.runId||""),Q=String(y?.status||"pending"),L=!U||!n||_.loading||Boolean(_.actionLoading),w=(N)=>(q)=>$({[N]:q.target.value,error:"",message:""}),J=f.length>0?f:u?[u]:[];return G("aside",{className:"pipeline-node-control","data-testid":"pipeline-node-control"},G("div",{className:"pipeline-node-control-head"},G("div",null,G("p",{className:"panel-eyebrow"},"Manual Node Control"),G(nf,{title:n||"点击控制图中的 node",level:3,loading:_.loading||Boolean(_.actionLoading)})),G("div",{className:"pipeline-node-control-head-actions"},n?G(Cn,{status:Q},Q):G(Cn,{status:"pending"},"idle"),G("button",{type:"button",className:"ghost-btn mini",onClick:F,"data-testid":"pipeline-node-sidebar-collapse"},"收起"))),G("div",{className:"pipeline-control-runbar"},G("label",null,G("span",null,"目标 run"),G("select",{value:U||l,disabled:J.length===0,onChange:(N)=>r(N.target.value),"data-testid":"pipeline-node-run-select"},J.map((N)=>G("option",{key:N.runId,value:N.runId},`${N.runId||"--"} / ${N.status||"--"}`)))),G("button",{type:"button",className:"ghost-btn",disabled:L,onClick:A,"data-testid":"pipeline-node-fetch"},_.loading?"抓取中":"抓取过程"),_.details?G(gr,{title:`Pipeline Node ${n}`,data:_.details,onOpen:j,testId:"raw-pipeline-node-control"}):null),G("div",{className:"pipeline-control-meta"},G("span",null,G("b",null,"kind"),String(i?.kind||"--")),G("span",null,G("b",null,"procedure"),String(y?.currentProcedureRunId||"--")),G("span",null,G("b",null,"attempts"),String(y?.attempts??"--")),G("span",null,G("b",null,"updated"),Nu(u?.updatedAt))),!n?G(Ur,{title:"未选择 node",text:"点击 React Flow 控制图中的任意 node 后,可抓取执行过程、追加 prompt、下发引导、增量修改、审核通过或重做。"}):null,G(yf,{error:_.error,wide:!0}),G("div",{className:"pipeline-control-actions"},G("label",null,G("span",null,"实时追加 prompt(仅 running node)"),G("textarea",{value:_.appendPrompt,onChange:w("appendPrompt"),placeholder:"让当前执行中的 agent 继续、补充检查或调整当前步骤...",rows:4,disabled:!n,"data-testid":"pipeline-node-append-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:L||!String(_.appendPrompt||"").trim(),onClick:()=>c("append"),"data-testid":"pipeline-node-append-button"},_.actionLoading==="append"?"追加中":"追加到运行中 node")),G("label",null,G("span",null,"下次尝试引导 prompt"),G("textarea",{value:_.guidePrompt,onChange:w("guidePrompt"),placeholder:"给该 node 下一次 attempt 的执行提示;不会立即打断当前 session。",rows:4,disabled:!n,"data-testid":"pipeline-node-guide-input"}),G("button",{type:"button",className:"ghost-btn compact",disabled:L||!String(_.guidePrompt||"").trim(),onClick:()=>c("guide"),"data-testid":"pipeline-node-guide-button"},_.actionLoading==="guide"?"下发中":"下发 guide")),G("label",null,G("span",null,"完成后增量修改 prompt"),G("textarea",{value:_.modifyPrompt,onChange:w("modifyPrompt"),placeholder:"在该 node 已完成结果基础上追加修改要求;runner 会重跑目标 node,并保留同 node 既有 OA 输出作为上下文。",rows:4,disabled:!n,"data-testid":"pipeline-node-modify-input"}),G("button",{type:"button",className:"ghost-btn compact",disabled:L||!String(_.modifyPrompt||"").trim(),onClick:()=>c("modify"),"data-testid":"pipeline-node-modify-button"},_.actionLoading==="modify"?"排队中":"增量修改 node")),G("label",null,G("span",null,"Monitor 审核通过原因"),G("textarea",{value:_.approveReason,onChange:w("approveReason"),placeholder:"当流程配置开启 monitor 审核时,记录审核通过原因并释放后续 node。",rows:3,disabled:!n,"data-testid":"pipeline-node-approve-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:L||!String(_.approveReason||"").trim(),onClick:()=>c("approve"),"data-testid":"pipeline-node-approve-button"},_.actionLoading==="approve"?"提交中":"审核通过")),G("label",null,G("span",null,"重做 / restart 原因"),G("textarea",{value:_.redoReason,onChange:w("redoReason"),placeholder:"说明为什么需要重做;runner 会重置目标 node 以及非 rework 下游 node。",rows:4,disabled:!n,"data-testid":"pipeline-node-redo-input"}),G("button",{type:"button",className:"danger-btn compact",disabled:L||!String(_.redoReason||"").trim(),onClick:()=>c("redo"),"data-testid":"pipeline-node-redo-button"},_.actionLoading==="redo"?"排队中":"重做 node"))),G("div",{className:"pipeline-control-evidence"},G("strong",null,"Node 过程索引"),G(QS,{details:_.details,selectedNodeId:n,selectedNodeRuntime:y,control:_,onRaw:j})))}function XL({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((lu)=>lu.id==="pipeline")||null,[n,i]=gl({loading:!1,error:"",health:null,snapshot:null,oaDiagnostics:null,minimaxQuota:null,refreshedAt:null}),[y,_]=gl(""),[$,A]=gl(""),[c,j]=gl(""),[F,U]=gl(R0()),[Q,L]=gl({}),[w,J]=gl(mn()),[N,q]=gl(w9()),[W,z]=gl(X$),[Z,H]=gl(!1),[E,D]=gl(!1),h=Pn(0),{addNotification:V}=Vl(),Y=Pn(!1),p=Pn(0),O=Pn(""),m=Pn({}),X=Pn(""),v=Pn("");async function T(lu={}){let Ou=lu.silent===!0;if(!r)return;if(Y.current)return;Y.current=!0;let Yu=h.current+1;if(h.current=Yu,!Ou)i((Iu)=>({...Iu,loading:!0,error:""}));try{let Iu=`__unideskArrayLimit=registry.components:80,runs:${rY}`,[Qf,il,ff]=await Promise.all([pn(`${l}/microservices/pipeline/proxy/api/snapshot?${Iu}`,{cache:"no-store"}),pn(`${l}/microservices/pipeline/proxy/api/oa-event-flow/diagnostics`,{cache:"no-store"}).catch(($f)=>({ok:!1,error:Hu($f,"OA event flow diagnostics failed")})),pn(`${l}/microservices/pipeline/proxy/api/model-quota/minimax`,{cache:"no-store"}).catch(($f)=>({ok:!1,error:Hu($f,"MiniMax quota failed")}))]);if(Yu!==h.current)return;let df={ok:Qf?.ok!==!1,service:"pipeline-v2-control snapshot"};i({loading:!1,error:"",health:df,snapshot:Qf,oaDiagnostics:il,minimaxQuota:ff,refreshedAt:new Date})}catch(Iu){if(Yu!==h.current)return;i((Qf)=>({...Qf,loading:!1,error:Hu(Iu,"Pipeline 加载失败")}))}finally{Y.current=!1}}j0(()=>{if(T(),!r)return;let lu=()=>{if(y8())T({silent:!0})},Ou=window.setInterval(()=>{lu()},vW),Yu=()=>{if(y8())lu()};return document.addEventListener("visibilitychange",Yu),()=>{window.clearInterval(Ou),document.removeEventListener("visibilitychange",Yu)}},[r?.id,r?.runtime?.providerStatus,l]);let S=KY(r),k=zY(r),I=GY(r),b=n.snapshot||{},o=n.oaDiagnostics||null,s=n.minimaxQuota||null,{components:x,pipelines:fu,runs:$u}=TY(b),tu=String($u[0]?.pipelineId||""),ju=(tu?fu.find((lu)=>String(lu.id||"")===tu):null)||fu[0]||{},Gu=fu.find((lu)=>String(lu.id||"")===y)||ju,qu=String(Gu.id||""),P=LL(Gu),e=Y9(Gu),uu=_L($u,qu),Wu=sY($u,qu),g=Wu.find((lu)=>String(lu?.runId||"")===$)||uu,Qu=String(N.runId||"")===String(g?.runId||"")?HY(N.details):null,Tu=BY(g,Qu),Zu=String(Tu?.runId||""),Xu=P.find((lu)=>String(lu?.id||"")===c)||null,uf=c?wL(Tu,c):null,_f=ZY($u),Jf=YY(x),Pf=Number(n.health?.components)||uL(b,"registry.components",x.length),Sl=uL(b,"runs",$u.length),vf=rL(Gu,Tu,x),ll={nodes:vf.nodes.map((lu)=>lu.id===c?{...lu,selected:!0,className:`${lu.className||""} selected-control-node`}:lu),edges:vf.edges},dl=fu.map((lu)=>{let Ou=String(lu.id||"pipeline"),Yu=_L($u,Ou);return{title:`${Ou}-${Yu?.runId||"snapshot"}`,flow:rL(lu,Yu,x)}}),el=String(w?.runId||Zu||""),cu=String(w?.interval?.nodeId||w?.marker?.nodeId||""),ku=el&&cu?Q[W9(el,cu)]||null:null,Tl=F8(F.details,el,cu),pu=F8(ku?.details,el,cu)||Tl,rl=el&&cu?{...Du(ku)?ku:{},runId:el,nodeId:cu,details:pu,loading:Boolean(ku?.loading)||!pu&&Boolean(F.loading)&&c===cu,error:String(ku?.error||""),fetchedAt:ku?.fetchedAt||(Tl?F.fetchedAt:null)}:null,El=Wu.map((lu)=>String(lu?.runId||"")).filter(Boolean).join("|"),Jl=P.map((lu)=>String(lu?.id||"")).filter(Boolean).join("|");j0(()=>{X.current=c},[c]),j0(()=>{v.current=Zu},[Zu]),j0(()=>{if(!$||El.split("|").includes($))return;A("")},[$,El]),j0(()=>{if(!c||Jl.split("|").includes(c))return;j(""),U(R0()),J(mn()),H(!1),D(!1)},[c,Jl]),j0(()=>{if(!c)H(!1)},[c]),j0(()=>{if(!w.mode)D(!1)},[w.mode]);async function nl(lu=Zu,Ou={}){if(!lu){q(w9());return}let Yu=Rn(Ou.scale??W??X$),Iu=`${lu}:timeline`;if(O.current===Iu)return;O.current=Iu;let Qf=Ou.silent===!0,il=p.current+1;p.current=il,q((ff)=>({runId:lu,scale:Yu,loading:!Qf||String(ff.runId||"")!==lu||!ff.details,error:"",details:Qf&&ff.runId===lu?ff.details:ff.runId===lu?ff.details:null,fetchedAt:ff.runId===lu?ff.fetchedAt:null}));try{let[ff,df]=await Promise.all([pn(E$(l,`/api/node-control/runs/${encodeURIComponent(lu)}?tail=160&view=timeline`),{cache:"no-store",strictJson:!0}),pn(E$(l,`/api/runs/${encodeURIComponent(lu)}`),{cache:"no-store"}).catch(($f)=>({ok:!1,runSummaryError:Hu($f,"抓取评分失败")}))]);if(il!==p.current)return;q({runId:lu,scale:Yu,loading:!1,error:"",details:{...ff,run:Du(df?.run)?df.run:void 0,runSummaryError:df?.runSummaryError},fetchedAt:new Date})}catch(ff){if(il!==p.current)return;q((df)=>({runId:lu,scale:Yu,loading:!1,error:Hu(ff,"抓取 epoch 执行过程失败"),details:df.runId===lu?df.details:null,fetchedAt:df.runId===lu?df.fetchedAt:null}))}finally{if(O.current===Iu)O.current=""}}function pl(lu,Ou,Yu){let Iu=W9(lu,Ou);L((Qf)=>{let il={...Qf,[Iu]:{...Du(Qf?.[Iu])?Qf[Iu]:{},runId:lu,nodeId:Ou,...Yu}},ff=Object.keys(il);if(ff.length>32)for(let df of ff.slice(0,ff.length-32))delete il[df];return il})}async function qr(lu,Ou){if(!lu||!Ou)return;let Yu=W9(lu,Ou),Iu=Number(m.current?.[Yu]||0)+1;m.current={...m.current,[Yu]:Iu},pl(lu,Ou,{loading:!0,error:""});try{let Qf=await pn(E$(l,`/api/node-control/runs/${encodeURIComponent(lu)}/nodes/${encodeURIComponent(Ou)}?tail=160`),{cache:"no-store",strictJson:!0});if(Number(m.current?.[Yu]||0)!==Iu)return;let il=new Date;if(pl(lu,Ou,{loading:!1,details:Qf,fetchedAt:il,error:""}),X.current===Ou&&v.current===lu)U((ff)=>({...ff,loading:!1,details:Qf,fetchedAt:il,error:""}))}catch(Qf){if(Number(m.current?.[Yu]||0)!==Iu)return;pl(lu,Ou,{loading:!1,error:Hu(Qf,"抓取 Gantt node 详情失败")})}}j0(()=>{if(!Zu){q(w9());return}nl(Zu);let lu=()=>{if(y8())nl(Zu,{silent:!0})},Ou=window.setInterval(()=>{lu()},vW),Yu=()=>{if(y8())lu()};return document.addEventListener("visibilitychange",Yu),()=>{window.clearInterval(Ou),document.removeEventListener("visibilitychange",Yu)}},[Zu,l]);async function rf(lu=Zu,Ou=c){if(!lu||!Ou){U((Yu)=>({...Yu,error:"请先选择 run 和 node",message:""}));return}U((Yu)=>({...Yu,loading:!0,error:"",message:""}));try{let Yu=await pn(E$(l,`/api/node-control/runs/${encodeURIComponent(lu)}/nodes/${encodeURIComponent(Ou)}?tail=160`),{cache:"no-store",strictJson:!0}),Iu=new Date;U((Qf)=>({...Qf,loading:!1,details:Yu,fetchedAt:Iu,error:""})),pl(lu,Ou,{loading:!1,details:Yu,fetchedAt:Iu,error:""})}catch(Yu){U((Iu)=>({...Iu,loading:!1,error:Hu(Yu,"抓取 node 执行过程失败")}))}}async function C1(lu){let Ou=String(lu?.runId||Zu||""),Yu=String(lu?.nodeId||"");if(J({mode:"interval",runId:Ou,interval:lu,marker:null}),D(!0),!Ou||!Yu)return;if(Ou!==Zu)A(Ou);j(Yu),U(R0()),nl(Ou,{silent:!0}),qr(Ou,Yu)}async function kn(lu){let Ou=String(lu?.runId||Zu||""),Yu=String(lu?.nodeId||"");if(J({mode:"event",runId:Ou,interval:null,marker:lu}),D(!0),!Ou)return;if(Ou!==Zu)A(Ou);if(nl(Ou,{silent:!0}),!Yu)return;j(Yu),U(R0()),qr(Ou,Yu)}async function R1(lu){if(!Zu||!c){U((Iu)=>({...Iu,error:"请先选择 run 和 node",message:""}));return}let Ou=lu==="append"?"prompts":lu,Yu=lu==="append"?F.appendPrompt:lu==="guide"?F.guidePrompt:lu==="modify"?F.modifyPrompt:lu==="approve"?F.approveReason:F.redoReason;if(!String(Yu||"").trim()){U((Iu)=>({...Iu,error:"操作内容不能为空",message:""}));return}U((Iu)=>({...Iu,actionLoading:lu,error:"",message:""}));try{let Iu=lu==="redo"||lu==="approve"?{reason:Yu,source:"unidesk-frontend",sourceKind:"webui"}:{prompt:Yu,source:"unidesk-frontend",sourceKind:"webui"},Qf=await pn(E$(l,`/api/node-control/runs/${encodeURIComponent(Zu)}/nodes/${encodeURIComponent(c)}/${Ou}`),{method:"POST",body:JSON.stringify(Iu)});if(U((ff)=>({...ff,actionLoading:"",details:Qf,fetchedAt:new Date,appendPrompt:lu==="append"?"":ff.appendPrompt,guidePrompt:lu==="guide"?"":ff.guidePrompt,modifyPrompt:lu==="modify"?"":ff.modifyPrompt,approveReason:lu==="approve"?"":ff.approveReason,redoReason:lu==="redo"?"":ff.redoReason,message:lu==="append"?"已追加到运行中 node":lu==="guide"?"已下发 guide,等待 runner 处理":lu==="modify"?"已排队增量修改命令":lu==="approve"?"已提交审核通过决策":"已排队重做命令"})),V("success",lu==="append"?"已追加到运行中 node":lu==="guide"?"已下发 guide,等待 runner 处理":lu==="modify"?"已排队增量修改命令":lu==="approve"?"已提交审核通过决策":"已排队重做命令"),await rf(Zu,c),await nl(Zu,{silent:!0}),lu!=="append")await T()}catch(Iu){U((Qf)=>({...Qf,actionLoading:"",error:Hu(Iu,"node 控制操作失败")}))}}if(!r)return G(Ur,{title:"Pipeline 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=pipeline"});return G("div",{className:"pipeline-page","data-testid":"pipeline-page"},G(c0,{title:"Pipeline v2 工作台",eyebrow:"D601 Snapshot 用户服务",loading:n.loading,actions:G("div",{className:"panel-actions"},G("button",{type:"button",className:"ghost-btn",onClick:T,disabled:n.loading,"data-testid":"pipeline-refresh-button"},n.loading?"刷新中":"刷新"),G(gr,{title:"Pipeline 用户服务",data:r,onOpen:f,testId:"raw-pipeline-service"}))},G("div",{className:"pipeline-hero"},G("div",null,G("div",{className:"node-version-line"},G(Cn,{status:S.providerStatus==="online"?"online":"warn"},S.providerStatus||"unknown"),G("span",null,r.providerId),G("span",null,I.public?"公网暴露":"仅 UniDesk frontend 代理访问")),G("p",{className:"muted paragraph"},r.description)),G("div",{className:"microservice-ref-card"},G("span",null,"Repo"),G("strong",null,k.url||"--"),G("code",null,k.commitId||"--")),G("div",{className:"microservice-ref-card"},G("span",null,"D601 Docker"),G("strong",null,`${I.nodeBindHost||"--"}:${I.nodePort||"--"}`),G("code",null,`${k.composeFile||"--"} / ${k.composeService||"--"}`))),G(yf,{error:n.error,wide:!0})),G("div",{className:"pipeline-grid"},G(c0,{title:"控制图",eyebrow:`${Gu.id||"pipeline"} / run ${Tu?.status||"--"}`,className:"pipeline-wide-panel",loading:n.loading,actions:G("div",{className:"pipeline-toolbar"},G("select",{value:qu,disabled:fu.length===0,onChange:(lu)=>{_(lu.target.value),A(""),j(""),U(R0()),J(mn()),H(!1),D(!1)},"data-testid":"pipeline-select"},fu.map((lu)=>G("option",{key:lu.id,value:lu.id},lu.id||lu.key))),G("select",{value:Zu,disabled:Wu.length===0,onChange:(lu)=>{if(A(lu.target.value),U(R0()),J(mn()),H(!1),D(!1),c)rf(lu.target.value,c)},"data-testid":"pipeline-run-select"},Wu.map((lu)=>G("option",{key:lu.runId,value:lu.runId},Z9(Wu,lu)))),G("button",{type:"button",className:"ghost-btn",disabled:ll.nodes.length===0,onClick:()=>zL(ll,`${Gu.id||"pipeline"}-${Tu?.runId||"snapshot"}`),"data-testid":"pipeline-export-graph"},"导出渲染图"),G("button",{type:"button",className:"ghost-btn",disabled:dl.every((lu)=>lu.flow.nodes.length===0),onClick:()=>gY(dl),"data-testid":"pipeline-export-all-graphs"},"批量导出"))},P.length===0?G(Ur,{title:"暂无控制图",text:"等待 D601 pipeline backend 返回 config.nodes / config.edges"}):G("div",{className:`pipeline-control-shell ${Z?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-control-shell","data-sidebar-open":Z?"true":"false"},G("div",{className:"pipeline-flow-frame","data-testid":"pipeline-react-flow"},G(PW,{nodes:ll.nodes,edges:ll.edges,nodeTypes:$Y,edgeTypes:_Y,fitView:!0,fitViewOptions:{padding:0.18},nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,minZoom:0.25,maxZoom:1.4,proOptions:{hideAttribution:!0},onNodeClick:(lu,Ou)=>{let Yu=String(Ou.id);if(j(Yu),U(R0()),H(!0),Zu)rf(Zu,Yu)}},G(CW,{gap:22,size:1,color:"rgba(215, 161, 58, 0.24)"}),G(xW,{showInteractive:!1})),!Z?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!c,onClick:()=>H(!0),"data-testid":"pipeline-node-sidebar-toggle"},c?"展开 node 控制":"点击 node 展开控制"):null),Z?G(wS,{activeRun:Tu,pipelineRuns:Wu,selectedRunId:$,onRunChange:(lu)=>{if(A(lu),U(R0()),J(mn()),c)rf(lu,c)},selectedNodeId:c,selectedNodeConfig:Xu,selectedNodeRuntime:uf,control:F,onControlChange:(lu)=>U((Ou)=>({...Ou,...lu})),onFetch:()=>rf(),onAction:R1,onRaw:f,onCollapse:()=>H(!1)}):null),G("div",{className:"pipeline-flow-summary"},G("span",null,`${ll.nodes.length} nodes`),G("span",null,`${ll.edges.length} edges`),G("span",null,`${fu.length} pipelines`),G("span",null,`source config+components(${x.length})`),G("span",null,`run ${Tu?.runId||"--"}`),G("span",null,`score ${E9(Tu)}`),G("span",null,c?`selected ${c}`:"click node to control"))),G(LS,{epochs:Wu,activeRun:Tu,activePipeline:Gu,pipelineNodes:P,pipelineEdges:e,selection:w,detailOpen:E,onDetailOpenChange:D,runDetails:N,nodeDetails:pu,nodeDetailsState:rl,ganttScale:W,onGanttScaleChange:z,onIntervalSelect:C1,onMarkerSelect:kn,onRunChange:(lu)=>{if(A(lu),U(R0()),J(mn()),D(!1),c)rf(lu,c)},onRaw:f}),G(c0,{title:"观测指标",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Snapshot",loading:n.loading},G("div",{className:"metric-grid"},G(Yl,{label:"Health",value:n.health?.ok?"OK":"--",hint:n.health?.service||"D601 /health",tone:n.health?.ok?"ok":"warn"}),G(Yl,{label:"组件",value:Pf,hint:"components registry",tone:b?.registry?.ok===!1?"warn":"ok"}),G(Yl,{label:"Pipeline",value:fu.length,hint:`${P.length} nodes / ${e.length} edges`}),G(Yl,{label:"运行记录",value:Sl,hint:`${_f.succeeded||0} succeeded / ${_f.running||0} running`}),G(Yl,{label:"OA 记录",value:Array.isArray(uu?.submissions)?uu.submissions.length:0,hint:uu?.runId||"latest run"}),G(Yl,{label:"Procedure",value:Array.isArray(uu?.procedureRuns)?uu.procedureRuns.length:0,hint:uu?.status||"no run"}),G(Yl,{label:"Score",value:E9(Tu),hint:Tu?.runId||"selected epoch",tone:p9(Tu)})),G("div",{className:"panel-actions inline-actions"},G(gr,{title:"Pipeline Snapshot",data:b,onOpen:f,testId:"raw-pipeline-snapshot"}))),G(c0,{title:"评分器",eyebrow:Tu?.runId||"selected epoch",loading:n.loading},G(XY,{run:Tu,onRaw:f})),G(c0,{title:"MiniMax 限额",eyebrow:"model/minimax-m27 quota",loading:n.loading},G(WS,{quota:s,onRaw:f})),G(c0,{title:"OA 事件流",eyebrow:"100% event-driven diagnostics",className:"pipeline-wide-panel",loading:n.loading},G(NS,{diagnostics:o,onRaw:f})),G(c0,{title:"组件矩阵",eyebrow:`${Jf.length} classes`,loading:n.loading},Jf.length===0?G(Ur,{title:"暂无组件",text:"等待 D601 pipeline backend 返回 registry.components"}):G("div",{className:"component-strata"},Jf.map((lu)=>G("article",{key:lu.name,className:"component-stratum"},G("span",null,lu.name),G("strong",null,lu.count)))),G("div",{className:"pipeline-component-list"},x.slice(0,12).map((lu)=>G("span",{key:lu.key,className:"data-chip"},G("b",null,lu.componentClass||"--"),G("span",null,lu.id||lu.key||"--"))))),G(c0,{title:"Epoch 列表",eyebrow:`${Wu.length}/${Sl} preview`,loading:n.loading},Wu.length===0?G(Ur,{title:"暂无运行记录",text:"当前 pipeline 在 .state/pipeline-runs 中还没有 epoch。"}):G("div",{className:"pipeline-run-list"},Wu.map((lu)=>{let Ou=String(lu?.runId||"")===Zu?Tu:lu;return G("article",{key:lu.runId,className:`pipeline-run-card ${String(lu.runId||"")===Zu?"active":""}`,role:"button",tabIndex:0,onClick:()=>{A(String(lu.runId||"")),J(mn())},onKeyDown:(Yu)=>{if(Yu.key==="Enter"||Yu.key===" ")A(String(lu.runId||"")),J(mn())}},G("div",{className:"node-card-head"},G("strong",null,Z9(Wu,lu)),G(Cn,{status:lu.status},lu.status||"--")),G("div",{className:"docker-meta compact"},G("span",null,Ou?.pipelineId||"--"),G("span",null,`nodes ${Array.isArray(Ou?.nodes)?Ou.nodes.length:0}`),G("span",null,`oa ${Array.isArray(Ou?.submissions)?Ou.submissions.length:0}`),G("span",null,`procedures ${Array.isArray(Ou?.procedureRuns)?Ou.procedureRuns.length:0}`),G(DY,{run:Ou})),G("p",{className:"muted paragraph"},j8(Ou?.task)),G("span",{className:"pipeline-run-time"},Nu(Ou?.updatedAt)))}))),G(c0,{title:"运行材料索引",eyebrow:Tu?.runId||"selected epoch",className:"pipeline-wide-panel",loading:n.loading},G(qS,{activeRun:Tu,onRaw:f}))))}var z8=Pu(qf(),1);var _u=z8.default.createElement,{useEffect:KS}=z8.default,K8=z8.default.useState,C9={id:"",sequenceNo:"",contractNo:"",name:"",currentStatus:"",pending:"",paymentStatus:"",notes:""};function GS({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return _u("span",{className:`status-badge ${l}`},f||u||"unknown")}function G8({label:u,value:f,hint:l,tone:r}){return _u("article",{className:`metric-card ${r||""}`},_u("div",{className:"metric-label"},u),_u("div",{className:"metric-value"},f),_u("div",{className:"metric-hint"},l))}function R9({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return _u("section",{className:`panel ${n||""}`},_u("div",{className:"panel-head"},_u("div",null,f?_u("p",{className:"panel-eyebrow"},f):null,_u(nf,{title:u,loading:i})),l?_u("div",{className:"panel-actions"},l):null),_u("div",{className:"panel-body"},r))}function YL({title:u,data:f,onOpen:l,testId:r}){return _u("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function SL({title:u,text:f}){return _u("div",{className:"empty-state"},_u("strong",null,u),_u("span",null,f))}function zS(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function TS(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function ES(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Uy(u,f){return`${u}/microservices/project-manager/proxy${f}`}function ZS(u){return{id:String(u.id||""),sequenceNo:u.sequenceNo===null||u.sequenceNo===void 0?"":String(u.sequenceNo),contractNo:String(u.contractNo||""),name:String(u.name||""),currentStatus:String(u.currentStatus||""),pending:String(u.pending||""),paymentStatus:String(u.paymentStatus||""),notes:String(u.notes||"")}}function OS(u){return{sequenceNo:u.sequenceNo===""?null:Number(u.sequenceNo),contractNo:String(u.contractNo||"").trim(),name:String(u.name||"").trim(),currentStatus:String(u.currentStatus||"").trim(),pending:String(u.pending||"").trim(),paymentStatus:String(u.paymentStatus||"").trim(),paymentRatio:String(u.paymentStatus||"").trim(),notes:String(u.notes||"").trim()}}function x9(u){return String(u||"item").replace(/[^A-Za-z0-9_-]+/g,"-")}function HS(u){let f=new Uint8Array(u),l="",r=32768;for(let n=0;n_u("tr",{key:n.id,className:f===n.id?"active-row":"","data-testid":`project-manager-row-${x9(n.id)}`},_u("td",null,n.sequenceNo??"--"),_u("td",null,_u("strong",null,n.contractNo||"--"),_u("code",null,n.id||"--")),_u("td",null,_u("strong",null,n.name||"--"),_u("span",{className:"muted block"},n.sourceFile||"--")),_u("td",null,n.currentStatus||"--"),_u("td",null,_u("span",{className:"preline"},n.pending||"--")),_u("td",null,_u(GS,{status:Number(n.paymentRatio||0)>=1?"online":"warn"},n.paymentStatus||"--")),_u("td",null,n.notes||"--"),_u("td",null,_u("div",{className:"inline-actions"},_u("button",{type:"button",className:"ghost-btn",onClick:()=>l(n),"data-testid":`project-manager-edit-${x9(n.id)}`},"编辑"),_u(YL,{title:`Project ${n.contractNo||n.id}`,data:n,onOpen:r,testId:`raw-project-${x9(n.id)}`}))))))))}function pL({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((E)=>E.id==="project-manager")||null,[n,i]=K8({loading:!1,saving:!1,importing:!1,exporting:!1,error:"",notice:"",health:null,list:null,refreshedAt:null}),[y,_]=K8({...C9}),[$,A]=K8(""),[c,j]=K8("all"),{addNotification:F}=Vl();async function U(E=$,D=c){if(!r)return;i((h)=>({...h,loading:!0,error:""}));try{let h=new URLSearchParams({pageSize:"200",status:D});if(E.trim())h.set("q",E.trim());let[V,Y]=await Promise.all([Eu(`${l}/microservices/project-manager/health`),Eu(Uy(l,`/api/projects?${h.toString()}`))]);i((p)=>({...p,loading:!1,health:V,list:Y,refreshedAt:new Date,error:""}))}catch(h){i((V)=>({...V,loading:!1,error:Hu(h,"Project Manager 加载失败")}))}}KS(()=>{U()},[r?.id,r?.runtime?.providerStatus]);async function Q(E){E.preventDefault(),i((D)=>({...D,saving:!0,error:"",notice:""}));try{let D=OS(y);if(y.id)await Eu(Uy(l,`/api/projects/${encodeURIComponent(y.id)}`),{method:"PUT",body:JSON.stringify(D)});else await Eu(Uy(l,"/api/projects"),{method:"POST",body:JSON.stringify(D)});let h=y.id?"项目已更新":"项目已创建";i((V)=>({...V,saving:!1,notice:h})),F("success",h),await U()}catch(D){i((h)=>({...h,saving:!1,error:Hu(D,"保存项目失败")}))}}async function L(){if(!y.id)return;if(!window.confirm(`删除项目 ${y.contractNo||y.name||y.id} ?`))return;i((E)=>({...E,saving:!0,error:"",notice:""}));try{await Eu(Uy(l,`/api/projects/${encodeURIComponent(y.id)}`),{method:"DELETE"}),_({...C9});let E="项目已删除";i((D)=>({...D,saving:!1,notice:E})),F("success",E),await U()}catch(E){i((D)=>({...D,saving:!1,error:Hu(E,"删除项目失败")}))}}async function w(E){let D=E.target.files?.[0];if(!D)return;i((h)=>({...h,importing:!0,error:"",notice:""}));try{let h=HS(await D.arrayBuffer()),Y=`Excel 已导入 ${(await Eu(Uy(l,"/api/import/excel"),{method:"POST",body:JSON.stringify({fileName:D.name,contentBase64:h,replace:!1})})).imported||0} 条项目`;i((p)=>({...p,importing:!1,notice:Y})),F("success",Y),E.target.value="",await U()}catch(h){i((V)=>({...V,importing:!1,error:Hu(h,"Excel 导入失败")}))}}async function J(){i((E)=>({...E,exporting:!0,error:""}));try{let E=await fU(Uy(l,"/api/projects/export.xlsx")),D=URL.createObjectURL(E),h=document.createElement("a");h.href=D,h.download=`project-manager-${X7()}.xlsx`,document.body.appendChild(h),h.click(),h.remove(),URL.revokeObjectURL(D),i((V)=>({...V,exporting:!1,notice:"Excel 已导出"}))}catch(E){i((D)=>({...D,exporting:!1,error:Hu(E,"Excel 导出失败")}))}}if(!r)return _u(SL,{title:"Project Manager 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=project-manager"});let N=zS(r),q=ES(r),W=TS(r),z=Array.isArray(n.list?.projects)?n.list.projects:[],Z=n.list?.summary||{},H=n.health||{};return _u("div",{className:"project-manager-page","data-testid":"project-manager-page"},_u(R9,{title:"项目管理工作台",eyebrow:"Main Server PostgreSQL 用户服务",loading:n.loading||n.exporting,actions:_u("div",{className:"panel-actions"},_u("button",{type:"button",className:"ghost-btn",disabled:n.loading,onClick:()=>U(),"data-testid":"project-manager-refresh-button"},n.loading?"刷新中":"刷新"),_u("button",{type:"button",className:"ghost-btn",disabled:n.exporting,onClick:J,"data-testid":"project-manager-export-button"},n.exporting?"导出中":"导出 Excel"),_u(YL,{title:"Project Manager 用户服务",data:r,onOpen:f,testId:"raw-project-manager-service"}))},_u("div",{className:"project-manager-hero"},_u(G8,{label:"项目总数",value:Z.total??z.length,hint:`PG 表 ${H.storage?.table||"project_manager_projects"}`,tone:"ok"}),_u(G8,{label:"进行中",value:Z.active??"--",hint:"当前状态未完全完成"}),_u(G8,{label:"已完成",value:Z.completed??"--",hint:"按 完成 关键字统计",tone:"ok"}),_u(G8,{label:"未全款",value:Z.unpaid??"--",hint:"付款比例 < 1",tone:Number(Z.unpaid||0)>0?"warn":"ok"})),_u(yf,{error:n.error}),n.notice?_u("div",{className:"form-success"},n.notice):null),_u("div",{className:"project-manager-hero"},_u("div",{className:"microservice-ref-card"},_u("span",null,"Repo"),_u("strong",null,q.url||"--"),_u("code",null,q.commitId||"--")),_u("div",{className:"microservice-ref-card"},_u("span",null,"Main Server Docker"),_u("strong",null,`${W.nodeBindHost||"--"}:${W.nodePort||"--"}`),_u("code",null,`${q.composeService||"--"} / ${q.containerName||"--"}`)),_u("div",{className:"microservice-ref-card"},_u("span",null,"Runtime"),_u("strong",null,N.providerName||r.providerId),_u("code",null,`Health ${H.ok?"OK":"--"} / ${n.refreshedAt?tf(n.refreshedAt):"--"}`)),_u("div",{className:"microservice-ref-card"},_u("span",null,"Import Source"),_u("strong",null,"D601 WeChat Excel"),_u("code",null,"合作项目列表_I_20260309.xlsx"))),_u("div",{className:"project-manager-layout"},_u(R9,{title:"项目清单",eyebrow:"CRUD + Excel Export",loading:n.loading||n.importing||n.exporting,actions:_u("div",{className:"inline-actions project-manager-filters"},_u("input",{value:$,onChange:(E)=>A(E.target.value),placeholder:"搜索合同号 / 项目名称 / 状态","data-testid":"project-manager-search"}),_u("select",{value:c,onChange:(E)=>{j(E.target.value),U($,E.target.value)},"data-testid":"project-manager-status-filter"},_u("option",{value:"all"},"全部"),_u("option",{value:"active"},"进行中"),_u("option",{value:"completed"},"已完成"),_u("option",{value:"unpaid"},"未全款")),_u("button",{type:"button",className:"ghost-btn",onClick:()=>U($,c)},"筛选"))},_u(BS,{projects:z,activeId:y.id,onSelect:(E)=>_(ZS(E)),onRaw:f})),_u(R9,{title:y.id?"编辑项目":"新建项目",eyebrow:"PostgreSQL Write Path",loading:n.saving||n.importing},_u("form",{className:"stack-form project-manager-form",onSubmit:Q,"data-testid":"project-manager-form"},y.id?_u("label",null,"项目 ID",_u("input",{value:y.id,disabled:!0})):null,_u("label",null,"序号",_u("input",{type:"number",value:y.sequenceNo,onChange:(E)=>_((D)=>({...D,sequenceNo:E.target.value}))})),_u("label",null,"合同号",_u("input",{value:y.contractNo,onChange:(E)=>_((D)=>({...D,contractNo:E.target.value})),required:!0})),_u("label",null,"项目名称",_u("input",{value:y.name,onChange:(E)=>_((D)=>({...D,name:E.target.value})),required:!0})),_u("label",null,"当前状况",_u("textarea",{value:y.currentStatus,onChange:(E)=>_((D)=>({...D,currentStatus:E.target.value}))})),_u("label",null,"待完成",_u("textarea",{value:y.pending,onChange:(E)=>_((D)=>({...D,pending:E.target.value}))})),_u("label",null,"付款情况",_u("input",{value:y.paymentStatus,onChange:(E)=>_((D)=>({...D,paymentStatus:E.target.value})),placeholder:"例如 1 / 0.5 / 50%"})),_u("label",null,"其它",_u("input",{value:y.notes,onChange:(E)=>_((D)=>({...D,notes:E.target.value}))})),_u("div",{className:"inline-actions"},_u("button",{type:"submit",className:"primary-btn",disabled:n.saving,"data-testid":"project-manager-save-button"},n.saving?"保存中":y.id?"保存修改":"创建项目"),_u("button",{type:"button",className:"ghost-btn",onClick:()=>_({...C9})},"清空"),y.id?_u("button",{type:"button",className:"danger-btn",disabled:n.saving,onClick:L,"data-testid":"project-manager-delete-button"},"删除"):null)),_u("div",{className:"project-manager-import"},_u("p",{className:"muted paragraph"},"浏览器只访问 UniDesk frontend;后端通过同源用户服务代理写入主 PostgreSQL,不暴露 4233 公网端口。"),_u("label",{className:"file-import"},n.importing?"导入中...":"导入 Excel",_u("input",{type:"file",accept:".xlsx",onChange:w,disabled:n.importing,"data-testid":"project-manager-import-input"}))))))}var Z8=Pu(qf(),1);var Au=Z8.default.createElement,{useEffect:VS}=Z8.default,al=Z8.default.useState;function DS({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return Au("span",{className:`status-badge ${l}`},f||u||"unknown")}function T8({label:u,value:f,hint:l,tone:r}){return Au("article",{className:`metric-card ${r||""}`},Au("div",{className:"metric-label"},u),Au("div",{className:"metric-value"},f),Au("div",{className:"metric-hint"},l))}function h9({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Au("section",{className:`panel ${n||""}`},Au("div",{className:"panel-head"},Au("div",null,f?Au("p",{className:"panel-eyebrow"},f):null,Au(nf,{title:u,loading:i})),l?Au("div",{className:"panel-actions"},l):null),Au("div",{className:"panel-body"},r))}function mL({title:u,data:f,onOpen:l,testId:r}){return Au("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function E8({title:u,text:f}){return Au("div",{className:"empty-state"},Au("strong",null,u),Au("span",null,f))}function XS(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function YS(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function SS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function ML(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function pS(u){if(!Number.isFinite(u))return"--";return`${u.toFixed(1)}%`}function Qy(u,f){return`${u}/microservices/todo-note/proxy${f}`}function CL(u){return u.reduce((f,l)=>{let r=CL(Array.isArray(l.children)?l.children:[]),n=Boolean(l.completed);return{total:f.total+1+r.total,completed:f.completed+(n?1:0)+r.completed,active:f.active+(n?0:1)+r.active}},{total:0,completed:0,active:0})}function v9(u,f){let l=f==="all"||(f==="completed"?Boolean(u.completed):!u.completed),r=Array.isArray(u.children)?u.children:[];return l||r.some((n)=>v9(n,f))}function PL(u){return Array.isArray(u?.instances)?u.instances:[]}function b9(u,f){for(let l of u){if(l?.id===f)return Array.isArray(l.children)?l.children:[];let r=b9(Array.isArray(l?.children)?l.children:[],f);if(r.length>0)return r}return[]}function RL({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((g)=>g.id==="todo-note")||null,[n,i]=al(null),[y,_]=al(null),[$,A]=al(""),[c,j]=al(null),[F,U]=al("all"),[Q,L]=al(13),[w,J]=al(""),[N,q]=al(""),[W,z]=al(""),[Z,H]=al(""),[E,D]=al(""),[h,V]=al(!1),[Y,p]=al(""),[O,m]=al(null),X=PL(y),v=CL(Array.isArray(c?.todos)?c.todos:[]),T=r?XS(r):{},S=r?SS(r):{},k=r?YS(r):{};async function I(g=$){let[Qu,Tu]=await Promise.all([Eu(`${l}/microservices/todo-note/health`),Eu(Qy(l,"/api/instances"))]);i(Qu),_(Tu);let Zu=PL(Tu),Xu=Zu.some((uf)=>uf.id===g)?g:Zu[0]?.id||"";return A(Xu),Xu}async function b(g=$){if(!g){j(null);return}let Qu=await Eu(Qy(l,`/api/instances/${encodeURIComponent(g)}`));j(Qu)}async function o(g=$){if(!r)return;V(!0),p("");try{let Qu=await I(g);await b(Qu),m(new Date)}catch(Qu){p(Hu(Qu,"Todo Note 加载失败"))}finally{V(!1)}}async function s(g){if(!$)return null;p("");try{let Qu=await Eu(Qy(l,`/api/instances/${encodeURIComponent($)}/actions`),{method:"POST",body:JSON.stringify({action:g})});return j(Qu),await I($),Qu}catch(Qu){return p(Hu(Qu,"Todo 操作失败")),null}}async function x(g){g.preventDefault();let Qu=w.trim();if(!Qu)return;V(!0),p("");try{let Tu=await Eu(Qy(l,"/api/instances"),{method:"POST",body:JSON.stringify({name:Qu})});J(""),await o(Tu.id)}catch(Tu){p(Hu(Tu,"创建清单失败"))}finally{V(!1)}}async function fu(g){if(!window.confirm("确认删除这个 Todo Note 清单?"))return;V(!0),p("");try{await Eu(Qy(l,`/api/instances/${encodeURIComponent(g)}`),{method:"DELETE"}),await o($===g?"":$)}catch(Qu){p(Hu(Qu,"删除清单失败"))}finally{V(!1)}}async function $u(g){g.preventDefault();let Qu=N.trim();if(!Qu)return;q(""),await s({type:"addTodo",title:Qu})}async function tu(g){if(!$)return;p("");try{let Qu=await Eu(Qy(l,`/api/instances/${encodeURIComponent($)}/${g}`),{method:"POST",body:JSON.stringify({})});j(Qu),await I($)}catch(Qu){p(Hu(Qu,`${g} 失败`))}}function ju(g){z(g.id),H(String(g.title||""))}async function Gu(g){let Qu=Z.trim();if(z(""),H(""),Qu)await s({type:"updateTodoTitle",todoId:g,title:Qu})}async function qu(g){let Tu=window.prompt("新增子任务标题")?.trim();if(!Tu)return;let Zu=b9(Array.isArray(c?.todos)?c.todos:[],g),Xu=new Set(Zu.map((Pf)=>Pf.id)),uf=await s({type:"addTodo",title:Tu,parentId:g,targetIndex:0});if(!uf)return;let _f=b9(Array.isArray(uf?.todos)?uf.todos:[],g),Jf=_f.find((Pf)=>!Xu.has(Pf.id));if(Jf&&_f[0]?.id!==Jf.id)await s({type:"moveTodo",todoId:Jf.id,targetParentId:g,targetIndex:0})}async function P(g,Qu){if(!E)return;let Tu={type:"moveTodo",todoId:E,targetIndex:Qu};if(g)Tu.targetParentId=g;D(""),await s(Tu)}if(VS(()=>{o()},[r?.id,r?.runtime?.providerStatus]),!r)return Au(E8,{title:"Todo Note 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=todo-note"});let e=X.find((g)=>g.id===$)||null,uu=Array.isArray(c?.todos)?c.todos:[],Wu=uu.map((g,Qu)=>({todo:g,index:Qu})).filter((g)=>v9(g.todo,F));return Au("div",{className:"todo-note-page","data-testid":"todo-note-page"},Au(h9,{title:"Todo Note 工作台",eyebrow:"Main Server 用户服务",loading:h,actions:Au("div",{className:"panel-actions"},Au("button",{type:"button",className:"ghost-btn",disabled:h,onClick:()=>o($),"data-testid":"todo-note-refresh-button"},h?"刷新中":"刷新"),Au(mL,{title:"Todo Note 用户服务",data:r,onOpen:f,testId:"raw-todo-note-service"}))},Au("div",{className:"todo-note-hero"},Au("div",null,Au("div",{className:"node-version-line"},Au(DS,{status:T.providerStatus==="online"?"online":"warn"},T.providerStatus||"unknown"),Au("span",null,r.providerId),Au("span",null,k.public?"公网暴露":"仅 UniDesk frontend 代理访问"),Au("span",null,n?.ok?"Health OK":"Health --")),Au("p",{className:"muted paragraph"},r.description)),Au("div",{className:"microservice-ref-card"},Au("span",null,"Repo"),Au("strong",null,S.url||"--"),Au("code",null,S.commitId||"--")),Au("div",{className:"microservice-ref-card"},Au("span",null,"Main Server Docker"),Au("strong",null,`${k.nodeBindHost||"--"}:${k.nodePort||"--"}`),Au("code",null,`${S.composeService||"--"} / ${S.containerName||"--"}`))),Au(yf,{error:Y,wide:!0})),Au("div",{className:"todo-note-layout"},Au(h9,{title:"清单",eyebrow:`${X.length} Instances`,className:"todo-list-panel",loading:h},Au("form",{className:"todo-create-list",onSubmit:x},Au("input",{placeholder:"新清单名称",value:w,onChange:(g)=>J(g.target.value),"aria-label":"新清单名称"}),Au("button",{type:"submit",className:"ghost-btn",disabled:h||!w.trim()},"创建")),X.length===0?Au(E8,{title:"暂无清单",text:"迁移或创建清单后会出现在这里"}):Au("div",{className:"todo-instance-list"},X.map((g)=>Au("button",{key:g.id,type:"button",className:`todo-instance-row ${$===g.id?"active":""}`,onClick:()=>{A(g.id),b(g.id)},"data-testid":`todo-instance-${ML(g.id)}`},Au("strong",null,g.name),Au("span",null,`${g.completedCount??0}/${g.todoCount??0} 完成`),Au("code",null,g.id))))),Au("div",{className:"todo-main-stack"},Au(h9,{title:e?.name||"待选择清单",eyebrow:O?`Updated ${tf(O)}`:"Todo Tree",loading:h,actions:c?Au("div",{className:"panel-actions"},Au("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"renameInstance",name:window.prompt("清单新名称",c.name)||c.name})},"重命名"),Au("button",{type:"button",className:"ghost-btn danger",onClick:()=>fu($)},"删除清单"),Au(mL,{title:`Todo Instance ${$}`,data:c,onOpen:f,testId:"raw-todo-instance"})):null},!c?Au(E8,{title:"未选择清单",text:"左侧选择一个 Todo Note 清单"}):Au("div",{className:"todo-workbench",style:{"--todo-font-size":`${Q}px`}},Au("div",{className:"todo-toolbar"},Au("form",{className:"todo-add-form",onSubmit:$u},Au("input",{placeholder:"新增根任务",value:N,onChange:(g)=>q(g.target.value),"aria-label":"新增根任务"}),Au("button",{type:"submit",className:"ghost-btn",disabled:!N.trim()},"新增")),Au("div",{className:"todo-filter-strip"},["all","active","completed"].map((g)=>Au("button",{key:g,type:"button",className:`todo-filter ${F===g?"active":""}`,onClick:()=>U(g)},g==="all"?"全部":g==="active"?"未完成":"已完成"))),Au("div",{className:"todo-toolbar-actions"},Au("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"setAllTodosExpanded",expanded:!0})},"全部展开"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"setAllTodosExpanded",expanded:!1})},"全部收起"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>tu("undo")},"撤销"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>tu("redo")},"重做"),Au("label",{className:"todo-font-control"},"字号",Au("input",{type:"range",min:11,max:18,value:Q,onChange:(g)=>L(Number(g.target.value))})))),Au("div",{className:"todo-stats-grid"},Au(T8,{label:"总任务",value:v.total,hint:`${X.length} lists`}),Au(T8,{label:"已完成",value:v.completed,hint:`${pS(v.total?v.completed/v.total*100:0)}`,tone:"ok"}),Au(T8,{label:"未完成",value:v.active,hint:F==="active"?"当前筛选":"active tasks",tone:v.active>0?"warn":"ok"}),Au(T8,{label:"历史指针",value:c.historyPointer??0,hint:"undo / redo"})),Au("div",{className:"todo-root-drop",onDragOver:(g)=>g.preventDefault(),onDrop:(g)=>{g.preventDefault(),P(null,uu.length)}},"拖到这里可移为根任务末尾"),Au("div",{className:"todo-tree","data-testid":"todo-note-tree"},Wu.length===0?Au(E8,{title:"没有匹配任务",text:"调整筛选或新增任务"}):Wu.map(({todo:g,index:Qu})=>Au(xL,{key:g.id,todo:g,depth:0,parentId:null,index:Qu,siblingCount:uu.length,filter:F,editingId:W,editingTitle:Z,setEditingTitle:H,beginEdit:ju,saveEdit:Gu,applyTodoAction:s,addChild:qu,dragTodoId:E,setDragTodoId:D,dropTodo:P}))))))))}function xL(u){let{todo:f,depth:l,parentId:r,index:n,siblingCount:i,filter:y,editingId:_,editingTitle:$,setEditingTitle:A,beginEdit:c,saveEdit:j,applyTodoAction:F,addChild:U,dragTodoId:Q,setDragTodoId:L,dropTodo:w}=u,J=Array.isArray(f.children)?f.children:[],N=J.map((z,Z)=>({child:z,childIndex:Z})).filter((z)=>v9(z.child,y)),q=_===f.id,W=r||null;return Au("div",{className:"todo-row-wrap"},Au("article",{className:`todo-row ${f.completed?"completed":""} ${Q===f.id?"dragging":""}`,style:{"--todo-depth":l},draggable:!0,onDragStart:(z)=>{L(f.id),z.dataTransfer.effectAllowed="move"},onDragOver:(z)=>z.preventDefault(),onDrop:(z)=>{z.preventDefault(),w(f.id,J.length)},"data-testid":`todo-row-${ML(f.id)}`},Au("button",{type:"button",className:"todo-expand",disabled:J.length===0,onClick:()=>F({type:"toggleTodoExpanded",todoId:f.id})},J.length===0?"·":f.expanded?"▾":"▸"),Au("input",{type:"checkbox",checked:Boolean(f.completed),onChange:()=>F({type:"toggleTodoCompleted",todoId:f.id}),"aria-label":`完成 ${f.title}`}),Au("div",{className:"todo-title-cell",onDoubleClick:()=>c(f)},q?Au("div",{className:"todo-edit-inline"},Au("input",{value:$,autoFocus:!0,onChange:(z)=>A(z.target.value),onKeyDown:(z)=>{if(z.key==="Enter")j(f.id);if(z.key==="Escape")c({id:"",title:""})}}),Au("button",{type:"button",className:"ghost-btn",onClick:()=>j(f.id)},"保存")):Au("strong",null,f.title||"Untitled"),Au("div",{className:"todo-meta-line"},Au("span",null,`子项 ${J.length}`),Au("span",null,`更新 ${Nu(f.updatedAt)}`),f.reminderAt?Au("span",{className:"todo-reminder"},`提醒 ${Nu(f.reminderAt)}`):Au("span",null,"无提醒"))),Au("input",{className:"todo-reminder-input",type:"datetime-local",value:a8(f.reminderAt),onChange:(z)=>F({type:"setTodoReminder",todoId:f.id,reminderAt:Y7(z.target.value)})}),Au("div",{className:"todo-row-actions"},Au("button",{type:"button",className:"ghost-btn",onClick:()=>c(f)},"编辑"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>U(f.id)},"子项"),Au("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:n-1})},"上移"),Au("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:0})},"置顶"),Au("button",{type:"button",className:"ghost-btn",disabled:n>=i-1,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:n+1})},"下移"),Au("button",{type:"button",className:"ghost-btn",disabled:!r,onClick:()=>F({type:"moveTodo",todoId:f.id,targetIndex:9999})},"提升"),Au("button",{type:"button",className:"ghost-btn danger",onClick:()=>F({type:"deleteTodo",todoId:f.id})},"删除"))),f.expanded&&N.length>0?Au("div",{className:"todo-children"},N.map(({child:z,childIndex:Z})=>Au(xL,{key:z.id,todo:z,depth:l+1,parentId:f.id,index:Z,siblingCount:J.length,filter:y,editingId:_,editingTitle:$,setEditingTitle:A,beginEdit:c,saveEdit:j,applyTodoAction:F,addChild:U,dragTodoId:Q,setDragTodoId:L,dropTodo:w}))):null)}var hL=Pu(qf(),1),xn=hL.default.createElement;function bL({title:u,items:f,actions:l,className:r,testId:n}){let i=Array.isArray(f)?f:[];return xn("section",{className:`top-status-bar ${r||""}`,"data-testid":n},xn("div",{className:"top-status-main"},u?xn("strong",{className:"top-status-title"},u):null,xn("div",{className:"top-status-chips"},i.map((y,_)=>xn("span",{key:y?.key||`${y?.label||"status"}-${_}`,className:`top-status-chip ${y?.tone||""}`,"data-testid":y?.testId},y?.label?xn("b",null,y.label):null,xn("span",null,y?.value??"--"))))),l?xn("div",{className:"top-status-actions"},l):null)}var S$=Pu(qf(),1);var hf=S$.default.createElement;function vL({onClose:u}){let{notifications:f,removeNotification:l,clearNotifications:r}=Vl(),n=S$.default.useRef(null);if(S$.default.useEffect(()=>{let i=(y)=>{if(n.current&&!n.current.contains(y.target))u()};return document.addEventListener("mousedown",i),()=>document.removeEventListener("mousedown",i)},[u]),f.length===0)return hf("div",{className:"notification-popup",ref:n},hf("div",{className:"notification-popup-header"},hf("span",null,"通知"),hf("button",{className:"notification-popup-close",onClick:u},"×")),hf("div",{className:"notification-popup-empty"},"暂无通知"));return hf("div",{className:"notification-popup",ref:n},hf("div",{className:"notification-popup-header"},hf("span",null,`通知 (${f.length})`),hf("div",{className:"notification-popup-actions"},hf("button",{className:"notification-popup-clear",onClick:r},"清空"),hf("button",{className:"notification-popup-close",onClick:u},"×"))),hf("div",{className:"notification-popup-list"},f.slice().reverse().map((i)=>hf("div",{key:i.id,className:`notification-item ${i.type}`},hf("span",{className:"notification-item-icon"},i.type==="success"?"✓":"×"),hf("span",{className:"notification-item-message"},i.message),hf("button",{className:"notification-item-dismiss",onClick:()=>l(i.id)},"×")))))}function kL({notification:u}){let{removeNotification:f}=Vl();return S$.default.useEffect(()=>{let l=setTimeout(()=>{f(u.id)},3000);return()=>clearTimeout(l)},[u.id,f]),hf("div",{className:`notification-banner ${u.type}`,role:"alert"},hf("span",{className:"notification-banner-icon"},u.type==="success"?"✓":"×"),hf("span",{className:"notification-banner-message"},u.message),hf("button",{className:"notification-banner-dismiss",onClick:()=>f(u.id)},"×"))}function nw(u,f){let l=document.getElementById("root")?.getAttribute(u);if(!l)return f;try{let r=JSON.parse(l);return typeof r==="object"&&r!==null&&!Array.isArray(r)?r:f}catch{return f}}var gu=nw("data-config",{apiBaseUrl:"/api",authUsername:"admin"}),mS=nw("data-codex-overview",null),t=bn.default.createElement,{useEffect:F0,useMemo:P$}=bn.default,hu=bn.default.useState,s9=bn.default.createContext(!1),Vr=xQ(u6),PS={id:"code-queue",name:"Code Queue",providerId:"main-server",description:"Code Queue",repository:{containerName:"code-queue-backend"},backend:{nodeBaseUrl:"http://code-queue:4222",nodeBindHost:"code-queue",nodePort:4222,public:!1},runtime:{providerStatus:"loading",providerName:"main-server"}};function IL(){return typeof document>"u"||document.visibilityState!=="hidden"}function MS(u,f){if(u==="ops"&&f==="status")return 5000;if(u==="nodes"&&f==="monitor")return 5000;if(u==="tasks"&&(f==="dispatch"||f==="scheduled"||f==="pending"))return 5000;if(u==="nodes"||u==="ops")return 1e4;if(u==="apps")return 15000;if(u==="tasks")return 15000;return 30000}async function CS(u){if(!u?._summaryOnly||!u?.id)return u;return(await Eu(`${gu.apiBaseUrl}/tasks/${encodeURIComponent(String(u.id))}`))?.task||u}function M$(u){return u?._summaryOnly?{...u,_loadRaw:()=>CS(u)}:u}function x0(u){if(!Number.isFinite(u))return"--";let f=Math.max(0,u);if(f===0)return"0s";if(f<0.01)return"<0.01s";if(f<0.1)return`${f.toFixed(2)}s`;if(f<1)return`${f.toFixed(1)}s`;if(f<10&&!Number.isInteger(f))return`${f.toFixed(1)}s`;if(f<60)return`${Math.round(f)}s`;let l=Math.floor(f);if(l<3600)return`${Math.floor(l/60)}m ${l%60}s`;return`${Math.floor(l/3600)}h ${Math.floor(l%3600/60)}m`}function Qr(u){let f=Number(u);if(!Number.isFinite(f))return"--";if(f<1)return`${Math.max(0,f).toFixed(1)}ms`;if(f<10)return`${f.toFixed(1)}ms`;if(f<1000)return`${Math.round(f)}ms`;return x0(f/1000)}function zl(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=["B","KB","MB","GB","TB"],r=f,n=0;while(r>=1024&&n0)return l[r]}return"任务失败但 provider 未返回明确原因"}function M1(u){if(u===null||u===void 0)return"--";if(typeof u==="boolean")return u?"是":"否";if(typeof u==="number")return String(u);if(typeof u==="string")return u.length>80?`${u.slice(0,77)}...`:u;if(Array.isArray(u))return`${u.length} 项`;if(typeof u==="object")return`${Object.keys(u).length} 字段`;return String(u)}function xS(u,f){let l=u.replace(/[-_\s]/g,"").toLowerCase(),r=l==="ts"||l.endsWith("at")||l.endsWith("timestamp")||l.endsWith("heartbeat");if((typeof f==="string"||typeof f==="number")&&r){let n=Nu(f);if(n!=="--")return n}if(u==="bodyText"&&typeof f==="string")return`${/^\s*[{[]/.test(f)?"JSON":"HTTP"} body ${f.length} chars`;return M1(f)}function _w(u){if(!u||typeof u!=="object"||Array.isArray(u))return[];return Object.entries(u)}function ol(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function o9(u,f){return u&&typeof u==="object"&&!Array.isArray(u)?u[f]:void 0}function H8(u,f,l="未知"){let r=o9(u?.labels,f);return typeof r==="string"&&r.length>0?r:l}function $w(u){return H8(u,"providerGatewayVersion")}function m$(u){return H8(u,"providerGatewayUpgradePolicy")}function gL(u){return H8(u,"providerGatewayStartedAt","")}function tw(u){let f=o9(u?.labels,"unideskCapabilities");if(typeof f==="string")return f.split(",").map((l)=>l.trim()).filter(Boolean);return Array.isArray(f)?f.filter((l)=>typeof l==="string"):[]}function Aw(u,f){return tw(u).includes(f)}function sL(u,f){let l=o9(u?.labels,f);return l===!0||l==="true"||l==="1"}function hS(u){if(!Aw(u,"host.ssh"))return{tone:"fail",label:"不可用",detail:"未声明 host.ssh"};if(!sL(u,"hostSshConfigured"))return{tone:"warn",label:"未配置",detail:"缺少 SSH 环境变量"};if(!sL(u,"hostSshKeyPresent"))return{tone:"warn",label:"缺 key",detail:"私钥未挂载"};return{tone:"ok",label:"可用",detail:H8(u,"hostSshTarget","host.ssh ready")}}function bS(u){if(!Aw(u,"provider.upgrade"))return{tone:"fail",label:"不可用",detail:"未声明 provider.upgrade"};let f=m$(u);if(f!=="always-enabled")return{tone:"warn",label:"待确认",detail:`策略 ${f}`};return{tone:"ok",label:"可用",detail:"always-enabled"}}function d9(u){let f=typeof u==="string"&&u.length>0?u:"未知";if(f==="未知")return"版本未知";return f.startsWith("v")?f:`v${f}`}function cw(u){return u?.payload&&typeof u.payload==="object"&&!Array.isArray(u.payload)?u.payload:{}}function B8(u){return u?.result&&typeof u.result==="object"&&!Array.isArray(u.result)?u.result:{}}function O8(u){let f=cw(u),l=B8(u);return(f.mode??l.mode)==="schedule"?"schedule":"plan"}function vS(u){let f=cw(u).source;return typeof f==="string"&&f.length>0?f:"unknown"}function kS(u){let f=B8(u),l=f.plan&&typeof f.plan==="object"&&!Array.isArray(f.plan)?f.plan:{},r=f.policy??l.policy;return typeof r==="string"&&r.length>0?r:"--"}function jw(u){let f=B8(u),l=f.plan&&typeof f.plan==="object"&&!Array.isArray(f.plan)?f.plan:{},r=f.targetProviderGatewayVersion??f.providerGatewayVersion??l.targetProviderGatewayVersion??l.providerGatewayVersion;return typeof r==="string"&&r.length>0?d9(r):"版本未知"}function Fw(u){if(String(u?.status||"").toLowerCase()==="failed")return yw(u);if(Ny(u))return"等待 provider 回传升级终态";let l=B8(u);if(typeof l.updaterContainerId==="string"&&l.updaterContainerId.length>0)return`updater ${l.updaterContainerId.slice(0,18)}`;if(typeof l.message==="string"&&l.message.length>0)return l.message;if(l.plan)return"升级计划已生成";return"无升级结果摘要"}function Jw(u,f){return u.filter((l)=>l?.providerId===f&&l?.command==="provider.upgrade").sort((l,r)=>(J0(r.updatedAt)??0)-(J0(l.updatedAt)??0))}function IS(u){return u.find((f)=>O8(f)==="schedule")||u[0]||null}function Uw(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function aL(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function gS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function wf({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return t("span",{className:`status-badge ${l}`},f||u||"unknown")}function cf({label:u,value:f,hint:l,tone:r,onClick:n,testId:i}){let y=typeof n==="function";return t("article",{className:`metric-card ${r||""} ${y?"clickable":""}`,role:y?"button":void 0,tabIndex:y?0:void 0,"data-testid":i,onClick:n,onKeyDown:y?(_)=>{if(_.key==="Enter"||_.key===" ")_.preventDefault(),n()}:void 0},t("div",{className:"metric-label"},u),t("div",{className:"metric-value"},f),t("div",{className:"metric-hint"},l))}function au({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){let y=bn.default.useContext(s9),_=Boolean(i)||y;return t("section",{className:`panel ${n||""}`},t("div",{className:"panel-head"},t("div",null,f?t("p",{className:"panel-eyebrow"},f):null,t(nf,{title:u,loading:_})),l?t("div",{className:"panel-actions"},l):null),t("div",{className:"panel-body"},r))}function bf({title:u,data:f,onOpen:l,testId:r}){let[n,i]=hu(!1),y=f&&typeof f==="object"&&typeof f._loadRaw==="function"?f._loadRaw:null;async function _(){if(!y){l(u,f);return}i(!0);try{l(u,await y())}catch($){l(u,{ok:!1,error:Hu($,"读取原始 JSON 失败"),fallback:f})}finally{i(!1)}}return t("button",{type:"button",className:"ghost-btn","data-testid":r,disabled:n,onClick:()=>void _()},n?"读取中":"查看原始JSON")}function sS({raw:u,onClose:f}){if(!u)return null;return t("div",{className:"modal-backdrop",role:"presentation"},t("section",{className:"raw-dialog",role:"dialog","aria-modal":"true","aria-label":u.title},t("div",{className:"raw-dialog-head"},t("h2",null,u.title),t("button",{type:"button",className:"ghost-btn",onClick:f},"关闭")),t("pre",{className:"raw-json","data-testid":"raw-json"},JSON.stringify(u.data,null,2))))}function Qw({labels:u,limit:f=8}){let l=_w(u).slice(0,f);if(l.length===0)return t("span",{className:"muted"},"无标签");return t("div",{className:"chip-row"},l.map(([r,n])=>t("span",{key:r,className:"data-chip"},t("b",null,r),t("span",null,M1(n)))))}function qy({node:u}){let f=$w(u);return t("span",{className:`version-chip ${f==="未知"?"unknown":""}`,"data-testid":`gateway-version-${ol(u?.providerId||"unknown")}`},d9(f))}function oL({title:u,state:f,testId:l}){return t("span",{className:`capability-badge ${f.tone}`,title:f.detail,"data-testid":l},t("b",null,u),t("strong",null,f.label),t("small",null,f.detail))}function e9({node:u}){let f=ol(u?.providerId||"unknown");return t("div",{className:"node-availability-strip"},t(oL,{title:"SSH 透传",state:hS(u),testId:`ssh-availability-${f}`}),t(oL,{title:"远程更新",state:bS(u),testId:`upgrade-availability-${f}`}))}function vn({data:u,empty:f="无数据"}){if(u===null||u===void 0)return t("span",{className:"muted"},f);if(typeof u!=="object")return t("span",{className:"summary-value"},M1(u));if(Array.isArray(u))return t("span",{className:"summary-value"},`${u.length} 项列表`);let l=Object.entries(u).slice(0,5);if(l.length===0)return t("span",{className:"muted"},f);return t("div",{className:"summary-grid"},l.map(([r,n])=>t("span",{key:r,className:"summary-item"},t("b",null,r),t("span",null,xS(r,n)))))}function Ff({title:u,text:f}){return t("div",{className:"empty-state"},t("strong",null,u),t("span",null,f))}function aS({onLogin:u}){let[f,l]=hu(gu.authUsername||"admin"),[r,n]=hu(""),[i,y]=hu(""),[_,$]=hu(!1);async function A(c){c.preventDefault(),$(!0),y("");try{let j=await Eu("/login",{method:"POST",body:JSON.stringify({username:f,password:r})});u(j)}catch(j){y(Hu(j,"登录失败"))}finally{$(!1)}}return t("main",{className:"login-screen","data-testid":"login-screen"},t("section",{className:"login-card"},t("div",{className:"login-brand"},t("span",{className:"brand-mark"},"UD"),t("div",null,t("h1",null,"UniDesk"),t("p",null,"Control Plane Login"))),t("form",{className:"login-form",onSubmit:A},t("label",null,"账号",t("input",{name:"username",autoComplete:"username",value:f,onChange:(c)=>l(c.target.value)})),t("label",null,"密码",t("input",{name:"password",type:"password",autoComplete:"current-password",value:r,onChange:(c)=>n(c.target.value)})),t(yf,{error:i}),t("button",{type:"submit",disabled:_},_?"登录中":"登录")),t("div",{className:"login-note"},"默认账号由 config.json 注入;公网入口只暴露前端登录面。")))}function oS({connection:u,lastRefresh:f,onRefresh:l,onLogout:r,session:n,clock:i,activeStatusItems:y=[],onNotificationToggle:_,unreadCount:$=0}){let A=[{key:"core",label:"核心",value:u.text,tone:u.ok?"ok":"fail",testId:"conn-text"},...Array.isArray(y)?y:[],{key:"refresh",label:"刷新",value:f?tf(f):"未刷新"},{key:"clock",label:y3,value:tf(i)},{key:"user",label:"用户",value:n?.user?.username||"--",tone:"user"}];return t("header",{className:"topbar"},t("div",null,t("p",{className:"eyebrow"},"Distributed Work Platform"),t("h1",null,"UniDesk 控制平面")),t(bL,{className:"global-top-status",title:"状态",items:A,actions:[t("button",{key:"notification",type:"button",className:`notification-icon-btn ${$>0?"has-unread":""}`,onClick:_,"aria-label":"通知"},"\uD83D\uDD14",$>0?t("span",{key:"badge",className:"notification-badge"},$>99?"99+":$):null),t("button",{key:"refresh",type:"button",className:"ghost-btn",onClick:l},"刷新"),t("button",{key:"logout",type:"button",className:"ghost-btn danger",onClick:r},"退出")]}))}function dS(u){return!u.defaultPrevented&&u.button===0&&!u.metaKey&&!u.altKey&&!u.ctrlKey&&!u.shiftKey&&u.currentTarget.target!=="_blank"}function qw({moduleId:u,tabId:f,className:l,active:r=!1,title:n,testId:i,onNavigate:y,children:_}){let $=f6(Vr,u,f);return t("a",{href:$,role:"button",className:l,title:n,"aria-current":r?"page":void 0,"data-testid":i,"data-route":$,onClick:(A)=>{if(!dS(A))return;A.preventDefault(),y(u,f)}},_)}function eS({activeModule:u,activeTabs:f,onNavigate:l,collapsed:r,onToggle:n}){return t("aside",{className:`rail ${r?"collapsed":""}`,"aria-label":"主模块"},t("div",{className:"brand"},t("span",{className:"brand-mark"},"UD"),t("span",{className:"brand-text"},"UniDesk"),t("button",{type:"button",className:"rail-toggle",onClick:n,"aria-label":r?"展开左侧边栏":"收起左侧边栏","data-testid":"rail-toggle"},r?"»":"«")),u6.map((i)=>{let y=f[i.id]||b_[i.id]||i.tabs[0]?.id||"";return t(qw,{key:i.id,moduleId:i.id,tabId:y,className:`module ${u===i.id?"active":""}`,active:u===i.id,title:i.label,onNavigate:l},t("span",{className:"module-code"},i.code),t("span",null,i.label))}))}function up({module:u,activeTab:f,onNavigate:l}){return t("nav",{className:"tabs","aria-label":`${u.label} 子功能`},u.tabs.map((r)=>t(qw,{key:r.id,moduleId:u.id,tabId:r.id,className:`tab ${f===r.id?"active":""}`,active:f===r.id,onNavigate:l},r.label)))}function fp({data:u,onRaw:f,onNavigate:l}){let r=u.overview||{},n=u.nodes.filter((U)=>U.status==="online"),i=u.pendingTasks||u.tasks.filter(Ny),y=r.pendingTaskCount??i.length,_=u.tasks.slice(0,5),$=r.pgdata||{},A=r.microserviceAvailability||{},c=Mu(A.totalCount),j=Mu(A.healthyCount),F=Mu(A.unhealthyCount);return t("div",{className:"page-grid overview-grid","data-testid":"overview-page"},t(au,{title:"核心指标",eyebrow:"Control"},t("div",{className:"metric-grid"},t(cf,{label:"数据库",value:r.dbReady?"READY":"WAIT",hint:"PostgreSQL internal network",tone:r.dbReady?"ok":"warn"}),t(cf,{label:"PGDATA",value:zl($.databaseBytes),hint:`${$.volumeName||"unidesk_pgdata_10gb"} / ${$.databasePretty||"--"}`,tone:"ok",testId:"pgdata-usage-card"}),t(cf,{label:"在线节点",value:r.onlineNodeCount??0,hint:`${r.nodeCount??0} registered`,tone:"ok"}),t(cf,{label:"WebSocket",value:r.activeSocketCount??0,hint:"Provider ingress sockets"}),t(cf,{label:"用户服务可用",value:c>0?`${j}/${c}`:"--",hint:c>0?`healthyCount ${j} · unhealthyCount ${F}`:"strict /health probes",tone:c>0&&F===0?"ok":"warn",testId:"microservice-availability-card"}),t(cf,{label:"待处理任务",value:y,hint:y>0?"点击查看具体任务":`timeout ${x0(Math.floor((r.taskPendingTimeoutMs??0)/1000))}`,tone:y>0?"warn":"ok",onClick:()=>l("tasks","pending"),testId:"pending-task-card"}))),t(au,{title:"本机 Provider",eyebrow:"Self Connected"},n.length===0?t(Ff,{title:"暂无在线节点",text:"provider-gateway 未完成自接入"}):t("div",{className:"node-card-list"},n.slice(0,4).map((U)=>t(lp,{key:U.providerId,node:U,onRaw:f})))),t(au,{title:"待处理任务明细",eyebrow:`${y} Pending`,actions:t("button",{type:"button",className:"ghost-btn",onClick:()=>l("tasks","pending"),"data-testid":"pending-task-detail-link"},"进入任务调度")},i.length===0?t(Ff,{title:"当前无待处理",text:"queued / dispatched / running 超时后会自动转为 failed,避免总览长期卡住"}):t("div",{className:"compact-list"},i.slice(0,5).map((U)=>t(fw,{key:U.id,task:U,onRaw:f})))),t(au,{title:"最近任务",eyebrow:"Dispatch"},_.length===0?t(Ff,{title:"暂无任务",text:"可以在任务调度模块发起 docker.ps 或 echo"}):t("div",{className:"compact-list"},_.map((U)=>t(fw,{key:U.id,task:U,onRaw:f})))))}function lp({node:u,onRaw:f}){return t("article",{className:"node-card"},t("div",{className:"node-card-head"},t("div",null,t("strong",null,u.name),t("code",null,u.providerId)),t(wf,{status:u.status})),t("div",{className:"node-version-line"},t(qy,{node:u}),t("span",null,`升级策略 ${m$(u)}`)),t(e9,{node:u}),t(Qw,{labels:u.labels,limit:6}),t("div",{className:"node-card-foot"},t("span",null,`心跳 ${Nu(u.lastHeartbeat)}`),t(bf,{title:`Provider ${u.providerId}`,data:u,onOpen:f,testId:`raw-node-${ol(u.providerId)}`})))}function rp({events:u,onRaw:f}){return t(au,{title:"事件摘要",eyebrow:"Latest 100"},u.length===0?t(Ff,{title:"暂无事件",text:"Provider 注册、心跳超时和任务状态会写入事件流"}):t("div",{className:"table-wrap"},t("table",null,t("thead",null,t("tr",null,t("th",null,"ID"),t("th",null,"类型"),t("th",null,"来源"),t("th",null,"摘要"),t("th",null,"时间"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.id},t("td",null,t("code",null,l.id)),t("td",null,t(wf,{status:l.type},l.type)),t("td",null,t("code",null,l.source)),t("td",null,t(vn,{data:l.payload})),t("td",null,Nu(l.createdAt)),t("td",null,t(bf,{title:`Event ${l.id}`,data:l,onOpen:f}))))))))}function np({logs:u,onRaw:f}){return t(au,{title:"服务日志",eyebrow:"Core Recent"},u.length===0?t(Ff,{title:"暂无日志",text:"backend-core 内存日志会在请求和 provider 事件后出现"}):t("div",{className:"log-list"},u.slice(-80).reverse().map((l,r)=>t("article",{key:r,className:`log-row ${l.level||"info"}`},t("span",null,Nu(l.ts)),t("b",null,l.level||"info"),t("strong",null,l.message||"log"),t(vn,{data:l.data,empty:"无附加字段"}),t(bf,{title:`Log ${l.message||r}`,data:l,onOpen:f})))))}function ip({nodes:u,onRaw:f}){return t(au,{title:"节点清单",eyebrow:`${u.length} Providers`},u.length===0?t(Ff,{title:"暂无 Provider 节点",text:"确认 provider-gateway 已连接 provider ingress"}):t("div",{className:"table-wrap"},t("table",{className:"node-list-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"Provider"),t("th",null,"网关版本"),t("th",null,"运维可用性"),t("th",null,"资源标签"),t("th",null,"连接时间"),t("th",null,"最后心跳"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.providerId},t("td",null,t(wf,{status:l.status})),t("td",null,t("strong",null,l.name),t("code",null,l.providerId)),t("td",null,t("div",{className:"gateway-cell"},t(qy,{node:l}),t("span",null,m$(l)))),t("td",null,t(e9,{node:l})),t("td",null,t(Qw,{labels:l.labels,limit:5})),t("td",null,Nu(l.connectedAt)),t("td",null,Nu(l.lastHeartbeat)),t("td",null,t(bf,{title:`Provider ${l.providerId}`,data:l,onOpen:f,testId:`raw-node-table-${ol(l.providerId)}`}))))))))}function yp({nodes:u}){let f=P$(()=>{let l=[];for(let r of u)for(let[n,i]of _w(r.labels))l.push({providerId:r.providerId,name:r.name,key:n,value:i});return l},[u]);return t(au,{title:"资源标签",eyebrow:"Structured Labels"},f.length===0?t(Ff,{title:"暂无标签",text:"provider-gateway 注册消息会同步资源标签"}):t("div",{className:"label-matrix"},f.map((l)=>t("article",{key:`${l.providerId}-${l.key}`,className:"label-card"},t("span",null,l.key),t("strong",null,M1(l.value)),t("code",null,l.providerId)))))}function _p({nodes:u}){return t(au,{title:"心跳状态",eyebrow:"Provider Liveness"},u.length===0?t(Ff,{title:"无心跳",text:"等待 provider 注册和 heartbeat"}):t("div",{className:"heartbeat-list"},u.map((f)=>t("article",{key:f.providerId,className:"heartbeat-row"},t("span",{className:`pulse ${f.status}`}),t("div",null,t("strong",null,f.name),t("code",null,f.providerId)),t("div",null,t("span",null,"connected"),t("b",null,Nu(f.connectedAt))),t("div",null,t("span",null,"last heartbeat"),t("b",null,Nu(f.lastHeartbeat)))))))}function $p({nodes:u,systemStatuses:f,tasks:l,onRaw:r,refresh:n}){let[i,y]=hu(""),_=P$(()=>u.map((L)=>{let w=f.find((J)=>J.providerId===L.providerId);return{...L,systemCurrent:w?.current||null,systemHistory:w?.history||[],systemUpdatedAt:w?.updatedAt||null}}),[u,f]),$=_.find((L)=>L.providerId===i)||_[0]||null;if(F0(()=>{if(!i&&_[0])y(_[0].providerId)},[_.length,i]),!$)return t(Ff,{title:"暂无资源监控",text:"等待 provider 上报 CPU、内存和硬盘指标"});let A=$.systemCurrent,c=$.systemHistory||[],j=A?.cpu||{},F=A?.memory||{},U=A?.disk||{},Q=c.length>0?c:A?[{at:A.collectedAt,cpuPercent:Mu(j.percent),memoryPercent:Mu(F.percent),diskPercent:Mu(U.percent)}]:[];return t("div",{className:"monitor-page","data-testid":"node-monitor-page"},t("div",{className:"docker-node-strip"},_.map((L)=>t("button",{key:L.providerId,type:"button",className:`docker-node-tile ${$.providerId===L.providerId?"active":""}`,onClick:()=>y(L.providerId)},t("span",{className:`pulse ${L.status}`}),t("strong",null,L.name),t("code",null,L.providerId),t("span",null,L.systemCurrent?`CPU ${hn(L.systemCurrent.cpu?.percent)} / MEM ${hn(L.systemCurrent.memory?.percent)}`:"等待指标")))),t("div",{className:"monitor-layout"},t(au,{title:"任务管理器视图",eyebrow:$.name,className:"monitor-main-panel",actions:A?t(bf,{title:`System ${$.providerId}`,data:{current:A,history:c},onOpen:r}):null},!A?t(Ff,{title:"系统指标未上报",text:"provider-gateway 会周期性采集 /proc 与 df,并保存历史曲线"}):t("div",null,t("div",{className:"monitor-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Node Performance"),t("h3",null,$.name),t("div",{className:"docker-meta"},t("span",null,`${j.cores||0} CPU cores`),t("span",null,`load ${Mu(j.load1).toFixed(2)} / ${Mu(j.load5).toFixed(2)} / ${Mu(j.load15).toFixed(2)}`),t("span",null,`memory actual ${zl(F.usedBytes)} / ${zl(F.totalBytes)}`),t("span",null,`disk ${zl(U.usedBytes)} / ${zl(U.totalBytes)}`))),t(wf,{status:A.ok?"online":"warn"},A.ok?"METRICS READY":"METRICS DEGRADED")),t("div",{className:"monitor-chart-grid"},t(I9,{title:"CPU",metricKey:"cpuPercent",current:j.percent,points:Q,detail:`${j.cores||0} cores / load ${Mu(j.load1).toFixed(2)}`,tone:"cpu",testId:"metric-chart-cpu"}),t(I9,{title:"Memory",metricKey:"memoryPercent",current:F.percent,points:Q,detail:`${zl(F.usedBytes)} actual / ${zl(F.cacheBytes)} cache excluded`,tone:"memory",testId:"metric-chart-memory"}),t(I9,{title:"Disk",metricKey:"diskPercent",current:U.percent,points:Q,detail:`${U.path||"/"} mounted ${U.mount||"--"}`,tone:"disk",testId:"metric-chart-disk"})),t("div",{className:"monitor-summary-grid"},t(cf,{label:"CPU 当前",value:hn(j.percent),hint:`history ${Q.length} samples`,tone:"ok"}),t(cf,{label:"实际内存",value:zl(F.usedBytes),hint:`${hn(F.percent)} 不含缓存`}),t(cf,{label:"硬盘已用",value:zl(U.usedBytes),hint:hn(U.percent)}),t(cf,{label:"更新时间",value:Nu($.systemUpdatedAt||A.collectedAt),hint:$.providerId})),t(tp,{current:A,onRaw:r}))),t("div",{className:"monitor-side-stack"},t(qp,{provider:$,refresh:n,onRaw:r}),t(Np,{provider:$,tasks:l,onRaw:r,limit:5}),t(au,{title:"采样说明",eyebrow:"Retention"},t("div",{className:"monitor-note-list"},t("article",null,t("b",null,"CPU"),t("span",null,"从 /proc/stat 计算相邻采样差值,首个采样用 load/cores 近似")),t("article",null,t("b",null,"Memory"),t("span",null,"实际内存 = MemTotal - MemFree - Buffers - Cached - SReclaimable + Shmem,不把 page cache / buffer 计入占用")),t("article",null,t("b",null,"Disk"),t("span",null,"使用 df -PB1 对配置路径采样,默认监控根文件系统")),t("article",null,t("b",null,"Process"),t("span",null,"从 /proc/[pid] 采集进程 CPU、实际内存 RSS、线程数和磁盘 I/O 速率;表格默认按内存占用降序")))))))}function dL(u,f){if(f==="memory")return Mu(u.rssBytes);if(f==="cpu")return Mu(u.cpuPercent);if(f==="disk")return Mu(u.readBytesPerSecond)+Mu(u.writeBytesPerSecond);if(f==="pid")return Mu(u.pid);if(f==="threads")return Mu(u.threads);if(f==="runtime")return Mu(u.elapsedSeconds);if(f==="user")return String(u.user||"");return String(u.name||u.command||"")}function eL({value:u,label:f,tone:l}){let r=Math.max(1,Math.min(100,Mu(u)));return t("div",{className:`process-meter ${l||""}`},t("span",{style:{width:`${r}%`}}),t("b",null,f))}function tp({current:u,onRaw:f}){let[l,r]=hu({key:"memory",direction:"desc"}),n=bn.default.useContext(s9),i=u?.processSummary&&typeof u.processSummary==="object"?u.processSummary:{},y=Array.isArray(u?.processes)?u.processes:[],_=P$(()=>{let A=l.direction==="asc"?1:-1;return[...y].sort((c,j)=>{let F=dL(c,l.key),U=dL(j,l.key);if(typeof F==="string"||typeof U==="string")return String(F).localeCompare(String(U),"zh-CN")*A;return(F-U)*A||Mu(c.pid)-Mu(j.pid)})},[y,l.key,l.direction]),$=(A,c)=>{let j=l.key===c,F=j?l.direction==="asc"?"ascending":"descending":"none";return t("th",{"aria-sort":F},t("button",{type:"button",className:`process-sort-button ${j?"active":""}`,"data-testid":`process-sort-${c}`,onClick:()=>r((U)=>({key:c,direction:U.key===c&&U.direction==="desc"?"asc":"desc"}))},A,t("span",null,j?l.direction==="desc"?"↓":"↑":"↕")))};return t("section",{className:"process-resource-panel","data-testid":"process-resource-panel"},t("div",{className:"process-resource-head"},t("div",null,t("p",{className:"panel-eyebrow"},"Windows Resource Monitor Style"),t(nf,{title:"进程资源占用",level:3,loading:n})),t("div",{className:"process-resource-actions"},t("span",{className:"data-chip"},"默认按内存排序"),t("span",{className:"data-chip"},`${Mu(i.visible,_.length)} / ${Mu(i.total,_.length)} 进程`),t(bf,{title:"Process Resource Snapshot",data:{processSummary:i,processes:y},onOpen:f,testId:"raw-process-resources"}))),_.length===0?t(Ff,{title:"暂无进程资源数据",text:"等待 provider-gateway 上报 /proc/[pid] 采样;旧版 provider 需要先升级到支持进程资源表的版本"}):t("div",{className:"process-table-wrap"},t("table",{className:"process-resource-table","data-testid":"process-resource-table"},t("thead",null,t("tr",null,$("进程","name"),$("PID","pid"),$("用户","user"),t("th",null,"状态"),$("CPU","cpu"),$("内存","memory"),t("th",null,"RSS"),$("磁盘 I/O","disk"),$("线程","threads"),$("运行时长","runtime"))),t("tbody",null,_.map((A)=>{let c=Mu(A.readBytesPerSecond)+Mu(A.writeBytesPerSecond);return t("tr",{key:`${A.pid}-${A.startedAt}`,"data-testid":`process-row-${ol(A.pid)}`,"data-memory-bytes":String(Mu(A.rssBytes)),"data-cpu-percent":String(Mu(A.cpuPercent)),"data-disk-bps":String(c),"data-pid":String(Mu(A.pid))},t("td",null,t("div",{className:"process-name-cell"},t("strong",null,A.name||"--"),t("span",{className:"process-command"},A.command||"--"))),t("td",null,t("code",null,A.pid||"--")),t("td",null,A.user||`uid:${A.uid??"--"}`),t("td",null,t("span",{className:`process-state state-${ol(A.state||"unknown")}`},A.state||"?")),t("td",null,t(eL,{value:A.cpuPercent,label:RS(A.cpuPercent),tone:"cpu"})),t("td",null,t(eL,{value:A.memoryPercent,label:hn(A.memoryPercent),tone:"memory"})),t("td",null,zl(A.rssBytes)),t("td",null,t("div",{className:"process-io-cell"},t("strong",null,k9(c)),t("span",null,`R ${k9(A.readBytesPerSecond)} / W ${k9(A.writeBytesPerSecond)}`))),t("td",null,A.threads||0),t("td",null,x0(Mu(A.elapsedSeconds))))})))))}function I9({title:u,metricKey:f,current:l,points:r,detail:n,tone:i,testId:y}){let _=r.map((F)=>Math.max(0,Math.min(100,Mu(F[f])))),$=_.length>1?_:[_[0]||0,_[0]||0],A=$.length<=1?100:100/($.length-1),c=$.map((F,U)=>`${(U*A).toFixed(2)},${(46-F*0.42).toFixed(2)}`).join(" "),j=`0,48 ${c} 100,48`;return t("article",{className:`metric-chart ${i}`,"data-testid":y},t("div",{className:"metric-chart-head"},t("div",null,t("span",null,u),t("strong",null,hn(l))),t("code",null,`${r.length} pts`)),t("svg",{viewBox:"0 0 100 48",preserveAspectRatio:"none",role:"img","aria-label":`${u} usage curve`},t("polygon",{points:j}),t("polyline",{points:c}),t("line",{x1:"0",x2:"100",y1:"24",y2:"24"})),t("div",{className:"metric-chart-foot"},t("span",null,"0%"),t("span",null,n),t("span",null,"100%")))}function h0(u){return Array.isArray(u)?u:[]}function Ap(u){let f=h0(u?.core?.requests?.componentSummary);return[...h0(u?.frontend?.requests?.componentSummary),...f].sort((r,n)=>Mu(n.requestCount)-Mu(r.requestCount))}function cp(u){let f=h0(u?.core?.operations?.summary);return[...h0(u?.frontend?.operations?.summary),...f].sort((r,n)=>Mu(n.count)-Mu(r.count))}function jp(u){let f=h0(u?.core?.requests?.recentFailures).map((r)=>({source:"backend",...r}));return[...h0(u?.frontend?.requests?.recentFailures).map((r)=>({source:"frontend",...r})),...f].sort((r,n)=>(J0(n.at)??0)-(J0(r.at)??0)).slice(0,20)}function Fp(u){let f=h0(u?.core?.operations?.recentSlowOperations);return[...h0(u?.frontend?.operations?.recentSlowOperations),...f].sort((r,n)=>Mu(n.durationMs)-Mu(r.durationMs)).slice(0,20)}function Jp(u){let f=performance.memory,l=Number(f?.usedJSHeapSize);if(Number.isFinite(l)&&l>0)return l;let r=Number(u?.appBundleBytes);if(Number.isFinite(r)&&r>0)return r;return Mu(u?.process?.heapUsedBytes)}function Up({points:u}){let f=h0(u),l=f.map((F)=>Mu(F.mb)),r=Math.max(1,...l),n=Math.max(0,Math.min(...l,0)),i=Math.max(1,r-n),y=f.length>1?f:[...f,...f],_=y.length<=1?100:100/(y.length-1),$=y.map((F,U)=>{let Q=Mu(F.mb);return`${(U*_).toFixed(2)},${(48-(Q-n)/i*42).toFixed(2)}`}).join(" "),A=`0,50 ${$} 100,50`,c=f.at(-1),j=f[0];return t("article",{className:"performance-memory-card","data-testid":"performance-memory-chart"},t("div",{className:"performance-memory-head"},t("strong",null,`Bwebui: ${c?`${Mu(c.mb).toFixed(1)}MB`:"--"}`),t("span",null,f.length>0?`${f.length} samples`:"等待采样")),t("svg",{viewBox:"0 0 100 50",preserveAspectRatio:"none",role:"img","aria-label":"Bwebui memory trend"},t("polygon",{points:A}),t("polyline",{points:$}),t("line",{x1:"0",x2:"100",y1:"25",y2:"25"})),t("div",{className:"performance-axis-row"},t("span",null,j?tf(new Date(j.at)):"--"),t("span",null,"时间"),t("span",null,c?tf(new Date(c.at)):"--")),t("div",{className:"performance-axis-row"},t("span",null,`${n.toFixed(1)}`),t("span",null,"(MB)"),t("span",null,`${r.toFixed(1)}`)))}function Qp({onRaw:u}){let[f,l]=hu({core:null,frontend:null}),[r,n]=hu([]),[i,y]=hu(""),[_,$]=hu(!1),[A,c]=hu(null),[j,F]=hu(!1);async function U(){$(!0),y("");try{let[Y,p]=await Promise.all([Eu(`${gu.apiBaseUrl}/performance`,{cache:"no-store"}),Eu(`${gu.apiBaseUrl}/frontend-performance`,{cache:"no-store"})]);l({core:Y,frontend:p});let O=Jp(p);n((m)=>[...m,{at:new Date().toISOString(),mb:O/1048576}].slice(-80))}catch(Y){y(Hu(Y,"性能指标加载失败"))}finally{$(!1)}}F0(()=>{U();let Y=setInterval(()=>void U(),5000);return()=>clearInterval(Y)},[]);async function Q(){F(!0),y(""),c(null);try{let Y=await Eu(`${gu.apiBaseUrl}/code-queue-load-test`,{method:"POST",body:JSON.stringify({targetMs:1000,timeoutMs:90000,url:gu.frontendPublicUrl||window.location.origin})});c(Y),U()}catch(Y){y(Hu(Y,"Code Queue Playwright 测量失败"))}finally{F(!1)}}let L=Ap(f),w=jp(f),J=cp(f),N=Fp(f),q=f.core?.process||{},W=f.frontend?.process||{},z=f.core?.database?.codeQueueStorage||{},Z=Mu(z.total),H=A?.result||{},E=Mu(H.wallMs,NaN),D=Mu(H.networkIdleMs,NaN),h=H.withinTarget===!0,V=j?"running":A===null?"idle":A.measurementOk===!0?h?"passed":"slow":"failed";return t("div",{className:"performance-page","data-testid":"performance-page"},t("div",{className:"performance-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Unified Performance"),t(nf,{title:"性能面板",loading:_||j}),t("p",null,"按组件统计 HTTP 请求、失败率、P95 延迟,并汇总 backend/frontend 内部操作耗时。")),t("div",{className:"inline-actions"},t("button",{type:"button",className:"ghost-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-button"},j?"测试中...":"测试 Code Queue 加载"),t("button",{type:"button",className:"ghost-btn",onClick:()=>void U(),disabled:_,"data-testid":"performance-refresh-button"},_?"刷新中":"刷新"),t(bf,{title:"Performance Snapshot",data:f,onOpen:u,testId:"raw-performance"}))),t(yf,{error:i}),t("div",{className:"performance-top-grid"},t(Up,{points:r}),t("div",{className:"performance-metric-stack"},t(cf,{label:"backend RSS",value:zl(q.rssBytes),hint:`heap ${zl(q.heapUsedBytes)}`}),t(cf,{label:"frontend RSS",value:zl(W.rssBytes),hint:`bundle ${zl(f.frontend?.appBundleBytes)}`}),t(cf,{label:"Codex PG 任务",value:Z||"--",hint:z.ok?"unidesk_code_queue_tasks":"等待表初始化",tone:z.ok?"ok":"warn"}),t(cf,{label:"请求样本",value:Mu(f.core?.requests?.sampleCount)+Mu(f.frontend?.requests?.sampleCount),hint:"rolling window 3000"}))),t(au,{title:"Code Queue 加载基准",eyebrow:"Playwright / target <1s",className:"codex-load-test-panel",loading:j,actions:t("div",{className:"panel-actions"},t("button",{type:"button",className:"primary-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-panel-button"},j?"正在运行 Playwright...":"手动触发测试"),A?t(bf,{title:"Code Queue Load Test",data:A,onOpen:u,testId:"raw-code-queue-load-test"}):null)},t("div",{className:"codex-load-test-grid","data-testid":"code-queue-load-test-result"},t(cf,{label:"总耗时",value:j?"运行中":Number.isFinite(E)?Qr(E):"--",hint:A===null?"点击按钮启动远端 Playwright":`目标 ${Qr(H.targetMs||1000)} / ${H.url||"Code Queue"}`,tone:V==="passed"?"ok":V==="failed"||V==="slow"?"warn":""}),t(cf,{label:"判定",value:j?"RUNNING":V==="passed"?"PASS <1s":V==="slow"?"SLOW":V==="failed"?"FAILED":"--",hint:A?.measurementOk===!1?String(A.error||H.error||"measurement failed").slice(0,120):"导航开始 -> DOMContentLoaded -> data-load-state=complete",tone:V==="passed"?"ok":V==="idle"||V==="running"?"":"fail"}),t(cf,{label:"Network idle",value:Number.isFinite(D)?Qr(D):"--",hint:`DOMContentLoaded ${Qr(H.domContentLoadedMs)} / ${H.networkIdleReached===!1?"未在 5s 内空闲":"已空闲"}`,tone:Number.isFinite(D)&&D<=1000?"ok":"warn"}),t(cf,{label:"组件耗时",value:Number.isFinite(Mu(H.componentLoadMs,NaN))?Qr(H.componentLoadMs):"--",hint:`queue ${Qr(H.queueMs)} / detail ${Qr(H.detailMs)}`,tone:Mu(H.componentLoadMs)>1000?"warn":"ok"}),t(cf,{label:"Trace 规模",value:Number.isFinite(Mu(H.transcriptRows,NaN))?String(H.transcriptRows):"--",hint:`${H.visibleTaskCount??0} visible tasks / ${H.partial?"preview":"complete"}`})),j?t("div",{className:"performance-empty-line"},"正在通过 main-server Host SSH 启动 Playwright,完成后会显示 wall time、组件耗时和最慢 API。"):null,A&&Array.isArray(H.slowestApi)&&H.slowestApi.length>0?t("div",{className:"table-wrap performance-table-wrap compact codex-load-api-table"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["API","状态","耗时"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,H.slowestApi.slice(0,5).map((Y,p)=>t("tr",{key:`${Y.url}-${p}`},t("td",null,t("code",null,Y.url)),t("td",null,Y.status),t("td",null,Qr(Y.durationMs))))))):null),t("div",{className:"performance-grid"},t(au,{title:"组件汇总",eyebrow:"Requests",loading:_},L.length===0?t(Ff,{title:"暂无请求样本",text:"刷新几次或打开页面后会自动形成组件统计"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["组件","请求数","失败数","失败率","平均延迟","P95"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,L.map((Y)=>t("tr",{key:Y.component},t("td",null,t("code",null,Y.component)),t("td",null,Y.requestCount),t("td",null,Y.failureCount),t("td",null,hn(Mu(Y.failureRate)*100)),t("td",null,Qr(Y.averageLatencyMs)),t("td",null,Qr(Y.p95LatencyMs)))))))),t(au,{title:"最近失败请求",eyebrow:"Failures",loading:_},w.length===0?t("div",{className:"performance-empty-line"},"最近没有失败请求"):t("div",{className:"table-wrap performance-table-wrap compact"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["时间","来源","组件","状态","路径"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,w.map((Y,p)=>t("tr",{key:`${Y.at}-${p}`},t("td",null,Nu(Y.at)),t("td",null,Y.source),t("td",null,t("code",null,Y.component)),t("td",null,t(wf,{status:"failed"},Y.status)),t("td",null,t("code",null,Y.path)))))))),t(au,{title:"内部操作汇总",eyebrow:"Operations",loading:_},J.length===0?t(Ff,{title:"暂无内部操作样本",text:"API 查询和代理请求会自动记录内部操作耗时"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["服务","操作","次数","平均延迟","P95"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,J.map((Y)=>t("tr",{key:`${Y.service}-${Y.operation}`},t("td",null,Y.service),t("td",null,t("code",null,Y.operation)),t("td",null,Y.count),t("td",null,Qr(Y.averageLatencyMs)),t("td",null,Qr(Y.p95LatencyMs)))))))),t(au,{title:"最近慢操作",eyebrow:"Slowest",loading:_},N.length===0?t(Ff,{title:"暂无慢操作",text:"后端会记录最近窗口内耗时最高的内部操作"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["时间","操作","耗时","结果","细节"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,N.map((Y,p)=>t("tr",{key:`${Y.at}-${Y.operation}-${p}`},t("td",null,Nu(Y.at)),t("td",null,t("code",null,Y.operation)),t("td",null,Qr(Y.durationMs)),t("td",null,Y.ok?"成功":"失败"),t("td",null,Y.detail||"-")))))))))}function qp({provider:u,refresh:f,onRaw:l}){let[r,n]=hu(""),[i,y]=hu(null),[_,$]=hu("");async function A(c){n(c),$("");try{let j=await Eu(`${gu.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:u.providerId,command:"provider.upgrade",payload:{mode:c,source:"frontend-resource-monitor",requestedAt:new Date().toISOString()}})});y({mode:c,...j}),await f()}catch(j){$(Hu(j,"升级命令下发失败"))}finally{n("")}}return t(au,{title:"Provider Gateway 升级",eyebrow:"Remote Control",loading:Boolean(r)},t("div",{className:"upgrade-control","data-testid":"provider-upgrade-control"},t("p",null,"通过 UniDesk WebSocket 向当前计算节点下发 provider.upgrade;预检只生成升级计划,执行升级会调度节点本地 updater 容器。"),t("div",{className:"upgrade-target-line"},t("span",null,"指定 Provider"),t("code",null,u.providerId),t(qy,{node:u})),t("div",{className:"upgrade-actions"},t("button",{type:"button",className:"ghost-btn",disabled:Boolean(r),onClick:()=>A("plan"),"data-testid":"upgrade-plan-button"},r==="plan"?"预检中":"预检升级"),t("button",{type:"button",className:"ghost-btn danger",disabled:Boolean(r),onClick:()=>A("schedule"),"data-testid":"upgrade-schedule-button"},r==="schedule"?"调度中":"执行升级")),t(yf,{error:_}),i?t("div",{className:"upgrade-result"},t(wf,{status:i.status||"queued"},i.status||"queued"),t("span",null,`${i.mode==="schedule"?"执行升级":"预检升级"} 已下发`),t("span",null,`指定版本 ${d9($w(u))}`),t("code",null,i.taskId||"--"),t(bf,{title:"Provider Upgrade Dispatch",data:i,onOpen:l})):t("span",{className:"muted"},"升级任务结果会进入任务历史;执行升级可能导致 provider 短暂重连。")))}function Nw({records:u,onRaw:f,compact:l=!1}){if(u.length===0)return t(Ff,{title:"暂无远程更新记录",text:"该节点还没有 provider.upgrade 任务;执行预检或升级后会在这里形成结构化记录"});return t("div",{className:`upgrade-record-table-wrap table-wrap ${l?"compact":""}`},t("table",{className:"upgrade-record-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"模式"),t("th",null,"任务"),t("th",null,"来源"),t("th",null,"耗时"),t("th",null,"策略"),t("th",null,"Gateway 版本"),t("th",null,"结果记录"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,u.map((r)=>t("tr",{key:r.id,"data-testid":`gateway-upgrade-record-${ol(r.id)}`},t("td",null,t(wf,{status:r.status})),t("td",null,t("span",{className:`mode-chip ${O8(r)}`},O8(r)==="schedule"?"执行升级":"预检")),t("td",null,t("strong",null,"provider.upgrade"),t("code",null,r.id)),t("td",null,vS(r)),t("td",null,t(Lw,{task:r})),t("td",null,kS(r)),t("td",null,t("span",{className:"version-chip"},jw(r))),t("td",null,t("span",{className:`upgrade-outcome ${String(r.status||"").toLowerCase()}`},Fw(r))),t("td",null,Nu(r.updatedAt)),t("td",null,t(bf,{title:`Provider Upgrade Task ${r.id}`,data:M$(r),onOpen:f})))))))}function Np({provider:u,tasks:f,onRaw:l,limit:r=5}){let n=Jw(f,u.providerId).slice(0,r);return t(au,{title:"远程更新记录",eyebrow:u.providerId,actions:t(qy,{node:u}),className:"provider-upgrade-records-panel"},t("div",{"data-testid":`provider-upgrade-records-${ol(u.providerId)}`},t(Nw,{records:n,onRaw:l,compact:!0})))}function Wp({nodes:u,tasks:f,onRaw:l}){let r=P$(()=>u.map((i)=>{let y=Jw(f,i.providerId);return{node:i,records:y,latest:IS(y),capabilities:tw(i)}}),[u,f]),n=r.reduce((i,y)=>i+y.records.length,0);return t("div",{className:"gateway-page","data-testid":"gateway-version-page"},t(au,{title:"Provider Gateway 版本",eyebrow:`${u.length} Providers / ${n} 更新记录`},u.length===0?t(Ff,{title:"暂无 Provider 节点",text:"等待 provider-gateway 注册后显示版本号和升级记录"}):t("div",{className:"table-wrap gateway-version-table-wrap"},t("table",{className:"gateway-version-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"Provider"),t("th",null,"Gateway 版本"),t("th",null,"升级策略"),t("th",null,"运维可用性"),t("th",null,"运行时间"),t("th",null,"能力"),t("th",null,"最近远程更新"),t("th",null,"操作"))),t("tbody",null,r.map((i)=>t("tr",{key:i.node.providerId},t("td",null,t(wf,{status:i.node.status})),t("td",null,t("strong",null,i.node.name),t("code",null,i.node.providerId)),t("td",null,t(qy,{node:i.node})),t("td",null,m$(i.node)),t("td",null,t(e9,{node:i.node})),t("td",null,gL(i.node)?Nu(gL(i.node)):"待新版上报"),t("td",null,t("div",{className:"capability-row"},i.capabilities.length===0?t("span",{className:"muted"},"未声明"):i.capabilities.slice(0,5).map((y)=>t("span",{key:y,className:"data-chip"},y)))),t("td",null,i.latest?t("div",{className:"latest-upgrade-cell"},t(wf,{status:i.latest.status}),t("span",null,`${O8(i.latest)==="schedule"?"执行升级":"预检"} / ${Nu(i.latest.updatedAt)}`),t("small",null,`Gateway ${jw(i.latest)}`),t("small",null,Fw(i.latest))):t("span",{className:"muted"},"暂无记录")),t("td",null,t(bf,{title:`Provider ${i.node.providerId}`,data:i.node,onOpen:l})))))))),t(au,{title:"远程更新记录",eyebrow:"Structured provider.upgrade records"},u.length===0?t(Ff,{title:"暂无记录",text:"没有 provider 节点时不会生成远程更新记录"}):t("div",{className:"gateway-record-grid"},r.map((i)=>t("article",{key:i.node.providerId,className:"gateway-record-card","data-testid":`gateway-records-${ol(i.node.providerId)}`},t("div",{className:"gateway-record-head"},t("div",null,t("strong",null,i.node.name),t("code",null,i.node.providerId)),t(qy,{node:i.node})),t("div",{className:"gateway-record-meta"},t("span",null,`心跳 ${Nu(i.node.lastHeartbeat)}`),t("span",null,`策略 ${m$(i.node)}`),t("span",null,`${i.records.length} 条记录`)),t(Nw,{records:i.records.slice(0,8),onRaw:l,compact:!0}))))))}function Lp(u){if(u==="running")return"online";if(u==="paused"||u==="restarting")return"warn";if(u==="exited"||u==="dead")return"offline";return"internal"}function Ww(u){return/^[a-f0-9]{48,64}$/i.test(u)}function p$(u){let f=String(u?.name||""),l=String(u?.labels||"");return f==="unidesk_pgdata_10gb"||l.includes("com.docker.compose.volume=unidesk_pgdata_10gb")||f.toLowerCase().includes("pgdata")}function uw(u){let f=String(u?.name||""),l=String(u?.labels||"");if(p$(u))return 0;if(l.includes("com.docker.compose.project=unidesk"))return 1;if(!Ww(f))return 2;return 3}function wp(u){return[...u].sort((f,l)=>{let r=uw(f)-uw(l);if(r!==0)return r;return String(f.name||"").localeCompare(String(l.name||""))})}function Kp({nodes:u,dockerStatuses:f,onRaw:l}){let[r,n]=hu(""),i=P$(()=>u.map((N)=>{let q=f.find((W)=>W.providerId===N.providerId);return{...N,dockerStatus:q?.dockerStatus||null,dockerUpdatedAt:q?.updatedAt||null}}),[u,f]),y=i.find((N)=>N.providerId===r)||i[0]||null;if(F0(()=>{if(!r&&i[0])n(i[0].providerId)},[i.length,r]),!y)return t(Ff,{title:"暂无 Docker 节点",text:"等待 provider 上报 Docker daemon 状态"});let _=y.dockerStatus,$=y.providerId==="main-server",A=_?.counts||{},c=_?.daemon||{},j=_?.containers||[],F=_?.images||[],U=wp(_?.volumes||[]),Q=$?U.find(p$):null,L=_?.networks||[],w=j.filter((N)=>N.state==="running"),J=j.filter((N)=>N.state!=="running");return t("div",{className:"docker-page","data-testid":"docker-status-page"},t("div",{className:"docker-node-strip"},i.map((N)=>t("button",{key:N.providerId,type:"button",className:`docker-node-tile ${y.providerId===N.providerId?"active":""}`,onClick:()=>n(N.providerId)},t("span",{className:`pulse ${N.status}`}),t("strong",null,N.name),t("code",null,N.providerId),t("span",null,N.dockerStatus?`Docker ${N.dockerStatus.ok?"ready":"degraded"}`:"等待上报")))),t("div",{className:"docker-layout"},t(au,{title:"Docker Desktop 视图",eyebrow:y.name,className:"docker-main-panel",actions:_?t(bf,{title:`Docker ${y.providerId}`,data:_,onOpen:l}):null},!_?t(Ff,{title:"Docker 状态未上报",text:"provider-gateway 会在连接后周期性采集 docker info / ps / images / volume / network"}):t("div",null,t("div",{className:"docker-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Daemon"),t("h3",null,c.name||y.providerId),t("div",{className:"docker-meta"},t("span",null,c.serverVersion?`Engine ${c.serverVersion}`:"Engine --"),t("span",null,c.operatingSystem||"OS --"),t("span",null,c.architecture||"arch --"),t("span",null,`${c.cpus||0} CPU / ${zl(c.memoryBytes)}`))),t(wf,{status:_.ok?"online":"warn"},_.ok?"Docker Ready":"Docker Degraded")),t("div",{className:"docker-metrics"},t(cf,{label:"Containers",value:A.containers??j.length,hint:`${A.running??w.length} running / ${A.stopped??J.length} stopped`,tone:"ok"}),t(cf,{label:"Images",value:A.images??F.length,hint:`${A.daemonImages??A.images??F.length} daemon images`}),t(cf,{label:"Volumes",value:A.volumes??U.length,hint:$?Q?"database volume visible":"database volume missing":"node local volumes",tone:Q?"ok":""}),t(cf,{label:"Networks",value:A.networks??L.length,hint:c.driver?`driver ${c.driver}`:"docker networks"})),$?t(Gp,{volume:Q,volumeCount:U.length}):null,t("div",{className:"docker-section-head"},t("h3",null,"Containers"),t("span",null,`updated ${Nu(y.dockerUpdatedAt||_.collectedAt)}`)),t("div",{className:"docker-container-table table-wrap","data-testid":"docker-container-table"},t("table",null,t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"容器"),t("th",null,"镜像"),t("th",null,"端口"),t("th",null,"运行时间"),t("th",null,"重启策略"),t("th",null,"PID"),t("th",null,"大小"))),t("tbody",null,j.length===0?t("tr",null,t("td",{colSpan:8},"暂无容器")):j.map((N)=>t("tr",{key:`${N.id}-${N.name}`},t("td",null,t(wf,{status:Lp(N.state)},N.state||"unknown")),t("td",null,t("strong",null,N.name||"--"),t("code",null,N.id||"--")),t("td",null,N.image||"--"),t("td",null,N.ports||t("span",{className:"muted"},"未发布")),t("td",null,N.runningFor||N.status||"--"),t("td",null,N.restartPolicy?t(wf,{status:N.restartPolicy==="always"?"online":"warn"},N.restartPolicy):"--"),t("td",null,N.pidMode?t("code",null,N.pidMode):"--"),t("td",null,N.size||"--")))))))),t("div",{className:"docker-side-stack"},t(g9,{title:"Images",items:F,render:(N)=>t("article",{key:`${N.id}-${N.repository}`,className:"docker-side-row"},t("strong",null,`${N.repository}:${N.tag}`),t("span",null,N.size||"--"),t("code",null,N.id||"--"))}),t(g9,{title:"Volumes",items:U,limit:U.length,render:(N)=>t("article",{key:N.name,className:`docker-side-row volume-row ${$&&p$(N)?"database-volume":""}`,"data-testid":$&&p$(N)?"database-volume-row":void 0},t("strong",null,N.name),t("span",null,$&&p$(N)?"PostgreSQL":Ww(String(N.name||""))?"anonymous":"named"),t("code",null,N.mountpoint||N.driver||N.scope||"--"))}),t(g9,{title:"Networks",items:L,render:(N)=>t("article",{key:N.id||N.name,className:"docker-side-row"},t("strong",null,N.name),t("span",null,N.driver||"--"),t("code",null,N.id||"--"))}))))}function Gp({volume:u,volumeCount:f}){return t("section",{className:`docker-volume-focus ${u?"ready":"missing"}`,"data-testid":"database-volume-card"},t("div",{className:"volume-focus-head"},t("span",{className:"panel-eyebrow"},"Database Named Volume"),t(wf,{status:u?"online":"warn"},u?"FOUND":"MISSING")),u?t("div",{className:"volume-focus-body"},t("strong",null,u.name),t("span",null,"PostgreSQL data volume for unidesk-database"),t("div",{className:"volume-route"},t("code",null,u.mountpoint||"/var/lib/docker/volumes/unidesk_pgdata_10gb/_data"),t("span",null,"->"),t("code",null,"unidesk-database:/var/lib/postgresql/data")),t("div",{className:"docker-meta compact"},t("span",null,`driver ${u.driver||"--"}`),t("span",null,`scope ${u.scope||"--"}`),t("span",null,`${f} volumes reported`))):t("div",{className:"volume-focus-body"},t("strong",null,"unidesk_pgdata_10gb"),t("span",null,"当前 Docker 快照没有发现数据库命名卷;请检查 provider-gateway 的 Docker volume 上报。")))}function g9({title:u,items:f,render:l,limit:r}){let n=f.slice(0,r??12),i=Math.max(0,f.length-n.length);return t(au,{title:u,eyebrow:`${f.length} items`,className:"docker-side-panel"},f.length===0?t(Ff,{title:`暂无 ${u}`,text:"等待 Docker 状态采集"}):t("div",{className:"docker-side-list"},n.map(l),i>0?t("div",{className:"docker-side-more"},`+ ${i} more`):null))}function zp({microservices:u,onRaw:f,onNavigate:l}){let r=u.filter((n)=>aL(n).public===!1);return t("div",{className:"microservice-page","data-testid":"microservice-catalog-page"},t(au,{title:"用户服务目录",eyebrow:"Provider Mounted User Services"},t("div",{className:"metric-grid"},t(cf,{label:"服务总数",value:u.length,hint:"config.json 用户服务登记"}),t(cf,{label:"私有后端",value:r.length,hint:"不直接暴露公网",tone:"ok"}),t(cf,{label:"D601 服务",value:u.filter((n)=>n.providerId==="D601").length,hint:"compute-node docker"}),t(cf,{label:"集成前端",value:u.filter((n)=>n.frontend?.integrated).length,hint:"UniDesk React 页面"}))),t(au,{title:"服务映射",eyebrow:"Repo Reference + Runtime"},u.length===0?t(Ff,{title:"暂无用户服务",text:"在 config.json 的 microservices 中登记用户服务的 provider、仓库引用和后端映射"}):t("div",{className:"table-wrap"},t("table",{className:"microservice-table"},t("thead",null,t("tr",null,t("th",null,"服务"),t("th",null,"Provider"),t("th",null,"代码引用"),t("th",null,"Docker 引用"),t("th",null,"后端映射"),t("th",null,"开发入口"),t("th",null,"运行态"),t("th",null,"操作"))),t("tbody",null,u.map((n)=>{let i=Uw(n),y=gS(n),_=aL(n),$=i.availability||{},A=$.status||(i.providerStatus==="online"?"unknown":"unhealthy");return t("tr",{key:n.id,"data-testid":`microservice-row-${ol(n.id)}`},t("td",null,t("strong",null,n.name),t("code",null,n.id)),t("td",null,t("strong",null,i.providerName||n.providerId),t("code",null,n.providerId)),t("td",null,t("span",null,y.url||"--"),t("code",null,y.commitId||"--")),t("td",null,t("span",null,y.composeFile||"--"),t("code",null,`${y.composeService||"--"} / ${y.containerName||"--"}`)),t("td",null,t(wf,{status:_.public?"warn":"online"},_.public?"public":"private"),t("code",null,`${_.nodeBindHost||"--"}:${_.nodePort||"--"} -> ${_.proxyMode||"--"}`)),t("td",null,t("span",null,n.development?.sshPassthrough?"SSH 透传":"未配置"),t("code",null,n.development?.worktreePath||"--")),t("td",null,t(wf,{status:A==="healthy"?"online":A==="unknown"?"warn":"failed"},A),t("span",null,$.reason||i.providerStatus||"unknown"),t(vn,{data:i.container,empty:"容器快照未上报"})),t("td",null,t("div",{className:"microservice-actions"},n.id==="findjob"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","findjob"),"data-testid":"open-findjob-button"},"打开"):null,n.id==="pipeline"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","pipeline"),"data-testid":"open-pipeline-button"},"打开"):null,n.id==="todo-note"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","todo-note"),"data-testid":"open-todo-note-button"},"打开"):null,n.id==="met-nonlinear"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","met-nonlinear"),"data-testid":"open-met-nonlinear-button"},"打开"):null,n.id==="claudeqq"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","claudeqq"),"data-testid":"open-claudeqq-button"},"打开"):null,n.id==="baidu-netdisk"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","baidu-netdisk"),"data-testid":"open-baidu-netdisk-button"},"打开"):null,n.id==="oa-event-flow"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","oa-event-flow"),"data-testid":"open-oa-event-flow-button"},"打开"):null,n.id==="code-queue"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","code-queue"),"data-testid":"open-code-queue-button"},"打开"):null,n.id==="project-manager"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","project-manager"),"data-testid":"open-project-manager-button"},"打开"):null,t(bf,{title:`用户服务 ${n.id}`,data:n,onOpen:f}))))}))))))}function Tp({nodes:u,onDispatched:f,onRaw:l}){let r=u.filter((V)=>V.status==="online"),[n,i]=hu(r[0]?.providerId||u[0]?.providerId||""),[y,_]=hu("docker.ps"),[$,A]=hu("frontend"),[c,j]=hu("operator-check"),[F,U]=hu("normal"),[Q,L]=hu(!1),[w,J]=hu(""),[N,q]=hu(!1),[W,z]=hu(null),[Z,H]=hu("");F0(()=>{if(!n&&(r[0]?.providerId||u[0]?.providerId))i(r[0]?.providerId||u[0].providerId)},[u.length,r.length,n]);function E(){return{source:$,note:c,priority:F}}function D(){J(JSON.stringify(E(),null,2)),L(!0)}async function h(V){V.preventDefault(),q(!0),H("");try{let Y=Q?JSON.parse(w||"{}"):E(),p=await Eu(`${gu.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:n,command:y,payload:Y})});z(p),await f()}catch(Y){H(Hu(Y,"下发失败"))}finally{q(!1)}}return t("div",{className:"page-grid dispatch-grid"},t(au,{title:"下发任务",eyebrow:"Real WebSocket Dispatch"},t("form",{className:"dispatch-form",onSubmit:h},t("label",null,"Provider",t("select",{value:n,onChange:(V)=>i(V.target.value)},u.map((V)=>t("option",{key:V.providerId,value:V.providerId},`${V.name} / ${V.providerId}`)))),t("label",null,"Command",t("select",{value:y,onChange:(V)=>_(V.target.value)},t("option",{value:"docker.ps"},"docker.ps"),t("option",{value:"host.ssh"},"host.ssh"),t("option",{value:"microservice.http"},"microservice.http"),t("option",{value:"echo"},"echo"))),t("label",null,"来源",t("input",{value:$,onChange:(V)=>A(V.target.value)})),t("label",null,"备注",t("input",{value:c,onChange:(V)=>j(V.target.value)})),t("label",null,"优先级",t("select",{value:F,onChange:(V)=>U(V.target.value)},t("option",{value:"normal"},"normal"),t("option",{value:"low"},"low"),t("option",{value:"urgent"},"urgent"))),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",onClick:D},"查看原始JSON"),t("button",{type:"submit",disabled:N||!n},N?"下发中":"下发任务")),Q?t("label",{className:"raw-editor-label"},"高级 Payload",t("textarea",{className:"raw-editor",value:w,onChange:(V)=>J(V.target.value)})):null,t(yf,{error:Z,wide:!0}))),t(au,{title:"下发结果",eyebrow:"Response"},W?t("div",{className:"result-card"},t(wf,{status:W.status||"queued"},W.status||"queued"),t("dl",null,t("dt",null,"Task ID"),t("dd",null,t("code",null,W.taskId||"--")),t("dt",null,"Provider 在线"),t("dd",null,M1(W.providerOnline))),t(bf,{title:"Dispatch Response",data:W,onOpen:l})):t(Ff,{title:"等待操作",text:"任务响应会以结构化结果卡展示"})))}function fw({task:u,onRaw:f}){return t("article",{className:"compact-row"},t(wf,{status:u.status}),t("div",null,t("strong",null,u.command),t("code",null,u.id)),t("span",null,Ny(u)?`已等待 ${a9(u.updatedAt)}`:`耗时 ${x0(iw(u)??0)}`),t(bf,{title:`Task ${u.id}`,data:M$(u),onOpen:f}))}function Lw({task:u}){let f=iw(u),l=Ny(u);return t("div",{className:"task-duration"},t("strong",null,f===null?"--":x0(f)),t("span",null,l?`已运行 / 创建 ${Nu(u.createdAt)}`:`创建 ${Nu(u.createdAt)}`))}function Ep({task:u}){let f=String(u?.status||"").toLowerCase(),l=u?.result,r=l&&typeof l==="object"&&!Array.isArray(l)?l:{},i=["exitCode","code","signal","timeoutMs","previousStatus","mode"].filter((y)=>r[y]!==void 0&&r[y]!==null);if(f==="failed"){let y=yw(u);return t("div",{className:"task-diagnostic failed"},t("b",null,"失败原因"),t("span",{className:"diagnostic-reason"},M1(y)),i.length>0?t("div",{className:"diagnostic-meta"},i.map((_)=>t("span",{key:_,className:"data-chip"},t("b",null,_),t("span",null,M1(r[_]))))):null)}if(Ny(u))return t("div",{className:"task-diagnostic warn"},t("b",null,"等待终态"),t("span",null,`最后更新 ${a9(u.updatedAt)} 前`));return t("div",{className:"task-diagnostic ok"},t("b",null,"完成摘要"),t(vn,{data:l,empty:"无执行输出"}))}function Zp({tasks:u,onRaw:f}){let l=u.filter(Ny);return t("div",{"data-testid":"pending-task-page"},t(au,{title:"待处理任务",eyebrow:`${l.length} Pending`},l.length===0?t(Ff,{title:"当前无待处理任务",text:"queued / dispatched / running 会在超时后自动转为 failed;历史记录仍可在任务历史中查看"}):t("div",{className:"table-wrap","data-testid":"pending-task-table"},t("table",null,t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"Provider"),t("th",null,"已等待"),t("th",null,"载荷摘要"),t("th",null,"操作"))),t("tbody",null,l.map((r)=>t("tr",{key:r.id},t("td",null,t(wf,{status:r.status})),t("td",null,t("strong",null,r.command),t("code",null,r.id)),t("td",null,t("code",null,r.providerId)),t("td",null,a9(r.updatedAt)),t("td",null,t(vn,{data:r.payload})),t("td",null,t(bf,{title:`Pending Task ${r.id}`,data:M$(r),onOpen:f})))))))))}function Op({tasks:u,onRaw:f}){return t("div",{"data-testid":"task-history-page"},t(au,{title:"任务历史",eyebrow:`${u.length} Tasks`},u.length===0?t(Ff,{title:"暂无任务",text:"下发任务后会在这里看到生命周期"}):t("div",{className:"table-wrap"},t("table",{className:"task-history-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"Provider"),t("th",null,"任务耗时"),t("th",null,"载荷摘要"),t("th",null,"诊断信息"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.id,"data-testid":`task-row-${ol(l.id)}`},t("td",null,t(wf,{status:l.status})),t("td",null,t("strong",null,l.command),t("code",null,l.id)),t("td",null,t("code",null,l.providerId)),t("td",null,t(Lw,{task:l})),t("td",null,t(vn,{data:l.payload})),t("td",null,t(Ep,{task:l})),t("td",null,Nu(l.updatedAt)),t("td",null,t(bf,{title:`Task ${l.id}`,data:M$(l),onOpen:f})))))))))}function Hp({tasks:u,onRaw:f}){let l=u.filter((r)=>["succeeded","failed"].includes(r.status));return t(au,{title:"执行结果",eyebrow:"Finished Tasks"},l.length===0?t(Ff,{title:"暂无结果",text:"任务完成后展示 provider 返回的结构化摘要"}):t("div",{className:"result-grid"},l.map((r)=>t("article",{key:r.id,className:"result-card"},t("div",{className:"node-card-head"},t("strong",null,r.command),t(wf,{status:r.status})),t("code",null,r.id),t(vn,{data:r.result,empty:"无执行输出"}),t(bf,{title:`Task Result ${r.id}`,data:M$(r),onOpen:f})))))}function Bp(u){if(!u||typeof u!=="object")return"--";if(u.type==="interval")return`每 ${x0(Number(u.everySeconds||0))}`;return`每天 ${u.timeOfDay||"03:00"} UTC`}function Vp(u){if(!u||typeof u!=="object")return"--";if(u.type==="pgdata_backup")return`PGDATA -> ${u.remoteBaseDir||"/SERVER_DATA/UNIDESK_PG_DATA"}`;if(u.type==="dispatch")return`${u.providerId||"--"} / ${u.command||"--"}`;return String(u.type||"--")}function Dp(u){let f=String(u||"").toLowerCase();if(f==="succeeded")return"online";if(f==="failed")return"failed";if(f==="running"||f==="queued")return"warn";return f}function Xp(u){let f=Number(u?.durationMs);if(Number.isFinite(f)&&f>=0)return x0(f/1000);let l=J0(u?.startedAt||u?.createdAt);if(l===null)return"--";let n=J0(u?.finishedAt)??Date.now();return x0(Math.max(0,(n-l)/1000))}function lw(u){return{id:"unidesk-pgdata-baidu-daily",name:"PGDATA daily Baidu Netdisk backup",description:"Daily PostgreSQL physical base backup uploaded to Baidu Netdisk /SERVER_DATA with monthly rotation.",enabled:!0,timeOfDay:"03:30",actionType:"pgdata_backup",providerId:u[0]?.providerId||"main-server",command:"echo",payloadJson:JSON.stringify({source:"scheduled-task",message:"hello from scheduler"},null,2),remoteBaseDir:"/SERVER_DATA/UNIDESK_PG_DATA",stagingSubdir:"server-data/unidesk-pg-data",timeoutMs:"3600000"}}function Yp({schedules:u,scheduleRuns:f,nodes:l,refresh:r,onRaw:n}){let[i,y]=hu(lw(l||[])),[_,$]=hu(!1),[A,c]=hu(""),[j,F]=hu(""),U=[...f||[]].sort((W,z)=>(J0(z.updatedAt)??0)-(J0(W.updatedAt)??0));function Q(W,z){y((Z)=>({...Z,[W]:z}))}function L(W){let z=W?.action||{};y({id:W?.id||"",name:W?.name||"",description:W?.description||"",enabled:W?.enabled!==!1,timeOfDay:W?.schedule?.timeOfDay||"03:30",actionType:z.type||"dispatch",providerId:z.providerId||l[0]?.providerId||"main-server",command:z.command||"echo",payloadJson:JSON.stringify(z.payload||{source:"scheduled-task"},null,2),remoteBaseDir:z.remoteBaseDir||"/SERVER_DATA/UNIDESK_PG_DATA",stagingSubdir:z.stagingSubdir||"server-data/unidesk-pg-data",timeoutMs:String(z.timeoutMs||3600000)}),F(`正在编辑 ${W?.id||""}`)}function w(){let W={id:i.id,name:i.name,description:i.description,enabled:i.enabled,concurrencyPolicy:"skip",schedule:{type:"daily",timeOfDay:i.timeOfDay,timezone:"Etc/UTC"}};if(i.actionType==="pgdata_backup")return{...W,action:{type:"pgdata_backup",volumeName:"unidesk_pgdata_10gb",remoteBaseDir:i.remoteBaseDir,stagingSubdir:i.stagingSubdir,timeoutMs:Number(i.timeoutMs)||3600000,cleanupLocal:!0}};return{...W,action:{type:"dispatch",providerId:i.providerId,command:i.command,payload:JSON.parse(i.payloadJson||"{}"),timeoutMs:Number(i.timeoutMs)||600000}}}async function J(W){W.preventDefault(),$(!0),c(""),F("");try{let z=w(),Z=encodeURIComponent(String(z.id));await Eu(`${gu.apiBaseUrl}/schedules/${Z}`,{method:"PUT",body:JSON.stringify(z)}),F("定时任务已保存"),await r()}catch(z){c(Hu(z,"保存定时任务失败"))}finally{$(!1)}}async function N(W){if(!W?.id)return;$(!0),c(""),F("");try{await Eu(`${gu.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}`,{method:"DELETE"}),F(`已删除 ${W.id}`),await r()}catch(z){c(Hu(z,"删除定时任务失败"))}finally{$(!1)}}async function q(W){if(!W?.id)return;$(!0),c(""),F("");try{let z=await Eu(`${gu.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}/run`,{method:"POST",body:"{}"});F(`已触发 ${W.id} / ${z?.run?.id||"run"}`),await r()}catch(z){c(Hu(z,"触发定时任务失败"))}finally{$(!1)}}return t("div",{className:"page-grid scheduled-task-page","data-testid":"scheduled-task-page"},t(au,{title:"定时任务",eyebrow:`${(u||[]).length} Schedules`},(u||[]).length===0?t(Ff,{title:"暂无定时任务",text:"创建 daily / dispatch / PGDATA backup 任务后会在这里展示下一次执行时间和最近结果"}):t("div",{className:"schedule-card-grid"},(u||[]).map((W)=>t("article",{key:W.id,className:"schedule-card","data-testid":`schedule-row-${ol(W.id)}`},t("div",{className:"node-card-head"},t("strong",null,W.name||W.id),t(wf,{status:W.enabled?"online":"warn"},W.enabled?"enabled":"disabled")),t("code",null,W.id),t("dl",null,t("dt",null,"计划"),t("dd",null,Bp(W.schedule)),t("dt",null,"动作"),t("dd",null,Vp(W.action)),t("dt",null,"下次执行"),t("dd",null,Nu(W.nextRunAt)),t("dt",null,"最近执行"),t("dd",null,W.lastRunAt?`${Nu(W.lastRunAt)} / ${W.lastRunId||"--"}`:"--")),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>L(W)},"编辑"),t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>q(W),"data-testid":`schedule-run-${ol(W.id)}`},"手动触发"),t("button",{type:"button",className:"ghost-btn danger",disabled:_,onClick:()=>N(W)},"删除"),t(bf,{title:`Schedule ${W.id}`,data:W,onOpen:n})))))),t(au,{title:i.id?"配置定时任务":"新建定时任务",eyebrow:"CRUD"},t("form",{className:"dispatch-form schedule-form",onSubmit:J},t("label",null,"ID",t("input",{value:i.id,onChange:(W)=>Q("id",W.target.value)})),t("label",null,"名称",t("input",{value:i.name,onChange:(W)=>Q("name",W.target.value)})),t("label",null,"每日执行时间 UTC",t("input",{value:i.timeOfDay,placeholder:"03:30",onChange:(W)=>Q("timeOfDay",W.target.value)})),t("label",null,"启用",t("select",{value:i.enabled?"true":"false",onChange:(W)=>Q("enabled",W.target.value==="true")},t("option",{value:"true"},"enabled"),t("option",{value:"false"},"disabled"))),t("label",null,"动作类型",t("select",{value:i.actionType,onChange:(W)=>Q("actionType",W.target.value)},t("option",{value:"pgdata_backup"},"PGDATA 备份到百度网盘"),t("option",{value:"dispatch"},"Provider Dispatch"))),i.actionType==="pgdata_backup"?[t("label",{key:"remote"},"网盘根目录",t("input",{value:i.remoteBaseDir,onChange:(W)=>Q("remoteBaseDir",W.target.value)})),t("label",{key:"staging"},"本地 staging 子目录",t("input",{value:i.stagingSubdir,onChange:(W)=>Q("stagingSubdir",W.target.value)}))]:[t("label",{key:"provider"},"Provider",t("select",{value:i.providerId,onChange:(W)=>Q("providerId",W.target.value)},(l||[]).map((W)=>t("option",{key:W.providerId,value:W.providerId},`${W.name} / ${W.providerId}`)))),t("label",{key:"command"},"Command",t("select",{value:i.command,onChange:(W)=>Q("command",W.target.value)},t("option",{value:"echo"},"echo"),t("option",{value:"docker.ps"},"docker.ps"),t("option",{value:"host.ssh"},"host.ssh"),t("option",{value:"microservice.http"},"microservice.http"))),t("label",{key:"payload",className:"raw-editor-label"},"Payload JSON",t("textarea",{className:"raw-editor",value:i.payloadJson,onChange:(W)=>Q("payloadJson",W.target.value)}))],t("label",null,"超时 ms",t("input",{value:i.timeoutMs,onChange:(W)=>Q("timeoutMs",W.target.value)})),t("label",{className:"raw-editor-label"},"描述",t("textarea",{className:"raw-editor compact",value:i.description,onChange:(W)=>Q("description",W.target.value)})),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>y(lw(l||[]))},"重置"),t("button",{type:"submit",disabled:_||!i.id},_?"保存中":"保存任务")),j?t("p",{className:"muted paragraph"},j):null,t(yf,{error:A,wide:!0}))),t(au,{title:"历史执行记录",eyebrow:`${U.length} Runs`},U.length===0?t(Ff,{title:"暂无执行记录",text:"定时触发或手动触发后会生成 run history"}):t("div",{className:"table-wrap"},t("table",{className:"task-history-table schedule-run-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"触发"),t("th",null,"耗时"),t("th",null,"结果摘要"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,U.map((W)=>t("tr",{key:W.id,"data-testid":`schedule-run-row-${ol(W.id)}`},t("td",null,t(wf,{status:Dp(W.status)},W.status)),t("td",null,t("strong",null,W.scheduleId),t("code",null,W.id),W.taskId?t("code",null,W.taskId):null),t("td",null,W.trigger||"--"),t("td",null,Xp(W)),t("td",null,t(vn,{data:W.result||W.error,empty:"无结果"})),t("td",null,Nu(W.updatedAt)),t("td",null,t(bf,{title:`Schedule Run ${W.id}`,data:W,onOpen:n})))))))))}function Sp({data:u}){let f=u.overview||{};return t("div",{className:"page-grid topology-grid"},t(au,{title:"公开入口",eyebrow:"Public"},t("div",{className:"endpoint-list"},t("article",null,t("b",null,"Frontend"),t("span",null,gu.frontendPublicUrl||window.location.origin),t(wf,{status:"online"},"public")),t("article",null,t("b",null,"Provider Ingress"),t("span",null,gu.providerIngressPublicUrl||"ws://public/ws/provider"),t(wf,{status:"online"},"public")))),t(au,{title:"内部服务",eyebrow:"Docker Network Only"},t("div",{className:"endpoint-list"},t("article",null,t("b",null,"backend-core API"),t("span",null,"http://backend-core:8080"),t(wf,{status:"internal"},"internal")),t("article",null,t("b",null,"database"),t("span",null,"postgres://database:5432/unidesk"),t(wf,{status:"internal"},"internal")))),t(au,{title:"运行态",eyebrow:"Runtime"},t("div",{className:"metric-grid"},t(cf,{label:"DB Ready",value:f.dbReady?"YES":"NO",hint:"internal health"}),t(cf,{label:"Online Nodes",value:f.onlineNodeCount??0,hint:"provider-gateway self-link"}))))}function pp({session:u}){return t(au,{title:"认证策略",eyebrow:"Frontend Login"},t("div",{className:"policy-grid"},t("article",null,t("span",null,"默认账号"),t("strong",null,gu.authUsername||"admin")),t("article",null,t("span",null,"当前会话"),t("strong",null,u?.user?.username||"--")),t("article",null,t("span",null,"Session TTL"),t("strong",null,`${gu.sessionTtlSeconds||0}s`)),t("article",null,t("span",null,"API 访问"),t("strong",null,"同源 Cookie 保护"))),t("p",{className:"muted paragraph"},"浏览器只访问 frontend 同源接口;frontend 容器使用 Docker 内网代理 backend-core API。"))}function mp(){return t(au,{title:"安全边界",eyebrow:"Exposure Rule"},t("div",{className:"security-board"},t("article",{className:"allow"},t("b",null,"允许公网"),t("span",null,"frontend 登录入口"),t("span",null,"provider ingress WebSocket/health")),t("article",{className:"deny"},t("b",null,"禁止公网"),t("span",null,"backend-core REST API"),t("span",null,"PostgreSQL database")),t("article",null,t("b",null,"数据库卷"),t("span",null,"named volume unidesk_pgdata_10gb"),t("span",null,"CLI stop/start 不删除数据卷"))))}function Pp({activeModule:u,activeTab:f,data:l,session:r,refresh:n,onRaw:i,onNavigate:y}){if(u==="ops"&&f==="status")return t(fp,{data:l,onRaw:i,onNavigate:y});if(u==="ops"&&f==="performance")return t(Qp,{onRaw:i});if(u==="ops"&&f==="events")return t(rp,{events:l.events,onRaw:i});if(u==="ops"&&f==="logs")return t(np,{logs:l.logs,onRaw:i});if(u==="nodes"&&f==="list")return t(ip,{nodes:l.nodes,onRaw:i});if(u==="nodes"&&f==="monitor")return t($p,{nodes:l.nodes,systemStatuses:l.systemStatuses,tasks:l.tasks,onRaw:i,refresh:n});if(u==="nodes"&&f==="docker")return t(Kp,{nodes:l.nodes,dockerStatuses:l.dockerStatuses,onRaw:i});if(u==="nodes"&&f==="gateway")return t(Wp,{nodes:l.nodes,tasks:l.tasks,onRaw:i});if(u==="nodes"&&f==="labels")return t(yp,{nodes:l.nodes});if(u==="nodes"&&f==="heartbeats")return t(_p,{nodes:l.nodes});if(u==="tasks"&&f==="dispatch")return t(Tp,{nodes:l.nodes,onDispatched:n,onRaw:i});if(u==="tasks"&&f==="scheduled")return t(Yp,{schedules:l.schedules,scheduleRuns:l.scheduleRuns,nodes:l.nodes,refresh:n,onRaw:i});if(u==="tasks"&&f==="pending")return t(Zp,{tasks:l.pendingTasks,onRaw:i});if(u==="tasks"&&f==="history")return t(Op,{tasks:l.tasks,onRaw:i});if(u==="tasks"&&f==="results")return t(Hp,{tasks:l.tasks,onRaw:i});if(u==="apps"&&f==="catalog")return t(zp,{microservices:l.microservices,onRaw:i,onNavigate:y});if(u==="apps"&&f==="todo-note")return t(RL,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="findjob")return t(YQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="pipeline")return t(XL,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="met-nonlinear")return t(MQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="claudeqq")return t(tU,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="baidu-netdisk")return t(yU,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="filebrowser")return t(XQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="oa-event-flow")return t(kQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="code-queue")return t(ZQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl,initialTasksData:mS});if(u==="apps"&&f==="project-manager")return t(pL,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="config"&&f==="topology")return t(Sp,{data:l});if(u==="config"&&f==="auth")return t(pp,{session:r});if(u==="config"&&f==="security")return t(mp);return t(Ff,{title:"未找到页面",text:"请选择左侧主模块和顶部子功能标签"})}function Mp({session:u,onLogout:f}){let l=yA(Vr,window.location.pathname),[r,n]=hu(l.moduleId),[i,y]=hu({...b_,[l.moduleId]:l.tabId}),[_,$]=hu({overview:null,nodes:[],systemStatuses:[],dockerStatuses:[],microservices:[],events:[],tasks:[],pendingTasks:[],schedules:[],scheduleRuns:[],logs:[]}),[A,c]=hu({ok:!1,text:"连接中"}),[j,F]=hu(null),[U,Q]=hu(new Date),[L,w]=hu(null),[J,N]=hu(!1),[q,W]=hu(!1),z=bn.default.useRef(!1),Z=Vr.moduleById[r]||Vr.modules[0],H=i[r]||b_[r]||Z.tabs[0].id,E=Array.isArray(_.microservices)?_.microservices:[],D=E.length===0&&r==="apps"&&H==="code-queue"?[PS]:E,h=D===E?_:{..._,microservices:D},V=r==="apps"?D.find((o)=>String(o?.id||"")===H):null,Y=V?Uw(V):{},p=Z.tabs.find((o)=>o.id===H)?.label||H,O=V?[{key:"microservice",label:"用户服务",value:`${p} ${Y.providerStatus==="online"?"在线":Y.providerStatus||"未知"}`,tone:Y.providerStatus==="online"?"ok":"warn",testId:"active-microservice-status"}]:[];async function m(){if(z.current)return;z.current=!0,W(!0);try{let o=[],s=(ju,Gu)=>{o.push([ju,Eu(Gu)])},x=r==="ops"&&H==="status",fu=x||r==="config"&&H==="topology",$u=x||r==="nodes"||r==="tasks"&&(H==="dispatch"||H==="scheduled"),tu=r==="apps"&&H!=="code-queue";if(fu)s("overview",`${gu.apiBaseUrl}/overview`);if($u)s("nodes",`${gu.apiBaseUrl}/nodes`);if(r==="nodes"&&H==="monitor")s("systemStatuses",`${gu.apiBaseUrl}/nodes/system-status?limit=60`),s("tasks",`${gu.apiBaseUrl}/tasks?limit=120&summary=1`);else if(r==="nodes"&&H==="docker")s("dockerStatuses",`${gu.apiBaseUrl}/nodes/docker-status`);else if(r==="nodes"&&H==="gateway")s("tasks",`${gu.apiBaseUrl}/tasks?limit=300&summary=1`);else if(r==="tasks"&&H==="scheduled")s("schedules",`${gu.apiBaseUrl}/schedules?limit=100`),s("scheduleRuns",`${gu.apiBaseUrl}/schedules/runs?limit=100`);else if(r==="tasks"&&H==="pending")s("pendingTasks",`${gu.apiBaseUrl}/tasks?status=pending&limit=100&summary=1`);else if(r==="tasks"&&(H==="history"||H==="results"))s("tasks",`${gu.apiBaseUrl}/tasks?limit=300&summary=1`);else if(x)s("tasks",`${gu.apiBaseUrl}/tasks?limit=8&lite=1`),s("pendingTasks",`${gu.apiBaseUrl}/tasks?status=pending&limit=20&lite=1`);if(tu)s("microservices",`${gu.apiBaseUrl}/microservices`);if(r==="ops"&&H==="events")s("events",`${gu.apiBaseUrl}/events?limit=100`);if(r==="ops"&&H==="logs")s("logs","/logs?limit=100");await Promise.all(o.map(async([ju,Gu])=>{let qu=await Gu,P={};if(ju==="overview")P.overview=qu;if(ju==="nodes")P.nodes=qu.nodes||[];if(ju==="systemStatuses")P.systemStatuses=qu.systemStatuses||[];if(ju==="dockerStatuses")P.dockerStatuses=qu.dockerStatuses||[];if(ju==="microservices")P.microservices=qu.microservices||[];if(ju==="events")P.events=qu.events||[];if(ju==="tasks")P.tasks=qu.tasks||[];if(ju==="pendingTasks")P.pendingTasks=qu.tasks||[];if(ju==="schedules")P.schedules=qu.schedules||[];if(ju==="scheduleRuns")P.scheduleRuns=qu.runs||[];if(ju==="logs")P.logs=qu.logs||[];$((e)=>({...e,...P}))})),c({ok:!0,text:"核心在线"}),F(new Date)}catch(o){if(c({ok:!1,text:Hu(o,"连接失败")}),o.status===401)f(!1)}finally{z.current=!1,W(!1)}}F0(()=>{let o=()=>{if(!IL())return;m()};o();let s=setInterval(o,MS(r,H)),x=()=>{if(IL())o()};return document.addEventListener("visibilitychange",x),()=>{clearInterval(s),document.removeEventListener("visibilitychange",x)}},[r,H]),F0(()=>{let o=setInterval(()=>Q(new Date),1000);return()=>clearInterval(o)},[]),F0(()=>{let o=hQ(Vr,window.location.pathname);if(o&&window.location.pathname!==o)window.history.replaceState(null,"",o)},[]),F0(()=>{let o=()=>{let s=yA(Vr,window.location.pathname);n(s.moduleId),y((x)=>({...x,[s.moduleId]:s.tabId})),w(null)};return window.addEventListener("popstate",o),()=>window.removeEventListener("popstate",o)},[]),F0(()=>{window.scrollTo({top:0,left:0,behavior:"auto"})},[r,H]);function X(o,s,x="push"){let fu=Vr.moduleById[o]?o:Vr.fallbackTarget.moduleId,$u=Vr.moduleById[fu]?.tabs.some((ju)=>ju.id===s)?s:b_[fu]||Vr.moduleById[fu]?.tabs[0]?.id||Vr.fallbackTarget.tabId;n(fu),y((ju)=>({...ju,[fu]:$u}));let tu=f6(Vr,fu,$u);if(window.location.pathname!==tu){let ju=x==="replace"?"replaceState":"pushState";window.history[ju](null,"",tu)}}function v(o,s){w({title:o,data:s})}let[T,S]=hu(!1),{unreadCount:k,notifications:I}=Vl(),b=I.length>0?I[I.length-1]:null;return t("div",{className:`shell ${J?"rail-collapsed":""}`,"data-testid":"app-shell"},t(eS,{activeModule:r,activeTabs:i,onNavigate:X,collapsed:J,onToggle:()=>N((o)=>!o)}),t("main",{className:"workspace"},t(oS,{connection:A,lastRefresh:j,onRefresh:m,onLogout:()=>f(!0),session:u,clock:U,activeStatusItems:O,onNotificationToggle:()=>S((o)=>!o),unreadCount:k}),t(up,{module:Z,activeTab:H,onNavigate:X}),t(s9.Provider,{value:q},t(Pp,{activeModule:r,activeTab:H,data:h,session:u,refresh:m,onRaw:v,onNavigate:X}))),t(sS,{raw:L,onClose:()=>w(null)}),b&&t(kL,{key:b.id,notification:b}),T&&t(vL,{onClose:()=>S(!1)}))}function Cp(){let[u,f]=hu(!0),[l,r]=hu(null);async function n(){f(!0);try{let y=await Eu("/api/session");r(y.authenticated?y:null)}catch{r(null)}finally{f(!1)}}async function i(y){if(y)try{await Eu("/logout",{method:"POST"})}catch{}r(null)}if(F0(()=>{n()},[]),u)return t("main",{className:"loading-screen"},t("div",{className:"brand-mark"},"UD"),t("span",null,"加载会话"));if(!l)return t(aS,{onLogin:r});return t(iU,null,t(Mp,{session:l,onLogout:i}))}var ww=document.getElementById("root");if(ww===null)throw Error("root element not found");rw.createRoot(ww).render(t(Cp));})(); + `,width:L,height:w}}function W8(u,f){let l=URL.createObjectURL(u),r=document.createElement("a");r.href=l,r.download=f,r.click(),setTimeout(()=>URL.revokeObjectURL(l),1000)}async function EL(u,f){let l=TL(f,"pipeline"),{svg:r,width:n,height:i}=bY(u,f),y=new Blob([r],{type:"image/svg+xml;charset=utf-8"}),_=URL.createObjectURL(y);try{let $=new Image;await new Promise((F,U)=>{$.onload=()=>F(),$.onerror=()=>U(Error("svg image load failed")),$.src=_});let A=document.createElement("canvas");A.width=n,A.height=i;let c=A.getContext("2d");if(!c)throw Error("canvas unavailable");c.drawImage($,0,0);let j=await new Promise((F)=>A.toBlob(F,"image/png"));if(!j)throw Error("png export failed");W8(j,`${l}.png`)}catch{W8(y,`${l}.svg`)}finally{URL.revokeObjectURL(_)}}async function sY(u){let f=TL(String(u?.title||"pipeline-gantt"),"pipeline-gantt"),{svg:l,width:r,height:n}=gY(u),i=new Blob([l],{type:"image/svg+xml;charset=utf-8"}),y=URL.createObjectURL(i);try{let _=new Image;await new Promise((j,F)=>{_.onload=()=>j(),_.onerror=()=>F(Error("gantt svg image load failed")),_.src=y});let $=document.createElement("canvas");$.width=r,$.height=n;let A=$.getContext("2d");if(!A)throw Error("canvas unavailable");A.drawImage(_,0,0);let c=await new Promise((j)=>$.toBlob(j,"image/png"));if(!c)throw Error("gantt png export failed");W8(c,`${f}.png`)}catch{W8(i,`${f}.svg`)}finally{URL.revokeObjectURL(y)}}async function aY(u){for(let f of u){if(f.flow.nodes.length===0)continue;await EL(f.flow,f.title),await new Promise((l)=>setTimeout(l,750))}}function tL(u,f){return u.find((l)=>String(l?.pipelineId||"")===f)||null}function AL(u){return ku(u?.startedAt)??ku(u?.artifact?.startedAt)??ku(u?.request?.createdAt)??ku(u?.updatedAt)??0}function oY(u,f){return u.filter((l)=>String(l?.pipelineId||"")===f).slice().sort((l,r)=>AL(l)-AL(r)||String(l?.runId||"").localeCompare(String(r?.runId||"")))}function H9(u,f){let l=String(f?.runId||""),r=u.findIndex((y)=>String(y?.runId||"")===l),n=r>=0?r+1:u.length,i=String(f?.status||"--");return`Epoch ${n} / ${l||"--"} / ${i}`}function Br(u){return String(u?.procedureRunId||u?.runId||"")}function G8(u,f){let l=String(u?.nodeId||u?.request?.nodeId||"");if(l)return l;let r=Br(u),n=`${f}__`;if(r.startsWith(n))return r.slice(n.length).replace(/__\d+$/u,"");return""}function A8(u,f){let l=Du(u?.artifact)?u.artifact:{},r=Du(u?.request)?u.request:{};return m$(u?.startedAt,l.startedAt,r.createdAt,r.startedAt,u?.createdAt,u?.updatedAt,f?.startedAt,f?.request?.createdAt)}function c8(u,f){let l=String(u?.status?.status||u?.artifact?.status||u?.status||"").toLowerCase(),r=Du(u?.artifact)?u.artifact:{},n=X9(l);return m$(u?.finishedAt,r.finishedAt,u?.completedAt,n?u?.updatedAt:void 0,n?r.updatedAt:void 0,n?f?.updatedAt:void 0)}function ZL(u,f,l=Date.now()){let r=String(u?.runId||""),n=new Set(f.map((i)=>String(i?.id||"")).filter(Boolean));return Vu(u?.procedureRuns).flatMap((i)=>{let y=G8(i,r);if(!y)return[];let _=String(i?.status?.status||i?.artifact?.status||i?.status||"unknown").toLowerCase(),$=A8(i,u),A=ku($);if(A===null)return[];let c=c8(i,u),j=ku(c)??(X9(_)?ku(i?.updatedAt)??A+1000:l),F=Math.max(A+1000,j);return[{nodeId:y,knownNode:n.has(y),procedureRunId:Br(i),status:_,startMs:A,endMs:F,startedAt:Y$(A),finishedAt:Y$(F),durationMs:F-A,runId:r,raw:i}]}).sort((i,y)=>i.startMs-y.startMs||i.endMs-y.endMs||i.nodeId.localeCompare(y.nodeId))}function dY(u,f,l=[]){let r=f.map((c)=>Number(c.startMs)).filter(Number.isFinite),n=f.map((c)=>Number(c.endMs)).filter(Number.isFinite);for(let c of l){let j=Vf(c?.eventMs??c?.ms);if(j!==null)r.push(j),n.push(j)}let i=ku(u?.startedAt)??ku(u?.artifact?.startedAt)??ku(u?.request?.createdAt),y=ku(u?.finishedAt)??ku(u?.artifact?.finishedAt)??ku(u?.updatedAt);if(i!==null)r.push(i);if(y!==null)n.push(y);let _=Date.now(),$=r.length>0?Math.min(...r):_-60000,A=Math.max($+60000,n.length>0?Math.max(...n):_);return{startMs:$,endMs:A,durationMs:A-$}}var j8=12,OL=20,B9=100,eY=!1;function bn(u){let f=Number(u);if(!Number.isFinite(f))return 0;return Math.max(0,Math.min(100,Math.round(f*100)/100))}function uS(u){let f=Math.max(j8,Number(u||j8)),l=Math.log(f/j8)/Math.log(OL);return bn(l*100)}var p$=uS(B9);function M9(u){let f=bn(u)/100,l=j8*Math.pow(OL,f),r=f<0.24?"全局":f<0.64?"均衡":"细节";return{value:bn(f*100),pxPerMinute:l,label:r}}function K9(u){let f=Math.round(Number(u));return Math.abs(f-B9)<=1?B9:f}function fS(u,f=p$){let l=Math.max(1,Number(u.durationMs||0)/60000),r=M9(f);return Math.round(Math.max(360,Math.min(7200,l*Number(r.pxPerMinute||48))))}function lS(u,f=7){let l=Math.max(1,Number(u.endMs||0)-Number(u.startMs||0));return Array.from({length:f},(r,n)=>{let i=f===1?0:n/(f-1);return{ms:Number(u.startMs)+l*i,percent:i*100}})}function rS(u,f){let l=Math.max(1,Number(f.endMs)-Number(f.startMs));return Math.max(0,Math.min(100,(u-Number(f.startMs))/l*100))}function Vf(u){let f=Number(u);return Number.isFinite(f)?f:null}function C9(u){return JL(u?.status)&&!X9(u?.status)}function HL(u,f,l,r){let n=Math.max(1,l-f),i=Math.max(0,Math.min(1,(u-f)/n));return Number((i*r).toFixed(3))}function cL(u,f){if(!f)return null;let l=Vf(f?.startMs),r=Vf(f?.endMs),n=Vf(f?.chartHeight);if(l===null||r===null||n===null)return null;return HL(u,l,r,n)}function BL(u,f){let l=Vf(u?.rawStartMs??u?.startMs)??Vf(u?.startMs)??f,r=Vf(u?.endMs)??l+1000;if(!C9(u))return Math.max(l+1000,r);return Math.max(l+1000,r,f)}function nS(u,f,l,r){let n=Vf(u?.startMs)??r-60000,i=Vf(u?.endMs)??r,y=l.reduce((Q,L)=>Math.max(Q,BL(L,r)),i),_=Math.max(n+60000,i,y),$=Math.max(1,_-n),A={startMs:n,endMs:_,durationMs:$},c=fS(A,f),j=M9(f),F=Math.max(5,Math.min(18,Math.round(c/150))),U=lS(A,F).map((Q)=>{let L=Number(Q.ms),w=HL(L,n,_,c);return{...Q,y:w,timestamp:Y$(L),offsetMs:L-n}});return{source:"frontend-y",startMs:n,endMs:_,durationMs:$,chartHeight:c,scale:bn(f),normalizedScale:Number((bn(f)/100).toFixed(3)),pxPerMinute:Number(Number(j.pxPerMinute||0).toFixed(3)),ticks:U}}function iS(u,f,l){if(!C9(u))return u;let r=Vf(u?.rawStartMs??u?.startMs)??Vf(u?.startMs)??l,n=BL(u,l),i=cL(r,f),y=cL(n,f),_=Vf(i??u?.y1??u?.startY)??0,$=Vf(y??u?.y2??u?.endY)??_+10,A=Math.max(24,$-_);return{...u,live:!0,startMs:r,endMs:n,durationMs:Math.max(1000,n-r),finishedAt:Y$(n),y1:_,y2:$,startY:_,endY:$,height:A}}function R9(u,f,l){return rS(u,f)/100*l}function Uy(u){return Boolean(u&&String(u?.source||"")!=="frontend-y")}function VL(u,f,l,r,n){if(Uy(r))for(let y of n){let _=Vf(u?.[y]);if(_!==null)return _}let i=Vf(u?.ms??u?.eventMs??u?.startMs);return R9(i??Number(f.startMs),f,l)}function L8(u,f,l,r){return VL(u,f,l,r,["y1","startY"])}function V9(u,f,l,r){if(Uy(r)){let i=Vf(u?.y2??u?.endY);if(i!==null)return i}let n=Vf(u?.endMs)??Number(f.endMs);return R9(n,f,l)}function DL(u,f,l,r){if(Uy(r)){let i=Vf(u?.height);if(i!==null)return Math.max(1,i)}let n=u?.live?24:10;return Math.max(n,V9(u,f,l,r)-L8(u,f,l,r))}function Jr(u,f,l,r){return VL(u,f,l,r,["y","timeAxisY"])}function XL(u,f,l,r){if(Uy(r)||String(r?.source||"")==="frontend-y"){let y=Vf(u?.y);if(y!==null)return y}let n=Vf(u?.percent);if(n!==null)return n/100*l;let i=Vf(u?.ms)??Number(f.startMs);return R9(i,f,l)}function yS(u){let f=String(u?.promptEvent||u?.raw?.promptEvent||u?.event||"").toLowerCase();if(!["node-long-running-observation","node-finished"].includes(f))return"";let l=String(u?.sourceNodeId||u?.raw?.sourceNodeId||u?.raw?.detail?.nodeId||""),r=String(u?.nodeId||u?.targetNodeId||"");return l&&l!==r?l:""}function _S(u,f){let l=new Set(f.map((n)=>[String(n.sourceNodeId||""),String(n.targetNodeId||""),String(n.targetMarkerId||""),String(n.action||"")].join(":"))),r=[...f];for(let n of u){let i=yS(n),y=String(n?.nodeId||""),_=String(n?.id||"");if(!i||!y||!_)continue;let $=[i,y,_,"observe"].join(":");if(l.has($))continue;l.add($),r.push({id:`observation-arrow:${_}:${i}:${y}`,commandId:String(n?.commandId||n?.eventId||_),sourceNodeId:i,targetNodeId:y,sourceMarkerId:"",targetMarkerId:_,sourceKind:"monitor",action:"observe",status:"observation"})}return{markers:u,arrows:r}}function $S(u){let f=Ir(u),l=String(u?.promptEvent||"");if(f==="initial-prompt-delivered")return"initial";if(l==="node-finished"||l==="node-long-running-observation"||l.startsWith("monitor-"))return"monitor";if(f==="monitor-prompt-delivered"||String(u?.sourceKind||"").toLowerCase()==="monitor")return"monitor";return"append"}function tS(u){return Vu(u?.tags||u?.raw?.tags).map((f)=>String(f||"")).filter(Boolean)}function AS(u){let f=Ir(u),l=String(u?.promptEvent||"");if(f==="initial-prompt-delivered")return"初始 prompt";if(l==="node-long-running-observation")return"长任务观察";if(l==="node-finished")return tS(u).includes("monitor.audit")?"节点完成 / OA 审核":"节点完成";if(l==="monitor-interval")return"Monitor observation";if(l==="monitor-start")return"Monitor start";if(l==="monitor-stop")return"Monitor stop";if(f==="monitor-prompt-delivered")return"Monitor prompt";if(f==="append-prompt-queued")return"追加 prompt 已排队";return"追加 prompt"}function jL(u){let f=Ir(u);if(f==="control-command-applied")return 3;if(f==="control-command-ignored")return 2;if(f==="control-command-queued")return 1;return 0}function cS(u,f){let l=String(u?.commandId||"");if(l)return`command:${l}`;return["control-event",jy(u)||m$(u?.createdAt,u?.timestamp)||`index-${f}`,String(u?.sourceKind||""),String(u?.sourceNodeId||""),String(u?.targetNodeId||""),R1(u)].join(":")}function jS(u){return Z9([u?.targetNodeId,...Vu(u?.resetNodeIds)])}function FS(u,f){let l=D$(u),r=Ir(u),n=String(u?.targetNodeId||""),i=Boolean(n)&&f!==n;if(r==="control-command-applied")return i?`${l} 波及`:`${l} 生效`;if(r==="control-command-ignored")return`${l} 忽略`;if(r==="control-command-queued")return`${l} 已发起`;return i?`${l} 波及`:l}function JS(u){if(Ir(u)==="control-command-ignored")return"ignored";let l=R1(u);if(l==="restart"||l==="redo")return"restart";if(l==="modify")return"modify";if(l==="approve")return"approve";if(l==="guide")return"guide";return"pending"}function US(u){let f=String(u?.sourceKind||"").toLowerCase();if(f==="monitor")return"monitor";if(f==="webui")return"webui";if(f==="cli")return"cli";return"system"}function QS(u,f,l,r){let n=u.filter((A)=>String(A.nodeId||"")===f).sort((A,c)=>Number(A.startMs)-Number(c.startMs)),i=n.find((A)=>l>=Number(A.startMs)-1000&&l<=Number(A.endMs)+1000);if(i)return{ms:l,onInterval:!0,snapReason:"inside-interval",procedureRunId:String(i.procedureRunId||"")};let y=R1(r),_=n.slice().reverse().find((A)=>Number(A.endMs)<=l+1000);if(_&&y==="approve")return{ms:Number(_.endMs),onInterval:!0,snapReason:"previous-interval-end",procedureRunId:String(_.procedureRunId||"")};let $=n.find((A)=>Number(A.startMs)>=l-1000);if($&&["guide","modify","restart","redo"].includes(y))return{ms:Number($.startMs),onInterval:!0,snapReason:"next-interval-start",procedureRunId:String($.procedureRunId||"")};return{ms:l,onInterval:!1,snapReason:"event-time",procedureRunId:String(r?.procedureRunId||"")}}function YL(u,f,l,r){let n=Math.hypot(l-u,r-f),i=n>gW?gW:0,y=i>0?l-(l-u)/n*i:l,_=i>0?r-(r-f)/n*i:r,$=y-u,A=Math.max(16,Math.min(42,Math.abs($)*0.45+12)),c=$===0?1:Math.sign($);return`M ${u},${f} C ${u+c*A},${f} ${y-c*A},${_} ${y},${_}`}function qS(u,f){let l=String(u?.runId||f?.runId||""),r=ZL({...Du(f)?f:{},...Du(u)?u:{},runId:l,procedureRuns:Vu(u?.procedureRuns).length>0?u.procedureRuns:f?.procedureRuns},[]),n=[],i=[],y=[],_=new Set,$=new Map,A=(F,U)=>{if(!F.nodeId||!Number.isFinite(Number(F.ms)))return;if(_.has(F.id))return;_.add(F.id),U.push(F)};for(let F of Vu(u?.procedureRuns)){let U=G8(F,l),Q=Br(F);if(!U)continue;for(let L of Vu(F?.attempts)){let w=K8(L);for(let J of E9(L?.controlEventRecords)){let N=Ir(J);if(!["initial-prompt-delivered","append-prompt-delivered","monitor-prompt-delivered"].includes(N))continue;let q=jy(J),W=ku(q);if(W===null)continue;let z=String(J?.eventId||"");A({id:`prompt:${z||`${Q}:${w}:${N}:${W}`}`,runId:l,nodeId:U,procedureRunId:Q,attempt:w,kind:"prompt",tone:$S(J),status:"delivered",label:AS(J),ms:W,timestampIso:q,sourceKind:String(J?.sourceKind||""),sourceNodeId:String(J?.sourceNodeId||""),targetNodeId:U,action:"",eventId:z,commandId:String(J?.commandId||""),raw:J},n)}}}let c=new Map;E9(u?.controlEvents).forEach((F,U)=>{let Q=cS(F,U),L=c.get(Q)||{key:Q,events:[]};L.events.push(F),c.set(Q,L)});for(let F of c.values()){let U=Vu(F.events).slice().sort((V,Y)=>jL(Y)-jL(V)),Q=Vu(F.events).find((V)=>Ir(V)==="control-command-queued")||null,L=U[0]||Q;if(!Q&&!L)continue;let w=String(Q?.sourceNodeId||L?.sourceNodeId||""),J=String(Q?.sourceKind||L?.sourceKind||""),N=jy(Q)||jy(L)||m$(Q?.createdAt,L?.createdAt),q=ku(N),W=String(L?.commandId||Q?.commandId||F.key),z=(Ir(L)||"control-command-queued").replace(/^control-command-/u,""),Z="";if(w&&q!==null)Z=`control-source:${W}:${w}`,$.set(W,Z),A({id:Z,runId:l,nodeId:w,procedureRunId:String(Q?.procedureRunId||L?.procedureRunId||""),attempt:"",kind:"control-source",tone:US(Q||L),status:z,label:`${D$(Q||L)} 发起`,ms:q,timestampIso:N,action:R1(Q||L),sourceKind:J,sourceNodeId:w,targetNodeId:String(L?.targetNodeId||Q?.targetNodeId||""),commandId:W,raw:Q||L},i);let H=L||Q,E=jy(H)||N,D=ku(E);if(D===null)continue;let h=jS(H);for(let V of h){let Y=QS(r,V,D,H),p=`control-target:${W}:${V}`;if(A({id:p,runId:l,nodeId:V,procedureRunId:Y.procedureRunId,attempt:"",kind:"control-target",tone:JS(H),status:z,label:FS(H,V),ms:Y.ms,eventMs:D,onInterval:Y.onInterval,snapReason:Y.snapReason,snapped:Number(Y.ms)!==D,timestampIso:E,renderedTimestampIso:Y$(Number(Y.ms)),action:R1(H),sourceKind:J,sourceNodeId:w,targetNodeId:V,commandId:W,raw:H},i),Z&&w&&w!==V)y.push({id:`control-arrow:${W}:${w}:${V}`,commandId:W,sourceNodeId:w,targetNodeId:V,sourceMarkerId:Z,targetMarkerId:p,sourceKind:J,action:R1(H),status:z})}}let j=[...n,...i].sort((F,U)=>Number(F.ms)-Number(U.ms)||String(F.nodeId).localeCompare(String(U.nodeId))||String(F.id).localeCompare(String(U.id)));return{..._S(j,y),sourceMarkerByCommand:$}}function NS({details:u,selectedNodeId:f,selectedNodeRuntime:l,control:r,onRaw:n}){if(!u)return G("span",{className:"muted"},"点击“抓取过程”读取 node 运行材料;主界面只显示结构化摘要,完整内容需点开原始 JSON。");let i=Vu(u.procedureRuns),y=i.at(-1)||{},_=Vu(y.attempts),$=_.at(-1)||{},A=Vu(y.workerLogTail),c=Vu($.controlEventsTail),j=Vu($.controlPromptsTail),F=Vu($.monitorPromptsTail),U=N9(c),Q=N9(j),L=N9(F),w=$.opencodeMessages||{};return G("div",{className:"pipeline-evidence-list compact"},G(Or,{title:"Node runtime",subtitle:f||"--",facts:[`status ${l?.status||"pending"}`,`attempts ${l?.attempts??_.length}`,`procedure ${l?.currentProcedureRunId||Br(y)||"--"}`,r.fetchedAt?`fetched ${$f(r.fetchedAt)}`:"not fetched"],data:u.node||u,onRaw:n,testId:"raw-pipeline-node-runtime"}),G(Or,{title:"Procedure runs",subtitle:`${i.length} groups`,facts:[`latest ${y.status?.status||y.status||"--"}`,`steps ${Vu(y.recentSteps).length}`,`duration ${Hr(ku(y.finishedAt)&&ku(y.startedAt)?Number(ku(y.finishedAt))-Number(ku(y.startedAt)):y.durationMs)}`],data:i,onRaw:n,testId:"raw-pipeline-node-procedures"}),G(Or,{title:"OpenCode messages",subtitle:String(w.exists?"available":"not indexed"),facts:[`messages ${J8(w.messageCount)}`,`size ${J8(w.size)}`,`updated ${Nu(w.updatedAt)}`],data:w,onRaw:n,testId:"raw-pipeline-node-messages"}),G(Or,{title:"Control prompts",subtitle:"manual / monitor append queues",facts:[`manual tail ${Q.total}`,`monitor tail ${L.total}`,`last ${Nu(D9(Q.lastAt,L.lastAt))}`],data:{controlPromptsTail:j,monitorPromptsTail:F},onRaw:n,testId:"raw-pipeline-node-prompts"}),G(Or,{title:"Control events",subtitle:U.eventKinds.length>0?U.eventKinds.join(", "):"event tail",facts:[`tail ${U.total}`,`parsed ${U.parsed}`,`last ${Nu(U.lastAt)}`],data:c,onRaw:n,testId:"raw-pipeline-node-events"}),G(Or,{title:"Worker log",subtitle:"tail is hidden on main canvas",facts:[`tail ${A.length} lines`,"raw only via button",`procedure ${Br(y)||"--"}`],data:A,onRaw:n,testId:"raw-pipeline-node-worker-log"}))}function WS({activeRun:u,onRaw:f}){if(!u)return G(Ur,{title:"暂无运行材料",text:"没有 Pipeline epoch 时不会展示运行材料索引。"});let l=Vu(u.nodes),r=Vu(u.procedureRuns),n=Vu(u.submissions),i=Vu(u.workerLogTail),y=oW(l),_=oW(r),$=r.filter((c)=>String(c?.status||"").toLowerCase()==="failed"),A=D9(...r.flatMap((c)=>[c.updatedAt,c.finishedAt,c.startedAt]));return G("div",{className:"pipeline-evidence-list"},G(Or,{title:"Epoch overview",subtitle:u.runId||"--",facts:[`pipeline ${u.pipelineId||"--"}`,`status ${u.status||"--"}`,`started ${Nu(u.startedAt)}`,`updated ${Nu(u.updatedAt)}`],data:u,onRaw:f,testId:"raw-pipeline-run"}),G(Or,{title:"Node states",subtitle:`${l.length} nodes`,facts:[`running ${y.running||0}`,`succeeded ${y.succeeded||0}`,`failed ${y.failed||0}`,`pending ${y.pending||0}`],data:l,onRaw:f,testId:"raw-pipeline-run-nodes"}),G(Or,{title:"Procedure run index",subtitle:`${r.length} procedure records`,facts:[`succeeded ${_.succeeded||0}`,`failed ${_.failed||0}`,`latest ${Nu(A)}`,`errors ${$.length}`],data:r,onRaw:f,testId:"raw-pipeline-run-procedures"}),G(Or,{title:"OA submissions",subtitle:`${n.length} submission files`,facts:[`records ${n.length}`,`task ${J8(u.task)}`,"raw grouped by run"],data:n,onRaw:f,testId:"raw-pipeline-run-submissions"}),G(Or,{title:"Worker log tail",subtitle:"hidden from main interface",facts:[`tail ${i.length} lines`,"display raw only after click",`updated ${Nu(u.updatedAt)}`],data:i,onRaw:f,testId:"raw-pipeline-run-worker-log"}))}function LS({diagnostics:u,onRaw:f}){let l=Vu(u?.runs).filter(Du),r=Vu(u?.forbiddenResiduals),n=Du(u?.guarantees)?u.guarantees:{},i=u?.hasNeutralNodeFinishedEvidence===!0&&u?.hasNoAuditPolicyEvidence===!0&&u?.hasAuditPolicyEvidence===!0,y=u?.ok===!0&&i&&r.length===0,_=l[0]||null,$=[{label:"中性完成事实",ok:n.neutralNodeFinished===!0,hint:"node-finished 不携带流程策略"},{label:"Config 策略判定",ok:n.auditPolicyFromConfig===!0,hint:"OA backend 读取当前 epoch 配置"},{label:"控制命令来自 OA",ok:n.runnerConsumesControlCommandsFromOaEvents===!0,hint:"runner 只消费 OA control.command"},{label:"无独立审核事件",ok:n.noIndependentAuditRequestEvent===!0,hint:"审核由 node-finished + policy 派生"},{label:"无批次门禁",ok:n.noBatchFinishedControlGate===!0,hint:"下游启动由每个 node 完成驱动"}];return G("div",{className:"pipeline-oa-panel","data-testid":"pipeline-oa-event-flow-panel"},G("div",{className:"metric-grid compact"},G(Sl,{label:"OA Flow",value:y?"100%":"--",hint:String(u?.mode||"waiting diagnostics"),tone:y?"ok":"warn"}),G(Sl,{label:"禁止残留",value:r.length,hint:r.length===0?"source scan clean":"needs cleanup",tone:r.length===0?"ok":"warn"}),G(Sl,{label:"No-audit",value:u?.hasNoAuditPolicyEvidence?"OK":"--",hint:"OA 下游策略证据",tone:u?.hasNoAuditPolicyEvidence?"ok":"warn"}),G(Sl,{label:"Monitor 审核",value:u?.hasAuditPolicyEvidence?"OK":"--",hint:"OA 控制事件闭环",tone:u?.hasAuditPolicyEvidence?"ok":"warn"})),G("div",{className:"pipeline-oa-guarantees"},$.map((A)=>G("article",{key:A.label,className:`pipeline-oa-guarantee ${A.ok?"ok":"warn"}`},G(hn,{status:A.ok?"online":"warn"},A.ok?"OK":"MISS"),G("div",null,G("strong",null,A.label),G("span",null,A.hint))))),G("div",{className:"pipeline-evidence-list compact"},l.slice(0,6).map((A)=>G(Or,{key:A.runId,title:String(A.runId||"--"),subtitle:[Number(A.monitorAuditNodeFinishedCount||0)>0?"monitor audit":"",Number(A.noAuditPolicyCount||0)>0?"no-audit policy":""].filter(Boolean).join(" / ")||"event evidence",facts:[`events ${A.eventCount||0}`,`node-finished ${A.nodeFinishedCount||0}`,`policy-in-detail ${A.nodeFinishedWithPolicyCount||0}`,`queued ${A.controlQueuedCount||0}`,`applied ${A.controlAppliedCount||0}`],data:A,onRaw:f,testId:`raw-pipeline-oa-run-${String(A.runId||"run").replace(/[^a-zA-Z0-9_.-]+/g,"-")}`}))),_?G("p",{className:"muted paragraph"},`最新证据 ${_.runId}: ${_.nodeFinishedCount||0} 个 node-finished,${_.controlAppliedCount||0} 个控制结果。`):G(Ur,{title:"暂无 OA 事件流证据",text:"等待 Pipeline backend 暴露 diagnostics。"}),u?G("div",{className:"panel-actions inline-actions"},G(gr,{title:"Pipeline OA Event Flow Diagnostics",data:u,onOpen:f,testId:"raw-pipeline-oa-event-flow"})):null)}function wS({quota:u,onRaw:f}){let l=Du(u?.summary)?u.summary:{},r=Du(u?.target)?u.target:{},n=Du(u?.cache)?u.cache:{},i=u?.ok===!0,y=String(u?.modelId||l.modelName||r.modelName||"MiniMax-M2.7"),_=l.totalCount??r.currentIntervalTotalCount,$=l.usageCount??r.currentIntervalUsageCount,A=l.remainingCount??r.currentIntervalRemainingCount,c=l.remainingRatio??(Number.isFinite(Number(_))&&Number(_)>0&&Number.isFinite(Number(A))?Number(A)/Number(_):void 0),j=l.usageRatio??(Number.isFinite(Number(_))&&Number(_)>0&&Number.isFinite(Number($))?Number($)/Number(_):void 0),F=l.resetAt||r.endAt,U=l.remainsMs??r.remainsMs,Q=Number(A),L=!i||Number.isFinite(Q)&&Q<=0?"warn":"ok",w=[i?`endpoint ${u?.endpoint||"--"}`:"quota unavailable",`fetched ${F8(u?.fetchedAt)}`,n.hit?`cache ${Hr(n.ageMs)}`:"live quota"];return G("div",{className:"pipeline-minimax-quota-panel","data-testid":"pipeline-minimax-quota-panel"},G("div",{className:"metric-grid compact"},G(Sl,{label:"MiniMax",value:i?y:"--",hint:u?.modelComponent||u?.error||"model/minimax-m27",tone:L}),G(Sl,{label:"当前窗口",value:`${q9($)}/${q9(_)}`,hint:`已用 ${aW(j)}`,tone:L}),G(Sl,{label:"剩余额度",value:q9(A),hint:`剩余 ${aW(c)}`,tone:L}),G(Sl,{label:"重置时间",value:F8(F),hint:U!==void 0?`约 ${Hr(U)}`:Nu(F),tone:L})),G(Y9,{items:w}),i?G("p",{className:"muted paragraph"},`MiniMax 限额来自 D601 Pipeline 后端实时查询;当前模型匹配 ${l.modelName||r.modelName||y}。`):G(yf,{error:u?.error||"MiniMax 限额查询失败"}),u?G("div",{className:"panel-actions inline-actions"},G(gr,{title:"Pipeline MiniMax Quota",data:u,onOpen:f,testId:"raw-pipeline-minimax-quota"})):null)}function KS({epochs:u,activeRun:f,activePipeline:l,pipelineNodes:r,pipelineEdges:n,runDetails:i,nodeDetails:y,nodeDetailsState:_,ganttScale:$=p$,onGanttScaleChange:A,onRunChange:c,onIntervalSelect:j,onMarkerSelect:F,selection:U,detailOpen:Q,onDetailOpenChange:L,onRaw:w}){let[J,N]=sl(eY),[q,W]=sl({startY:0,endY:0,startMs:0,endMs:0}),[z,Z]=sl(Date.now()),H=Rn(null),E=String(f?.runId||""),D=Boolean(Q),h=(cu)=>{if(typeof L==="function")L(cu)},V=bn($??p$),Y=String(i?.runId||"")===E?i?.details:null,p=Y?{...Du(f)?f:{},...Du(Y)?Y:{},runId:E,procedureRuns:Vu(Y?.procedureRuns).length>0?Y.procedureRuns:f?.procedureRuns}:f,O=ZL(p,r,z),m=Y?qS(Y,p):{markers:[],arrows:[]},X=Vu(m.markers),v=dY(p,O,X),T=nS(v,V,O,z),S=String(T.source||"frontend-y"),k=O.map((cu)=>iS(cu,T,z)),I={startMs:Number(T.startMs),endMs:Number(T.endMs),durationMs:Math.max(1,Number(T.durationMs??Number(T.endMs)-Number(T.startMs)))},b=M9(V),o={...b,pxPerMinute:Number(T.pxPerMinute??b.pxPerMinute)},g=Math.round(Number(T.chartHeight||360)),x=O.some(C9);F0(()=>{if(!E||!x)return;let cu=window.setInterval(()=>Z(Date.now()),1000);return()=>window.clearInterval(cu)},[E,x]);let fu=xY(l,r,Array.isArray(n)?n:[]),$u=r.map((cu)=>String(cu?.id||"")).filter(Boolean),tu=k.map((cu)=>String(cu.nodeId||"")).filter(Boolean),ju=X.map((cu)=>String(cu.nodeId||"")).filter(Boolean),Gu=Array.from(new Set([...fu,...$u,...tu,...ju])),qu={startY:0,endY:g,startMs:Number(I.startMs),endMs:Number(I.endMs)},P=Number(q?.endY||0)>0?q:qu,e=(cu)=>{return L8(cu,I,g,T)<=Number(P.endY)&&V9(cu,I,g,T)>=Number(P.startY)},uu=(cu)=>{let Iu=Jr(cu,I,g,T);return Iu>=Number(P.startY)&&Iu<=Number(P.endY)},wu=new Set(Gu.filter((cu)=>k.some((Iu)=>Iu.nodeId===cu&&e(Iu))||X.some((Iu)=>Iu.nodeId===cu&&uu(Iu)))),s=J?Gu.filter((cu)=>wu.has(cu)):Gu,Qu=`${U9}px ${s.length>0?s.map(()=>`${c0}px`).join(" "):"minmax(160px, 1fr)"}`,zu=Vu(T.ticks).filter(Du),Ou=String(U?.mode==="interval"?U?.interval?.procedureRunId||"":""),bu=String(U?.mode==="event"?U?.marker?.id||"":""),eu=()=>{let cu=H.current;if(!cu){W(qu);return}let Iu=Math.max(0,cu.scrollTop-Q9),Jl=Math.max(120,cu.clientHeight-Q9),Su=Math.min(g,Iu+Jl),ll={startY:Iu,endY:Su,startMs:Number(I.startMs),endMs:Number(I.endMs)},rl=Math.max(0,Math.min(1,Iu/g)),el=Math.max(rl,Math.min(1,Su/g)),nl=Math.max(1,Number(I.endMs)-Number(I.startMs));ll.startMs=Number(I.startMs)+nl*rl,ll.endMs=Number(I.startMs)+nl*el,W(ll)};F0(()=>{let cu=H.current,Iu=window.setTimeout(eu,0);return cu?.addEventListener("scroll",eu),window.addEventListener("resize",eu),()=>{window.clearTimeout(Iu),cu?.removeEventListener("scroll",eu),window.removeEventListener("resize",eu)}},[E,I.startMs,I.endMs,g]);let pu=Math.max(0,Gu.length-s.length),Ff=new Set(X.filter((cu)=>s.includes(String(cu.nodeId||""))&&uu(cu)).map((cu)=>String(cu.id))),Fl=new Map(X.map((cu)=>[String(cu.id),cu])),Tl=Vu(m.arrows).filter((cu)=>{if(!Ff.has(String(cu.targetMarkerId||"")))return!1;if(String(cu.action||"")==="observe")return s.includes(String(cu.sourceNodeId||""));return Ff.has(String(cu.sourceMarkerId||""))}),fl=U9+Math.max(1,s.length)*c0,of=(cu)=>{let Iu=bn(cu.target.value);if(typeof A==="function")A(Iu);window.setTimeout(eu,0)},El=()=>sY({title:`${l?.id||"pipeline"}-${E||"epoch"}-gantt`,meta:[`run ${E||"--"}`,`${Nu(I.startMs)} -> ${Nu(I.endMs)}`,`duration ${Hr(I.durationMs)}`,`${o.label} / ${K9(o.pxPerMinute)} px/min`,`${s.length}/${Gu.length} nodes`,`${X.length} markers`],visibleNodeIds:s,intervals:k,markers:X.filter((cu)=>s.includes(String(cu.nodeId||""))),arrows:Tl,ticks:zu,bounds:I,chartHeight:g,backendLayout:T}),pl=Du(Y?.gantt?.diagnostics)?Y.gantt.diagnostics:null;return G(j0,{title:"Epoch 甘特图",eyebrow:`${l?.id||"pipeline"} / ${u.length} epochs`,className:"pipeline-wide-panel",loading:i?.loading,actions:G("div",{className:"pipeline-gantt-actions"},G("select",{value:E,disabled:u.length===0,onChange:(cu)=>c(cu.target.value),"data-testid":"pipeline-epoch-select"},u.map((cu)=>G("option",{key:cu.runId,value:cu.runId},H9(u,cu)))),G("label",{className:"pipeline-gantt-toggle"},G("input",{type:"checkbox","data-testid":"pipeline-gantt-auto-hide-idle",checked:J,onChange:(cu)=>{N(Boolean(cu.target.checked)),window.setTimeout(eu,0)}}),G("span",null,"自动隐藏空闲列")),G("label",{className:"pipeline-gantt-scale"},G("span",null,G("b",null,"时间尺度"),G("em",{"data-testid":"pipeline-gantt-scale-label"},`${o.label} · ${K9(o.pxPerMinute)} px/min`)),G("input",{type:"range",min:0,max:100,step:0.01,value:V,onChange:of,"aria-label":"调整甘特图时间尺度","data-testid":"pipeline-gantt-time-scale"}),G("small",null,G("span",null,"全局"),G("span",null,"细节"))),f?G("button",{type:"button",className:"ghost-btn",onClick:El,disabled:s.length===0,"data-testid":"pipeline-export-gantt"},"导出甘特图"):null,f?G(gr,{title:`Pipeline Epoch ${f.runId}`,data:f,onOpen:w,testId:"raw-pipeline-epoch-gantt"}):null)},!f?G(Ur,{title:"暂无 Epoch",text:"当前 pipeline 还没有完整运行记录。"}):k.length===0?G(Ur,{title:"暂无时间区间",text:"等待 D601 Pipeline backend 在 procedure summary 中返回 startedAt / finishedAt。"}):G("div",{className:"pipeline-gantt-wrap"},G("div",{className:`pipeline-gantt-detail-layout ${D?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-gantt-detail-layout","data-sidebar-open":D?"true":"false"},G("div",{className:"pipeline-gantt-main"},G("div",{className:"pipeline-gantt-main-head"},G("div",{className:"pipeline-gantt-meta"},G("span",null,`time ${Nu(I.startMs)} -> ${Nu(I.endMs)}`),G("span",null,`duration ${Hr(I.durationMs)}`),G("span",null,`scale ${o.label} / ${K9(o.pxPerMinute)} px/min`),G("span",null,`layout ${S}`),pl?G("span",null,`align ${pl.timeAxisAlignmentOk===!1?"check":"ok"}`):null,G("span",null,`visible ${s.length}/${Gu.length} nodes`),Y?G("span",null,`markers ${X.length}`):null,J&&pu>0?G("span",null,`hidden idle ${pu}`):null),!D?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!U?.mode,onClick:()=>h(!0),"data-testid":"pipeline-gantt-sidebar-toggle"},U?.mode?"展开详情":"点击甘特图元素展开详情"):null),G("div",{className:"pipeline-gantt-viewport",ref:H,"data-testid":"pipeline-epoch-gantt","data-pipeline-id":l?.id||"","data-run-id":E,"data-layout-source":S,"data-start-ms":String(I.startMs),"data-end-ms":String(I.endMs),"data-chart-height":String(g)},G("div",{className:"pipeline-gantt-board",style:{gridTemplateColumns:Qu,minWidth:`${fl}px`}},G("div",{className:"pipeline-gantt-head time"},"Time"),s.length===0?G("div",{className:"pipeline-gantt-head empty"},"当前时间窗无工作节点"):s.map((cu)=>G("div",{key:`head-${cu}`,className:"pipeline-gantt-head node",title:cu,"data-testid":"pipeline-gantt-head-node","data-node-id":cu},G(GY,{value:cu}))),G("div",{className:"pipeline-gantt-time-axis",style:{height:`${g}px`}},zu.map((cu)=>{let Iu=XL(cu,I,g,T);return G("div",{key:`tick-${cu.ms}-${Iu}`,className:"pipeline-gantt-tick",style:{top:`${Iu}px`},"data-testid":"pipeline-gantt-tick","data-ms":String(cu.ms),"data-y":String(Iu)},G("b",null,Nu(cu.ms)),G("span",null,`+${Hr(Number(cu.offsetMs??Number(cu.ms)-Number(I.startMs)))}`))})),s.length>0?G("svg",{className:"pipeline-gantt-arrow-layer",width:s.length*c0,height:g,viewBox:`0 0 ${s.length*c0} ${g}`,style:{left:`${U9}px`,top:`${Q9}px`,width:`${s.length*c0}px`,height:`${g}px`},"aria-hidden":"true"},G("defs",null,G("marker",{id:"pipeline-gantt-arrowhead",viewBox:"0 0 10 10",refX:9,refY:5,markerWidth:6,markerHeight:6,orient:"auto-start-reverse"},G("path",{d:"M 0 0 L 10 5 L 0 10 z",fill:"context-stroke"}))),Tl.map((cu)=>{let Iu=Fl.get(String(cu.targetMarkerId||""));if(!Iu)return null;let Jl=Fl.get(String(cu.sourceMarkerId||"")),Su=String(Jl?.nodeId||cu.sourceNodeId||""),ll=s.indexOf(Su),rl=s.indexOf(String(Iu.nodeId||""));if(ll<0||rl<0)return null;let el=ll*c0+c0/2,nl=rl*c0+c0/2,Zl=Jl?Jr(Jl,I,g,T):Jr(Iu,I,g,T),Q0=Jr(Iu,I,g,T);return G("path",{key:cu.id,className:`pipeline-gantt-arrow ${String(cu.sourceKind||"").toLowerCase()} ${String(cu.status||"").toLowerCase()} ${String(cu.action||"").toLowerCase()}`,d:YL(el,Zl,nl,Q0),markerEnd:"url(#pipeline-gantt-arrowhead)","data-testid":String(cu.action||"")==="observe"?"pipeline-gantt-observation-arrow":"pipeline-gantt-arrow","data-source-node-id":String(cu.sourceNodeId||""),"data-target-node-id":String(cu.targetNodeId||""),"data-target-marker-id":String(cu.targetMarkerId||""),"data-action":String(cu.action||""),"data-source-y":String(Zl),"data-target-y":String(Q0)})})):null,s.length===0?G("div",{className:"pipeline-gantt-empty-col",style:{height:`${g}px`}},"滚动到有活动的时间段后,相关 node 列会自动出现。"):s.map((cu)=>{let Iu=k.filter((Su)=>Su.nodeId===cu),Jl=X.filter((Su)=>String(Su.nodeId||"")===cu);return G("div",{key:`col-${cu}`,className:"pipeline-gantt-node-col",style:{height:`${g}px`}},Iu.map((Su)=>{let ll=L8(Su,I,g,T),rl=V9(Su,I,g,T),el=DL(Su,I,g,T),nl=String(Su.procedureRunId||`${cu}-${Su.startMs}`);return G("button",{key:nl,type:"button",className:`pipeline-gantt-bar ${Su.status} ${Su.live?"live":""} ${Ou===nl?"selected":""}`,style:{top:`${ll}px`,height:`${el}px`},title:`${cu} ${Su.status} ${Nu(Su.startedAt||Su.startMs)} -> ${Nu(Su.finishedAt||Su.endMs)}`,onClick:()=>j(Su),"data-testid":"pipeline-gantt-line","data-node-id":cu,"data-procedure-run-id":String(Su.procedureRunId||""),"data-status":String(Su.status||""),"data-live":Su.live?"true":"false","data-start-ms":String(Su.startMs||""),"data-end-ms":String(Su.endMs||""),"data-y1":String(ll),"data-y2":String(rl),"data-natural-height":String(Math.max(0,rl-ll))},G("strong",null,Su.status||"working"),G("span",null,Hr(Su.durationMs)))}),Jl.map((Su)=>G("button",{key:Su.id,type:"button",className:`pipeline-gantt-marker ${Su.kind} ${Su.tone||""} ${Su.status||""} ${bu===String(Su.id)?"selected":""}`,style:{top:`${Jr(Su,I,g,T)}px`},title:`${Su.label||"event"} / ${Nu(Su.timestampIso||Su.timestamp||Su.ms)}`,onClick:()=>F(Su),"data-testid":Su.kind==="prompt"?"pipeline-gantt-prompt-marker":"pipeline-gantt-control-marker","data-marker-id":String(Su.id||""),"data-ms":String(Su.ms??Su.eventMs??""),"data-y":String(Jr(Su,I,g,T))})))})))),D?G(KY,{selection:U,runDetails:i,nodeDetails:y,nodeDetailsState:_,onRaw:w,onCollapse:()=>h(!1)}):null)))}function x0(){return{loading:!1,actionLoading:"",error:"",message:"",details:null,fetchedAt:null,appendPrompt:"",guidePrompt:"",modifyPrompt:"",approveReason:"",redoReason:""}}function Cn(){return{mode:"",runId:"",interval:null,marker:null}}function G9(){return{runId:"",loading:!1,error:"",details:null,fetchedAt:null}}function H$(u,f){return`${u}/microservices/pipeline/proxy${f}`}function GS({activeRun:u,pipelineRuns:f,selectedRunId:l,onRunChange:r,selectedNodeId:n,selectedNodeConfig:i,selectedNodeRuntime:y,control:_,onControlChange:$,onFetch:A,onAction:c,onRaw:j,onCollapse:F}){let U=String(u?.runId||""),Q=String(y?.status||"pending"),L=!U||!n||_.loading||Boolean(_.actionLoading),w=(N)=>(q)=>$({[N]:q.target.value,error:"",message:""}),J=f.length>0?f:u?[u]:[];return G("aside",{className:"pipeline-node-control","data-testid":"pipeline-node-control"},G("div",{className:"pipeline-node-control-head"},G("div",null,G("p",{className:"panel-eyebrow"},"Manual Node Control"),G(nf,{title:n||"点击控制图中的 node",level:3,loading:_.loading||Boolean(_.actionLoading)})),G("div",{className:"pipeline-node-control-head-actions"},n?G(hn,{status:Q},Q):G(hn,{status:"pending"},"idle"),G("button",{type:"button",className:"ghost-btn mini",onClick:F,"data-testid":"pipeline-node-sidebar-collapse"},"收起"))),G("div",{className:"pipeline-control-runbar"},G("label",null,G("span",null,"目标 run"),G("select",{value:U||l,disabled:J.length===0,onChange:(N)=>r(N.target.value),"data-testid":"pipeline-node-run-select"},J.map((N)=>G("option",{key:N.runId,value:N.runId},`${N.runId||"--"} / ${N.status||"--"}`)))),G("button",{type:"button",className:"ghost-btn",disabled:L,onClick:A,"data-testid":"pipeline-node-fetch"},_.loading?"抓取中":"抓取过程"),_.details?G(gr,{title:`Pipeline Node ${n}`,data:_.details,onOpen:j,testId:"raw-pipeline-node-control"}):null),G("div",{className:"pipeline-control-meta"},G("span",null,G("b",null,"kind"),String(i?.kind||"--")),G("span",null,G("b",null,"procedure"),String(y?.currentProcedureRunId||"--")),G("span",null,G("b",null,"attempts"),String(y?.attempts??"--")),G("span",null,G("b",null,"updated"),Nu(u?.updatedAt))),!n?G(Ur,{title:"未选择 node",text:"点击 React Flow 控制图中的任意 node 后,可抓取执行过程、追加 prompt、下发引导、增量修改、审核通过或重做。"}):null,G(yf,{error:_.error,wide:!0}),G("div",{className:"pipeline-control-actions"},G("label",null,G("span",null,"实时追加 prompt(仅 running node)"),G("textarea",{value:_.appendPrompt,onChange:w("appendPrompt"),placeholder:"让当前执行中的 agent 继续、补充检查或调整当前步骤...",rows:4,disabled:!n,"data-testid":"pipeline-node-append-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:L||!String(_.appendPrompt||"").trim(),onClick:()=>c("append"),"data-testid":"pipeline-node-append-button"},_.actionLoading==="append"?"追加中":"追加到运行中 node")),G("label",null,G("span",null,"下次尝试引导 prompt"),G("textarea",{value:_.guidePrompt,onChange:w("guidePrompt"),placeholder:"给该 node 下一次 attempt 的执行提示;不会立即打断当前 session。",rows:4,disabled:!n,"data-testid":"pipeline-node-guide-input"}),G("button",{type:"button",className:"ghost-btn compact",disabled:L||!String(_.guidePrompt||"").trim(),onClick:()=>c("guide"),"data-testid":"pipeline-node-guide-button"},_.actionLoading==="guide"?"下发中":"下发 guide")),G("label",null,G("span",null,"完成后增量修改 prompt"),G("textarea",{value:_.modifyPrompt,onChange:w("modifyPrompt"),placeholder:"在该 node 已完成结果基础上追加修改要求;runner 会重跑目标 node,并保留同 node 既有 OA 输出作为上下文。",rows:4,disabled:!n,"data-testid":"pipeline-node-modify-input"}),G("button",{type:"button",className:"ghost-btn compact",disabled:L||!String(_.modifyPrompt||"").trim(),onClick:()=>c("modify"),"data-testid":"pipeline-node-modify-button"},_.actionLoading==="modify"?"排队中":"增量修改 node")),G("label",null,G("span",null,"Monitor 审核通过原因"),G("textarea",{value:_.approveReason,onChange:w("approveReason"),placeholder:"当流程配置开启 monitor 审核时,记录审核通过原因并释放后续 node。",rows:3,disabled:!n,"data-testid":"pipeline-node-approve-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:L||!String(_.approveReason||"").trim(),onClick:()=>c("approve"),"data-testid":"pipeline-node-approve-button"},_.actionLoading==="approve"?"提交中":"审核通过")),G("label",null,G("span",null,"重做 / restart 原因"),G("textarea",{value:_.redoReason,onChange:w("redoReason"),placeholder:"说明为什么需要重做;runner 会重置目标 node 以及非 rework 下游 node。",rows:4,disabled:!n,"data-testid":"pipeline-node-redo-input"}),G("button",{type:"button",className:"danger-btn compact",disabled:L||!String(_.redoReason||"").trim(),onClick:()=>c("redo"),"data-testid":"pipeline-node-redo-button"},_.actionLoading==="redo"?"排队中":"重做 node"))),G("div",{className:"pipeline-control-evidence"},G("strong",null,"Node 过程索引"),G(NS,{details:_.details,selectedNodeId:n,selectedNodeRuntime:y,control:_,onRaw:j})))}function SL({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((lu)=>lu.id==="pipeline")||null,[n,i]=sl({loading:!1,error:"",health:null,snapshot:null,oaDiagnostics:null,minimaxQuota:null,refreshedAt:null}),[y,_]=sl(""),[$,A]=sl(""),[c,j]=sl(""),[F,U]=sl(x0()),[Q,L]=sl({}),[w,J]=sl(Cn()),[N,q]=sl(G9()),[W,z]=sl(p$),[Z,H]=sl(!1),[E,D]=sl(!1),h=Rn(0),{addNotification:V}=Dl(),Y=Rn(!1),p=Rn(0),O=Rn(""),m=Rn({}),X=Rn(""),v=Rn("");async function T(lu={}){let Hu=lu.silent===!0;if(!r)return;if(Y.current)return;Y.current=!0;let Yu=h.current+1;if(h.current=Yu,!Hu)i((gu)=>({...gu,loading:!0,error:""}));try{let gu=`__unideskArrayLimit=registry.components:80,runs:${iY}`,[_f,Pf,rf]=await Promise.all([Mn(`${l}/microservices/pipeline/proxy/api/snapshot?${gu}`,{cache:"no-store"}),Mn(`${l}/microservices/pipeline/proxy/api/oa-event-flow/diagnostics`,{cache:"no-store"}).catch((Dr)=>({ok:!1,error:Zu(Dr,"OA event flow diagnostics failed")})),Mn(`${l}/microservices/pipeline/proxy/api/model-quota/minimax`,{cache:"no-store"}).catch((Dr)=>({ok:!1,error:Zu(Dr,"MiniMax quota failed")}))]);if(Yu!==h.current)return;let Ul={ok:_f?.ok!==!1,service:"pipeline-v2-control snapshot"};i({loading:!1,error:"",health:Ul,snapshot:_f,oaDiagnostics:Pf,minimaxQuota:rf,refreshedAt:new Date})}catch(gu){if(Yu!==h.current)return;i((_f)=>({..._f,loading:!1,error:Zu(gu,"Pipeline 加载失败")}))}finally{Y.current=!1}}F0(()=>{if(T(),!r)return;let lu=()=>{if($8())T({silent:!0})},Hu=window.setInterval(()=>{lu()},IW),Yu=()=>{if($8())lu()};return document.addEventListener("visibilitychange",Yu),()=>{window.clearInterval(Hu),document.removeEventListener("visibilitychange",Yu)}},[r?.id,r?.runtime?.providerStatus,l]);let S=zY(r),k=EY(r),I=TY(r),b=n.snapshot||{},o=n.oaDiagnostics||null,g=n.minimaxQuota||null,{components:x,pipelines:fu,runs:$u}=ZY(b),tu=String($u[0]?.pipelineId||""),ju=(tu?fu.find((lu)=>String(lu.id||"")===tu):null)||fu[0]||{},Gu=fu.find((lu)=>String(lu.id||"")===y)||ju,qu=String(Gu.id||""),P=KL(Gu),e=p9(Gu),uu=tL($u,qu),wu=oY($u,qu),s=wu.find((lu)=>String(lu?.runId||"")===$)||uu,Qu=String(N.runId||"")===String(s?.runId||"")?VY(N.details):null,zu=DY(s,Qu),Ou=String(zu?.runId||""),bu=P.find((lu)=>String(lu?.id||"")===c)||null,eu=c?GL(zu,c):null,pu=HY($u),Ff=pY(x),Fl=Number(n.health?.components)||lL(b,"registry.components",x.length),Tl=lL(b,"runs",$u.length),fl=iL(Gu,zu,x),of={nodes:fl.nodes.map((lu)=>lu.id===c?{...lu,selected:!0,className:`${lu.className||""} selected-control-node`}:lu),edges:fl.edges},El=fu.map((lu)=>{let Hu=String(lu.id||"pipeline"),Yu=tL($u,Hu);return{title:`${Hu}-${Yu?.runId||"snapshot"}`,flow:iL(lu,Yu,x)}}),pl=String(w?.runId||Ou||""),cu=String(w?.interval?.nodeId||w?.marker?.nodeId||""),Iu=pl&&cu?Q[w9(pl,cu)]||null:null,Jl=U8(F.details,pl,cu),Su=U8(Iu?.details,pl,cu)||Jl,ll=pl&&cu?{...Du(Iu)?Iu:{},runId:pl,nodeId:cu,details:Su,loading:Boolean(Iu?.loading)||!Su&&Boolean(F.loading)&&c===cu,error:String(Iu?.error||""),fetchedAt:Iu?.fetchedAt||(Jl?F.fetchedAt:null)}:null,rl=wu.map((lu)=>String(lu?.runId||"")).filter(Boolean).join("|"),el=P.map((lu)=>String(lu?.id||"")).filter(Boolean).join("|");F0(()=>{X.current=c},[c]),F0(()=>{v.current=Ou},[Ou]),F0(()=>{if(!$||rl.split("|").includes($))return;A("")},[$,rl]),F0(()=>{if(!c||el.split("|").includes(c))return;j(""),U(x0()),J(Cn()),H(!1),D(!1)},[c,el]),F0(()=>{if(!c)H(!1)},[c]),F0(()=>{if(!w.mode)D(!1)},[w.mode]);async function nl(lu=Ou,Hu={}){if(!lu){q(G9());return}let Yu=bn(Hu.scale??W??p$),gu=`${lu}:timeline`;if(O.current===gu)return;O.current=gu;let _f=Hu.silent===!0,Pf=p.current+1;p.current=Pf,q((rf)=>({runId:lu,scale:Yu,loading:!_f||String(rf.runId||"")!==lu||!rf.details,error:"",details:_f&&rf.runId===lu?rf.details:rf.runId===lu?rf.details:null,fetchedAt:rf.runId===lu?rf.fetchedAt:null}));try{let[rf,Ul]=await Promise.all([Mn(H$(l,`/api/node-control/runs/${encodeURIComponent(lu)}?tail=160&view=timeline`),{cache:"no-store",strictJson:!0}),Mn(H$(l,`/api/runs/${encodeURIComponent(lu)}`),{cache:"no-store"}).catch((Dr)=>({ok:!1,runSummaryError:Zu(Dr,"抓取评分失败")}))]);if(Pf!==p.current)return;q({runId:lu,scale:Yu,loading:!1,error:"",details:{...rf,run:Du(Ul?.run)?Ul.run:void 0,runSummaryError:Ul?.runSummaryError},fetchedAt:new Date})}catch(rf){if(Pf!==p.current)return;q((Ul)=>({runId:lu,scale:Yu,loading:!1,error:Zu(rf,"抓取 epoch 执行过程失败"),details:Ul.runId===lu?Ul.details:null,fetchedAt:Ul.runId===lu?Ul.fetchedAt:null}))}finally{if(O.current===gu)O.current=""}}function Zl(lu,Hu,Yu){let gu=w9(lu,Hu);L((_f)=>{let Pf={..._f,[gu]:{...Du(_f?.[gu])?_f[gu]:{},runId:lu,nodeId:Hu,...Yu}},rf=Object.keys(Pf);if(rf.length>32)for(let Ul of rf.slice(0,rf.length-32))delete Pf[Ul];return Pf})}async function Q0(lu,Hu){if(!lu||!Hu)return;let Yu=w9(lu,Hu),gu=Number(m.current?.[Yu]||0)+1;m.current={...m.current,[Yu]:gu},Zl(lu,Hu,{loading:!0,error:""});try{let _f=await Mn(H$(l,`/api/node-control/runs/${encodeURIComponent(lu)}/nodes/${encodeURIComponent(Hu)}?tail=160`),{cache:"no-store",strictJson:!0});if(Number(m.current?.[Yu]||0)!==gu)return;let Pf=new Date;if(Zl(lu,Hu,{loading:!1,details:_f,fetchedAt:Pf,error:""}),X.current===Hu&&v.current===lu)U((rf)=>({...rf,loading:!1,details:_f,fetchedAt:Pf,error:""}))}catch(_f){if(Number(m.current?.[Yu]||0)!==gu)return;Zl(lu,Hu,{loading:!1,error:Zu(_f,"抓取 Gantt node 详情失败")})}}F0(()=>{if(!Ou){q(G9());return}nl(Ou);let lu=()=>{if($8())nl(Ou,{silent:!0})},Hu=window.setInterval(()=>{lu()},IW),Yu=()=>{if($8())lu()};return document.addEventListener("visibilitychange",Yu),()=>{window.clearInterval(Hu),document.removeEventListener("visibilitychange",Yu)}},[Ou,l]);async function ur(lu=Ou,Hu=c){if(!lu||!Hu){U((Yu)=>({...Yu,error:"请先选择 run 和 node",message:""}));return}U((Yu)=>({...Yu,loading:!0,error:"",message:""}));try{let Yu=await Mn(H$(l,`/api/node-control/runs/${encodeURIComponent(lu)}/nodes/${encodeURIComponent(Hu)}?tail=160`),{cache:"no-store",strictJson:!0}),gu=new Date;U((_f)=>({..._f,loading:!1,details:Yu,fetchedAt:gu,error:""})),Zl(lu,Hu,{loading:!1,details:Yu,fetchedAt:gu,error:""})}catch(Yu){U((gu)=>({...gu,loading:!1,error:Zu(Yu,"抓取 node 执行过程失败")}))}}async function v0(lu){let Hu=String(lu?.runId||Ou||""),Yu=String(lu?.nodeId||"");if(J({mode:"interval",runId:Hu,interval:lu,marker:null}),D(!0),!Hu||!Yu)return;if(Hu!==Ou)A(Hu);j(Yu),U(x0()),nl(Hu,{silent:!0}),Q0(Hu,Yu)}async function Jf(lu){let Hu=String(lu?.runId||Ou||""),Yu=String(lu?.nodeId||"");if(J({mode:"event",runId:Hu,interval:null,marker:lu}),D(!0),!Hu)return;if(Hu!==Ou)A(Hu);if(nl(Hu,{silent:!0}),!Yu)return;j(Yu),U(x0()),Q0(Hu,Yu)}async function h1(lu){if(!Ou||!c){U((gu)=>({...gu,error:"请先选择 run 和 node",message:""}));return}let Hu=lu==="append"?"prompts":lu,Yu=lu==="append"?F.appendPrompt:lu==="guide"?F.guidePrompt:lu==="modify"?F.modifyPrompt:lu==="approve"?F.approveReason:F.redoReason;if(!String(Yu||"").trim()){U((gu)=>({...gu,error:"操作内容不能为空",message:""}));return}U((gu)=>({...gu,actionLoading:lu,error:"",message:""}));try{let gu=lu==="redo"||lu==="approve"?{reason:Yu,source:"unidesk-frontend",sourceKind:"webui"}:{prompt:Yu,source:"unidesk-frontend",sourceKind:"webui"},_f=await Mn(H$(l,`/api/node-control/runs/${encodeURIComponent(Ou)}/nodes/${encodeURIComponent(c)}/${Hu}`),{method:"POST",body:JSON.stringify(gu)});if(U((rf)=>({...rf,actionLoading:"",details:_f,fetchedAt:new Date,appendPrompt:lu==="append"?"":rf.appendPrompt,guidePrompt:lu==="guide"?"":rf.guidePrompt,modifyPrompt:lu==="modify"?"":rf.modifyPrompt,approveReason:lu==="approve"?"":rf.approveReason,redoReason:lu==="redo"?"":rf.redoReason,message:lu==="append"?"已追加到运行中 node":lu==="guide"?"已下发 guide,等待 runner 处理":lu==="modify"?"已排队增量修改命令":lu==="approve"?"已提交审核通过决策":"已排队重做命令"})),V("success",lu==="append"?"已追加到运行中 node":lu==="guide"?"已下发 guide,等待 runner 处理":lu==="modify"?"已排队增量修改命令":lu==="approve"?"已提交审核通过决策":"已排队重做命令"),await ur(Ou,c),await nl(Ou,{silent:!0}),lu!=="append")await T()}catch(gu){U((_f)=>({..._f,actionLoading:"",error:Zu(gu,"node 控制操作失败")}))}}if(!r)return G(Ur,{title:"Pipeline 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=pipeline"});return G("div",{className:"pipeline-page","data-testid":"pipeline-page"},G(j0,{title:"Pipeline v2 工作台",eyebrow:"D601 Snapshot 用户服务",loading:n.loading,actions:G("div",{className:"panel-actions"},G("button",{type:"button",className:"ghost-btn",onClick:T,disabled:n.loading,"data-testid":"pipeline-refresh-button"},n.loading?"刷新中":"刷新"),G(gr,{title:"Pipeline 用户服务",data:r,onOpen:f,testId:"raw-pipeline-service"}))},G("div",{className:"pipeline-hero"},G("div",null,G("div",{className:"node-version-line"},G(hn,{status:S.providerStatus==="online"?"online":"warn"},S.providerStatus||"unknown"),G("span",null,r.providerId),G("span",null,I.public?"公网暴露":"仅 UniDesk frontend 代理访问")),G("p",{className:"muted paragraph"},r.description)),G("div",{className:"microservice-ref-card"},G("span",null,"Repo"),G("strong",null,k.url||"--"),G("code",null,k.commitId||"--")),G("div",{className:"microservice-ref-card"},G("span",null,"D601 Docker"),G("strong",null,`${I.nodeBindHost||"--"}:${I.nodePort||"--"}`),G("code",null,`${k.composeFile||"--"} / ${k.composeService||"--"}`))),G(yf,{error:n.error,wide:!0})),G("div",{className:"pipeline-grid"},G(j0,{title:"控制图",eyebrow:`${Gu.id||"pipeline"} / run ${zu?.status||"--"}`,className:"pipeline-wide-panel",loading:n.loading,actions:G("div",{className:"pipeline-toolbar"},G("select",{value:qu,disabled:fu.length===0,onChange:(lu)=>{_(lu.target.value),A(""),j(""),U(x0()),J(Cn()),H(!1),D(!1)},"data-testid":"pipeline-select"},fu.map((lu)=>G("option",{key:lu.id,value:lu.id},lu.id||lu.key))),G("select",{value:Ou,disabled:wu.length===0,onChange:(lu)=>{if(A(lu.target.value),U(x0()),J(Cn()),H(!1),D(!1),c)ur(lu.target.value,c)},"data-testid":"pipeline-run-select"},wu.map((lu)=>G("option",{key:lu.runId,value:lu.runId},H9(wu,lu)))),G("button",{type:"button",className:"ghost-btn",disabled:of.nodes.length===0,onClick:()=>EL(of,`${Gu.id||"pipeline"}-${zu?.runId||"snapshot"}`),"data-testid":"pipeline-export-graph"},"导出渲染图"),G("button",{type:"button",className:"ghost-btn",disabled:El.every((lu)=>lu.flow.nodes.length===0),onClick:()=>aY(El),"data-testid":"pipeline-export-all-graphs"},"批量导出"))},P.length===0?G(Ur,{title:"暂无控制图",text:"等待 D601 pipeline backend 返回 config.nodes / config.edges"}):G("div",{className:`pipeline-control-shell ${Z?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-control-shell","data-sidebar-open":Z?"true":"false"},G("div",{className:"pipeline-flow-frame","data-testid":"pipeline-react-flow"},G(CW,{nodes:of.nodes,edges:of.edges,nodeTypes:AY,edgeTypes:tY,fitView:!0,fitViewOptions:{padding:0.18},nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,minZoom:0.25,maxZoom:1.4,proOptions:{hideAttribution:!0},onNodeClick:(lu,Hu)=>{let Yu=String(Hu.id);if(j(Yu),U(x0()),H(!0),Ou)ur(Ou,Yu)}},G(xW,{gap:22,size:1,color:"rgba(215, 161, 58, 0.24)"}),G(bW,{showInteractive:!1})),!Z?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!c,onClick:()=>H(!0),"data-testid":"pipeline-node-sidebar-toggle"},c?"展开 node 控制":"点击 node 展开控制"):null),Z?G(GS,{activeRun:zu,pipelineRuns:wu,selectedRunId:$,onRunChange:(lu)=>{if(A(lu),U(x0()),J(Cn()),c)ur(lu,c)},selectedNodeId:c,selectedNodeConfig:bu,selectedNodeRuntime:eu,control:F,onControlChange:(lu)=>U((Hu)=>({...Hu,...lu})),onFetch:()=>ur(),onAction:h1,onRaw:f,onCollapse:()=>H(!1)}):null),G("div",{className:"pipeline-flow-summary"},G("span",null,`${of.nodes.length} nodes`),G("span",null,`${of.edges.length} edges`),G("span",null,`${fu.length} pipelines`),G("span",null,`source config+components(${x.length})`),G("span",null,`run ${zu?.runId||"--"}`),G("span",null,`score ${O9(zu)}`),G("span",null,c?`selected ${c}`:"click node to control"))),G(KS,{epochs:wu,activeRun:zu,activePipeline:Gu,pipelineNodes:P,pipelineEdges:e,selection:w,detailOpen:E,onDetailOpenChange:D,runDetails:N,nodeDetails:Su,nodeDetailsState:ll,ganttScale:W,onGanttScaleChange:z,onIntervalSelect:v0,onMarkerSelect:Jf,onRunChange:(lu)=>{if(A(lu),U(x0()),J(Cn()),D(!1),c)ur(lu,c)},onRaw:f}),G(j0,{title:"观测指标",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Snapshot",loading:n.loading},G("div",{className:"metric-grid"},G(Sl,{label:"Health",value:n.health?.ok?"OK":"--",hint:n.health?.service||"D601 /health",tone:n.health?.ok?"ok":"warn"}),G(Sl,{label:"组件",value:Fl,hint:"components registry",tone:b?.registry?.ok===!1?"warn":"ok"}),G(Sl,{label:"Pipeline",value:fu.length,hint:`${P.length} nodes / ${e.length} edges`}),G(Sl,{label:"运行记录",value:Tl,hint:`${pu.succeeded||0} succeeded / ${pu.running||0} running`}),G(Sl,{label:"OA 记录",value:Array.isArray(uu?.submissions)?uu.submissions.length:0,hint:uu?.runId||"latest run"}),G(Sl,{label:"Procedure",value:Array.isArray(uu?.procedureRuns)?uu.procedureRuns.length:0,hint:uu?.status||"no run"}),G(Sl,{label:"Score",value:O9(zu),hint:zu?.runId||"selected epoch",tone:P9(zu)})),G("div",{className:"panel-actions inline-actions"},G(gr,{title:"Pipeline Snapshot",data:b,onOpen:f,testId:"raw-pipeline-snapshot"}))),G(j0,{title:"评分器",eyebrow:zu?.runId||"selected epoch",loading:n.loading},G(SY,{run:zu,onRaw:f})),G(j0,{title:"MiniMax 限额",eyebrow:"model/minimax-m27 quota",loading:n.loading},G(wS,{quota:g,onRaw:f})),G(j0,{title:"OA 事件流",eyebrow:"100% event-driven diagnostics",className:"pipeline-wide-panel",loading:n.loading},G(LS,{diagnostics:o,onRaw:f})),G(j0,{title:"组件矩阵",eyebrow:`${Ff.length} classes`,loading:n.loading},Ff.length===0?G(Ur,{title:"暂无组件",text:"等待 D601 pipeline backend 返回 registry.components"}):G("div",{className:"component-strata"},Ff.map((lu)=>G("article",{key:lu.name,className:"component-stratum"},G("span",null,lu.name),G("strong",null,lu.count)))),G("div",{className:"pipeline-component-list"},x.slice(0,12).map((lu)=>G("span",{key:lu.key,className:"data-chip"},G("b",null,lu.componentClass||"--"),G("span",null,lu.id||lu.key||"--"))))),G(j0,{title:"Epoch 列表",eyebrow:`${wu.length}/${Tl} preview`,loading:n.loading},wu.length===0?G(Ur,{title:"暂无运行记录",text:"当前 pipeline 在 .state/pipeline-runs 中还没有 epoch。"}):G("div",{className:"pipeline-run-list"},wu.map((lu)=>{let Hu=String(lu?.runId||"")===Ou?zu:lu;return G("article",{key:lu.runId,className:`pipeline-run-card ${String(lu.runId||"")===Ou?"active":""}`,role:"button",tabIndex:0,onClick:()=>{A(String(lu.runId||"")),J(Cn())},onKeyDown:(Yu)=>{if(Yu.key==="Enter"||Yu.key===" ")A(String(lu.runId||"")),J(Cn())}},G("div",{className:"node-card-head"},G("strong",null,H9(wu,lu)),G(hn,{status:lu.status},lu.status||"--")),G("div",{className:"docker-meta compact"},G("span",null,Hu?.pipelineId||"--"),G("span",null,`nodes ${Array.isArray(Hu?.nodes)?Hu.nodes.length:0}`),G("span",null,`oa ${Array.isArray(Hu?.submissions)?Hu.submissions.length:0}`),G("span",null,`procedures ${Array.isArray(Hu?.procedureRuns)?Hu.procedureRuns.length:0}`),G(YY,{run:Hu})),G("p",{className:"muted paragraph"},J8(Hu?.task)),G("span",{className:"pipeline-run-time"},Nu(Hu?.updatedAt)))}))),G(j0,{title:"运行材料索引",eyebrow:zu?.runId||"selected epoch",className:"pipeline-wide-panel",loading:n.loading},G(WS,{activeRun:zu,onRaw:f}))))}var E8=Pu(Qf(),1);var _u=E8.default.createElement,{useEffect:zS}=E8.default,z8=E8.default.useState,x9={id:"",sequenceNo:"",contractNo:"",name:"",currentStatus:"",pending:"",paymentStatus:"",notes:""};function TS({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return _u("span",{className:`status-badge ${l}`},f||u||"unknown")}function T8({label:u,value:f,hint:l,tone:r}){return _u("article",{className:`metric-card ${r||""}`},_u("div",{className:"metric-label"},u),_u("div",{className:"metric-value"},f),_u("div",{className:"metric-hint"},l))}function h9({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return _u("section",{className:`panel ${n||""}`},_u("div",{className:"panel-head"},_u("div",null,f?_u("p",{className:"panel-eyebrow"},f):null,_u(nf,{title:u,loading:i})),l?_u("div",{className:"panel-actions"},l):null),_u("div",{className:"panel-body"},r))}function pL({title:u,data:f,onOpen:l,testId:r}){return _u("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function mL({title:u,text:f}){return _u("div",{className:"empty-state"},_u("strong",null,u),_u("span",null,f))}function ES(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function ZS(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function OS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Qy(u,f){return`${u}/microservices/project-manager/proxy${f}`}function HS(u){return{id:String(u.id||""),sequenceNo:u.sequenceNo===null||u.sequenceNo===void 0?"":String(u.sequenceNo),contractNo:String(u.contractNo||""),name:String(u.name||""),currentStatus:String(u.currentStatus||""),pending:String(u.pending||""),paymentStatus:String(u.paymentStatus||""),notes:String(u.notes||"")}}function BS(u){return{sequenceNo:u.sequenceNo===""?null:Number(u.sequenceNo),contractNo:String(u.contractNo||"").trim(),name:String(u.name||"").trim(),currentStatus:String(u.currentStatus||"").trim(),pending:String(u.pending||"").trim(),paymentStatus:String(u.paymentStatus||"").trim(),paymentRatio:String(u.paymentStatus||"").trim(),notes:String(u.notes||"").trim()}}function b9(u){return String(u||"item").replace(/[^A-Za-z0-9_-]+/g,"-")}function VS(u){let f=new Uint8Array(u),l="",r=32768;for(let n=0;n_u("tr",{key:n.id,className:f===n.id?"active-row":"","data-testid":`project-manager-row-${b9(n.id)}`},_u("td",null,n.sequenceNo??"--"),_u("td",null,_u("strong",null,n.contractNo||"--"),_u("code",null,n.id||"--")),_u("td",null,_u("strong",null,n.name||"--"),_u("span",{className:"muted block"},n.sourceFile||"--")),_u("td",null,n.currentStatus||"--"),_u("td",null,_u("span",{className:"preline"},n.pending||"--")),_u("td",null,_u(TS,{status:Number(n.paymentRatio||0)>=1?"online":"warn"},n.paymentStatus||"--")),_u("td",null,n.notes||"--"),_u("td",null,_u("div",{className:"inline-actions"},_u("button",{type:"button",className:"ghost-btn",onClick:()=>l(n),"data-testid":`project-manager-edit-${b9(n.id)}`},"编辑"),_u(pL,{title:`Project ${n.contractNo||n.id}`,data:n,onOpen:r,testId:`raw-project-${b9(n.id)}`}))))))))}function PL({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((E)=>E.id==="project-manager")||null,[n,i]=z8({loading:!1,saving:!1,importing:!1,exporting:!1,error:"",notice:"",health:null,list:null,refreshedAt:null}),[y,_]=z8({...x9}),[$,A]=z8(""),[c,j]=z8("all"),{addNotification:F}=Dl();async function U(E=$,D=c){if(!r)return;i((h)=>({...h,loading:!0,error:""}));try{let h=new URLSearchParams({pageSize:"200",status:D});if(E.trim())h.set("q",E.trim());let[V,Y]=await Promise.all([Eu(`${l}/microservices/project-manager/health`),Eu(Qy(l,`/api/projects?${h.toString()}`))]);i((p)=>({...p,loading:!1,health:V,list:Y,refreshedAt:new Date,error:""}))}catch(h){i((V)=>({...V,loading:!1,error:Zu(h,"Project Manager 加载失败")}))}}zS(()=>{U()},[r?.id,r?.runtime?.providerStatus]);async function Q(E){E.preventDefault(),i((D)=>({...D,saving:!0,error:"",notice:""}));try{let D=BS(y);if(y.id)await Eu(Qy(l,`/api/projects/${encodeURIComponent(y.id)}`),{method:"PUT",body:JSON.stringify(D)});else await Eu(Qy(l,"/api/projects"),{method:"POST",body:JSON.stringify(D)});let h=y.id?"项目已更新":"项目已创建";i((V)=>({...V,saving:!1,notice:h})),F("success",h),await U()}catch(D){i((h)=>({...h,saving:!1,error:Zu(D,"保存项目失败")}))}}async function L(){if(!y.id)return;if(!window.confirm(`删除项目 ${y.contractNo||y.name||y.id} ?`))return;i((E)=>({...E,saving:!0,error:"",notice:""}));try{await Eu(Qy(l,`/api/projects/${encodeURIComponent(y.id)}`),{method:"DELETE"}),_({...x9});let E="项目已删除";i((D)=>({...D,saving:!1,notice:E})),F("success",E),await U()}catch(E){i((D)=>({...D,saving:!1,error:Zu(E,"删除项目失败")}))}}async function w(E){let D=E.target.files?.[0];if(!D)return;i((h)=>({...h,importing:!0,error:"",notice:""}));try{let h=VS(await D.arrayBuffer()),Y=`Excel 已导入 ${(await Eu(Qy(l,"/api/import/excel"),{method:"POST",body:JSON.stringify({fileName:D.name,contentBase64:h,replace:!1})})).imported||0} 条项目`;i((p)=>({...p,importing:!1,notice:Y})),F("success",Y),E.target.value="",await U()}catch(h){i((V)=>({...V,importing:!1,error:Zu(h,"Excel 导入失败")}))}}async function J(){i((E)=>({...E,exporting:!0,error:""}));try{let E=await rU(Qy(l,"/api/projects/export.xlsx")),D=URL.createObjectURL(E),h=document.createElement("a");h.href=D,h.download=`project-manager-${S7()}.xlsx`,document.body.appendChild(h),h.click(),h.remove(),URL.revokeObjectURL(D),i((V)=>({...V,exporting:!1,notice:"Excel 已导出"}))}catch(E){i((D)=>({...D,exporting:!1,error:Zu(E,"Excel 导出失败")}))}}if(!r)return _u(mL,{title:"Project Manager 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=project-manager"});let N=ES(r),q=OS(r),W=ZS(r),z=Array.isArray(n.list?.projects)?n.list.projects:[],Z=n.list?.summary||{},H=n.health||{};return _u("div",{className:"project-manager-page","data-testid":"project-manager-page"},_u(h9,{title:"项目管理工作台",eyebrow:"Main Server PostgreSQL 用户服务",loading:n.loading||n.exporting,actions:_u("div",{className:"panel-actions"},_u("button",{type:"button",className:"ghost-btn",disabled:n.loading,onClick:()=>U(),"data-testid":"project-manager-refresh-button"},n.loading?"刷新中":"刷新"),_u("button",{type:"button",className:"ghost-btn",disabled:n.exporting,onClick:J,"data-testid":"project-manager-export-button"},n.exporting?"导出中":"导出 Excel"),_u(pL,{title:"Project Manager 用户服务",data:r,onOpen:f,testId:"raw-project-manager-service"}))},_u("div",{className:"project-manager-hero"},_u(T8,{label:"项目总数",value:Z.total??z.length,hint:`PG 表 ${H.storage?.table||"project_manager_projects"}`,tone:"ok"}),_u(T8,{label:"进行中",value:Z.active??"--",hint:"当前状态未完全完成"}),_u(T8,{label:"已完成",value:Z.completed??"--",hint:"按 完成 关键字统计",tone:"ok"}),_u(T8,{label:"未全款",value:Z.unpaid??"--",hint:"付款比例 < 1",tone:Number(Z.unpaid||0)>0?"warn":"ok"})),_u(yf,{error:n.error}),n.notice?_u("div",{className:"form-success"},n.notice):null),_u("div",{className:"project-manager-hero"},_u("div",{className:"microservice-ref-card"},_u("span",null,"Repo"),_u("strong",null,q.url||"--"),_u("code",null,q.commitId||"--")),_u("div",{className:"microservice-ref-card"},_u("span",null,"Main Server Docker"),_u("strong",null,`${W.nodeBindHost||"--"}:${W.nodePort||"--"}`),_u("code",null,`${q.composeService||"--"} / ${q.containerName||"--"}`)),_u("div",{className:"microservice-ref-card"},_u("span",null,"Runtime"),_u("strong",null,N.providerName||r.providerId),_u("code",null,`Health ${H.ok?"OK":"--"} / ${n.refreshedAt?$f(n.refreshedAt):"--"}`)),_u("div",{className:"microservice-ref-card"},_u("span",null,"Import Source"),_u("strong",null,"D601 WeChat Excel"),_u("code",null,"合作项目列表_I_20260309.xlsx"))),_u("div",{className:"project-manager-layout"},_u(h9,{title:"项目清单",eyebrow:"CRUD + Excel Export",loading:n.loading||n.importing||n.exporting,actions:_u("div",{className:"inline-actions project-manager-filters"},_u("input",{value:$,onChange:(E)=>A(E.target.value),placeholder:"搜索合同号 / 项目名称 / 状态","data-testid":"project-manager-search"}),_u("select",{value:c,onChange:(E)=>{j(E.target.value),U($,E.target.value)},"data-testid":"project-manager-status-filter"},_u("option",{value:"all"},"全部"),_u("option",{value:"active"},"进行中"),_u("option",{value:"completed"},"已完成"),_u("option",{value:"unpaid"},"未全款")),_u("button",{type:"button",className:"ghost-btn",onClick:()=>U($,c)},"筛选"))},_u(DS,{projects:z,activeId:y.id,onSelect:(E)=>_(HS(E)),onRaw:f})),_u(h9,{title:y.id?"编辑项目":"新建项目",eyebrow:"PostgreSQL Write Path",loading:n.saving||n.importing},_u("form",{className:"stack-form project-manager-form",onSubmit:Q,"data-testid":"project-manager-form"},y.id?_u("label",null,"项目 ID",_u("input",{value:y.id,disabled:!0})):null,_u("label",null,"序号",_u("input",{type:"number",value:y.sequenceNo,onChange:(E)=>_((D)=>({...D,sequenceNo:E.target.value}))})),_u("label",null,"合同号",_u("input",{value:y.contractNo,onChange:(E)=>_((D)=>({...D,contractNo:E.target.value})),required:!0})),_u("label",null,"项目名称",_u("input",{value:y.name,onChange:(E)=>_((D)=>({...D,name:E.target.value})),required:!0})),_u("label",null,"当前状况",_u("textarea",{value:y.currentStatus,onChange:(E)=>_((D)=>({...D,currentStatus:E.target.value}))})),_u("label",null,"待完成",_u("textarea",{value:y.pending,onChange:(E)=>_((D)=>({...D,pending:E.target.value}))})),_u("label",null,"付款情况",_u("input",{value:y.paymentStatus,onChange:(E)=>_((D)=>({...D,paymentStatus:E.target.value})),placeholder:"例如 1 / 0.5 / 50%"})),_u("label",null,"其它",_u("input",{value:y.notes,onChange:(E)=>_((D)=>({...D,notes:E.target.value}))})),_u("div",{className:"inline-actions"},_u("button",{type:"submit",className:"primary-btn",disabled:n.saving,"data-testid":"project-manager-save-button"},n.saving?"保存中":y.id?"保存修改":"创建项目"),_u("button",{type:"button",className:"ghost-btn",onClick:()=>_({...x9})},"清空"),y.id?_u("button",{type:"button",className:"danger-btn",disabled:n.saving,onClick:L,"data-testid":"project-manager-delete-button"},"删除"):null)),_u("div",{className:"project-manager-import"},_u("p",{className:"muted paragraph"},"浏览器只访问 UniDesk frontend;后端通过同源用户服务代理写入主 PostgreSQL,不暴露 4233 公网端口。"),_u("label",{className:"file-import"},n.importing?"导入中...":"导入 Excel",_u("input",{type:"file",accept:".xlsx",onChange:w,disabled:n.importing,"data-testid":"project-manager-import-input"}))))))}var H8=Pu(Qf(),1);var Au=H8.default.createElement,{useEffect:XS}=H8.default,ol=H8.default.useState;function YS({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return Au("span",{className:`status-badge ${l}`},f||u||"unknown")}function Z8({label:u,value:f,hint:l,tone:r}){return Au("article",{className:`metric-card ${r||""}`},Au("div",{className:"metric-label"},u),Au("div",{className:"metric-value"},f),Au("div",{className:"metric-hint"},l))}function v9({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Au("section",{className:`panel ${n||""}`},Au("div",{className:"panel-head"},Au("div",null,f?Au("p",{className:"panel-eyebrow"},f):null,Au(nf,{title:u,loading:i})),l?Au("div",{className:"panel-actions"},l):null),Au("div",{className:"panel-body"},r))}function ML({title:u,data:f,onOpen:l,testId:r}){return Au("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function O8({title:u,text:f}){return Au("div",{className:"empty-state"},Au("strong",null,u),Au("span",null,f))}function SS(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function pS(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function mS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function RL(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function PS(u){if(!Number.isFinite(u))return"--";return`${u.toFixed(1)}%`}function qy(u,f){return`${u}/microservices/todo-note/proxy${f}`}function xL(u){return u.reduce((f,l)=>{let r=xL(Array.isArray(l.children)?l.children:[]),n=Boolean(l.completed);return{total:f.total+1+r.total,completed:f.completed+(n?1:0)+r.completed,active:f.active+(n?0:1)+r.active}},{total:0,completed:0,active:0})}function I9(u,f){let l=f==="all"||(f==="completed"?Boolean(u.completed):!u.completed),r=Array.isArray(u.children)?u.children:[];return l||r.some((n)=>I9(n,f))}function CL(u){return Array.isArray(u?.instances)?u.instances:[]}function k9(u,f){for(let l of u){if(l?.id===f)return Array.isArray(l.children)?l.children:[];let r=k9(Array.isArray(l?.children)?l.children:[],f);if(r.length>0)return r}return[]}function hL({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((s)=>s.id==="todo-note")||null,[n,i]=ol(null),[y,_]=ol(null),[$,A]=ol(""),[c,j]=ol(null),[F,U]=ol("all"),[Q,L]=ol(13),[w,J]=ol(""),[N,q]=ol(""),[W,z]=ol(""),[Z,H]=ol(""),[E,D]=ol(""),[h,V]=ol(!1),[Y,p]=ol(""),[O,m]=ol(null),X=CL(y),v=xL(Array.isArray(c?.todos)?c.todos:[]),T=r?SS(r):{},S=r?mS(r):{},k=r?pS(r):{};async function I(s=$){let[Qu,zu]=await Promise.all([Eu(`${l}/microservices/todo-note/health`),Eu(qy(l,"/api/instances"))]);i(Qu),_(zu);let Ou=CL(zu),bu=Ou.some((eu)=>eu.id===s)?s:Ou[0]?.id||"";return A(bu),bu}async function b(s=$){if(!s){j(null);return}let Qu=await Eu(qy(l,`/api/instances/${encodeURIComponent(s)}`));j(Qu)}async function o(s=$){if(!r)return;V(!0),p("");try{let Qu=await I(s);await b(Qu),m(new Date)}catch(Qu){p(Zu(Qu,"Todo Note 加载失败"))}finally{V(!1)}}async function g(s){if(!$)return null;p("");try{let Qu=await Eu(qy(l,`/api/instances/${encodeURIComponent($)}/actions`),{method:"POST",body:JSON.stringify({action:s})});return j(Qu),await I($),Qu}catch(Qu){return p(Zu(Qu,"Todo 操作失败")),null}}async function x(s){s.preventDefault();let Qu=w.trim();if(!Qu)return;V(!0),p("");try{let zu=await Eu(qy(l,"/api/instances"),{method:"POST",body:JSON.stringify({name:Qu})});J(""),await o(zu.id)}catch(zu){p(Zu(zu,"创建清单失败"))}finally{V(!1)}}async function fu(s){if(!window.confirm("确认删除这个 Todo Note 清单?"))return;V(!0),p("");try{await Eu(qy(l,`/api/instances/${encodeURIComponent(s)}`),{method:"DELETE"}),await o($===s?"":$)}catch(Qu){p(Zu(Qu,"删除清单失败"))}finally{V(!1)}}async function $u(s){s.preventDefault();let Qu=N.trim();if(!Qu)return;q(""),await g({type:"addTodo",title:Qu})}async function tu(s){if(!$)return;p("");try{let Qu=await Eu(qy(l,`/api/instances/${encodeURIComponent($)}/${s}`),{method:"POST",body:JSON.stringify({})});j(Qu),await I($)}catch(Qu){p(Zu(Qu,`${s} 失败`))}}function ju(s){z(s.id),H(String(s.title||""))}async function Gu(s){let Qu=Z.trim();if(z(""),H(""),Qu)await g({type:"updateTodoTitle",todoId:s,title:Qu})}async function qu(s){let zu=window.prompt("新增子任务标题")?.trim();if(!zu)return;let Ou=k9(Array.isArray(c?.todos)?c.todos:[],s),bu=new Set(Ou.map((Fl)=>Fl.id)),eu=await g({type:"addTodo",title:zu,parentId:s,targetIndex:0});if(!eu)return;let pu=k9(Array.isArray(eu?.todos)?eu.todos:[],s),Ff=pu.find((Fl)=>!bu.has(Fl.id));if(Ff&&pu[0]?.id!==Ff.id)await g({type:"moveTodo",todoId:Ff.id,targetParentId:s,targetIndex:0})}async function P(s,Qu){if(!E)return;let zu={type:"moveTodo",todoId:E,targetIndex:Qu};if(s)zu.targetParentId=s;D(""),await g(zu)}if(XS(()=>{o()},[r?.id,r?.runtime?.providerStatus]),!r)return Au(O8,{title:"Todo Note 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=todo-note"});let e=X.find((s)=>s.id===$)||null,uu=Array.isArray(c?.todos)?c.todos:[],wu=uu.map((s,Qu)=>({todo:s,index:Qu})).filter((s)=>I9(s.todo,F));return Au("div",{className:"todo-note-page","data-testid":"todo-note-page"},Au(v9,{title:"Todo Note 工作台",eyebrow:"Main Server 用户服务",loading:h,actions:Au("div",{className:"panel-actions"},Au("button",{type:"button",className:"ghost-btn",disabled:h,onClick:()=>o($),"data-testid":"todo-note-refresh-button"},h?"刷新中":"刷新"),Au(ML,{title:"Todo Note 用户服务",data:r,onOpen:f,testId:"raw-todo-note-service"}))},Au("div",{className:"todo-note-hero"},Au("div",null,Au("div",{className:"node-version-line"},Au(YS,{status:T.providerStatus==="online"?"online":"warn"},T.providerStatus||"unknown"),Au("span",null,r.providerId),Au("span",null,k.public?"公网暴露":"仅 UniDesk frontend 代理访问"),Au("span",null,n?.ok?"Health OK":"Health --")),Au("p",{className:"muted paragraph"},r.description)),Au("div",{className:"microservice-ref-card"},Au("span",null,"Repo"),Au("strong",null,S.url||"--"),Au("code",null,S.commitId||"--")),Au("div",{className:"microservice-ref-card"},Au("span",null,"Main Server Docker"),Au("strong",null,`${k.nodeBindHost||"--"}:${k.nodePort||"--"}`),Au("code",null,`${S.composeService||"--"} / ${S.containerName||"--"}`))),Au(yf,{error:Y,wide:!0})),Au("div",{className:"todo-note-layout"},Au(v9,{title:"清单",eyebrow:`${X.length} Instances`,className:"todo-list-panel",loading:h},Au("form",{className:"todo-create-list",onSubmit:x},Au("input",{placeholder:"新清单名称",value:w,onChange:(s)=>J(s.target.value),"aria-label":"新清单名称"}),Au("button",{type:"submit",className:"ghost-btn",disabled:h||!w.trim()},"创建")),X.length===0?Au(O8,{title:"暂无清单",text:"迁移或创建清单后会出现在这里"}):Au("div",{className:"todo-instance-list"},X.map((s)=>Au("button",{key:s.id,type:"button",className:`todo-instance-row ${$===s.id?"active":""}`,onClick:()=>{A(s.id),b(s.id)},"data-testid":`todo-instance-${RL(s.id)}`},Au("strong",null,s.name),Au("span",null,`${s.completedCount??0}/${s.todoCount??0} 完成`),Au("code",null,s.id))))),Au("div",{className:"todo-main-stack"},Au(v9,{title:e?.name||"待选择清单",eyebrow:O?`Updated ${$f(O)}`:"Todo Tree",loading:h,actions:c?Au("div",{className:"panel-actions"},Au("button",{type:"button",className:"ghost-btn",onClick:()=>g({type:"renameInstance",name:window.prompt("清单新名称",c.name)||c.name})},"重命名"),Au("button",{type:"button",className:"ghost-btn danger",onClick:()=>fu($)},"删除清单"),Au(ML,{title:`Todo Instance ${$}`,data:c,onOpen:f,testId:"raw-todo-instance"})):null},!c?Au(O8,{title:"未选择清单",text:"左侧选择一个 Todo Note 清单"}):Au("div",{className:"todo-workbench",style:{"--todo-font-size":`${Q}px`}},Au("div",{className:"todo-toolbar"},Au("form",{className:"todo-add-form",onSubmit:$u},Au("input",{placeholder:"新增根任务",value:N,onChange:(s)=>q(s.target.value),"aria-label":"新增根任务"}),Au("button",{type:"submit",className:"ghost-btn",disabled:!N.trim()},"新增")),Au("div",{className:"todo-filter-strip"},["all","active","completed"].map((s)=>Au("button",{key:s,type:"button",className:`todo-filter ${F===s?"active":""}`,onClick:()=>U(s)},s==="all"?"全部":s==="active"?"未完成":"已完成"))),Au("div",{className:"todo-toolbar-actions"},Au("button",{type:"button",className:"ghost-btn",onClick:()=>g({type:"setAllTodosExpanded",expanded:!0})},"全部展开"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>g({type:"setAllTodosExpanded",expanded:!1})},"全部收起"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>tu("undo")},"撤销"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>tu("redo")},"重做"),Au("label",{className:"todo-font-control"},"字号",Au("input",{type:"range",min:11,max:18,value:Q,onChange:(s)=>L(Number(s.target.value))})))),Au("div",{className:"todo-stats-grid"},Au(Z8,{label:"总任务",value:v.total,hint:`${X.length} lists`}),Au(Z8,{label:"已完成",value:v.completed,hint:`${PS(v.total?v.completed/v.total*100:0)}`,tone:"ok"}),Au(Z8,{label:"未完成",value:v.active,hint:F==="active"?"当前筛选":"active tasks",tone:v.active>0?"warn":"ok"}),Au(Z8,{label:"历史指针",value:c.historyPointer??0,hint:"undo / redo"})),Au("div",{className:"todo-root-drop",onDragOver:(s)=>s.preventDefault(),onDrop:(s)=>{s.preventDefault(),P(null,uu.length)}},"拖到这里可移为根任务末尾"),Au("div",{className:"todo-tree","data-testid":"todo-note-tree"},wu.length===0?Au(O8,{title:"没有匹配任务",text:"调整筛选或新增任务"}):wu.map(({todo:s,index:Qu})=>Au(bL,{key:s.id,todo:s,depth:0,parentId:null,index:Qu,siblingCount:uu.length,filter:F,editingId:W,editingTitle:Z,setEditingTitle:H,beginEdit:ju,saveEdit:Gu,applyTodoAction:g,addChild:qu,dragTodoId:E,setDragTodoId:D,dropTodo:P}))))))))}function bL(u){let{todo:f,depth:l,parentId:r,index:n,siblingCount:i,filter:y,editingId:_,editingTitle:$,setEditingTitle:A,beginEdit:c,saveEdit:j,applyTodoAction:F,addChild:U,dragTodoId:Q,setDragTodoId:L,dropTodo:w}=u,J=Array.isArray(f.children)?f.children:[],N=J.map((z,Z)=>({child:z,childIndex:Z})).filter((z)=>I9(z.child,y)),q=_===f.id,W=r||null;return Au("div",{className:"todo-row-wrap"},Au("article",{className:`todo-row ${f.completed?"completed":""} ${Q===f.id?"dragging":""}`,style:{"--todo-depth":l},draggable:!0,onDragStart:(z)=>{L(f.id),z.dataTransfer.effectAllowed="move"},onDragOver:(z)=>z.preventDefault(),onDrop:(z)=>{z.preventDefault(),w(f.id,J.length)},"data-testid":`todo-row-${RL(f.id)}`},Au("button",{type:"button",className:"todo-expand",disabled:J.length===0,onClick:()=>F({type:"toggleTodoExpanded",todoId:f.id})},J.length===0?"·":f.expanded?"▾":"▸"),Au("input",{type:"checkbox",checked:Boolean(f.completed),onChange:()=>F({type:"toggleTodoCompleted",todoId:f.id}),"aria-label":`完成 ${f.title}`}),Au("div",{className:"todo-title-cell",onDoubleClick:()=>c(f)},q?Au("div",{className:"todo-edit-inline"},Au("input",{value:$,autoFocus:!0,onChange:(z)=>A(z.target.value),onKeyDown:(z)=>{if(z.key==="Enter")j(f.id);if(z.key==="Escape")c({id:"",title:""})}}),Au("button",{type:"button",className:"ghost-btn",onClick:()=>j(f.id)},"保存")):Au("strong",null,f.title||"Untitled"),Au("div",{className:"todo-meta-line"},Au("span",null,`子项 ${J.length}`),Au("span",null,`更新 ${Nu(f.updatedAt)}`),f.reminderAt?Au("span",{className:"todo-reminder"},`提醒 ${Nu(f.reminderAt)}`):Au("span",null,"无提醒"))),Au("input",{className:"todo-reminder-input",type:"datetime-local",value:e8(f.reminderAt),onChange:(z)=>F({type:"setTodoReminder",todoId:f.id,reminderAt:p7(z.target.value)})}),Au("div",{className:"todo-row-actions"},Au("button",{type:"button",className:"ghost-btn",onClick:()=>c(f)},"编辑"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>U(f.id)},"子项"),Au("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:n-1})},"上移"),Au("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:0})},"置顶"),Au("button",{type:"button",className:"ghost-btn",disabled:n>=i-1,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:n+1})},"下移"),Au("button",{type:"button",className:"ghost-btn",disabled:!r,onClick:()=>F({type:"moveTodo",todoId:f.id,targetIndex:9999})},"提升"),Au("button",{type:"button",className:"ghost-btn danger",onClick:()=>F({type:"deleteTodo",todoId:f.id})},"删除"))),f.expanded&&N.length>0?Au("div",{className:"todo-children"},N.map(({child:z,childIndex:Z})=>Au(bL,{key:z.id,todo:z,depth:l+1,parentId:f.id,index:Z,siblingCount:J.length,filter:y,editingId:_,editingTitle:$,setEditingTitle:A,beginEdit:c,saveEdit:j,applyTodoAction:F,addChild:U,dragTodoId:Q,setDragTodoId:L,dropTodo:w}))):null)}var vL=Pu(Qf(),1),vn=vL.default.createElement;function kL({title:u,items:f,actions:l,className:r,testId:n}){let i=Array.isArray(f)?f:[];return vn("section",{className:`top-status-bar ${r||""}`,"data-testid":n},vn("div",{className:"top-status-main"},u?vn("strong",{className:"top-status-title"},u):null,vn("div",{className:"top-status-chips"},i.map((y,_)=>vn("span",{key:y?.key||`${y?.label||"status"}-${_}`,className:`top-status-chip ${y?.tone||""}`,"data-testid":y?.testId},y?.label?vn("b",null,y.label):null,vn("span",null,y?.value??"--"))))),l?vn("div",{className:"top-status-actions"},l):null)}var P$=Pu(Qf(),1);var hf=P$.default.createElement;function IL({onClose:u}){let{notifications:f,removeNotification:l,clearNotifications:r}=Dl(),n=P$.default.useRef(null);if(P$.default.useEffect(()=>{let i=(y)=>{if(n.current&&!n.current.contains(y.target))u()};return document.addEventListener("mousedown",i),()=>document.removeEventListener("mousedown",i)},[u]),f.length===0)return hf("div",{className:"notification-popup",ref:n},hf("div",{className:"notification-popup-header"},hf("span",null,"通知"),hf("button",{className:"notification-popup-close",onClick:u},"×")),hf("div",{className:"notification-popup-empty"},"暂无通知"));return hf("div",{className:"notification-popup",ref:n},hf("div",{className:"notification-popup-header"},hf("span",null,`通知 (${f.length})`),hf("div",{className:"notification-popup-actions"},hf("button",{className:"notification-popup-clear",onClick:r},"清空"),hf("button",{className:"notification-popup-close",onClick:u},"×"))),hf("div",{className:"notification-popup-list"},f.slice().reverse().map((i)=>hf("div",{key:i.id,className:`notification-item ${i.type}`},hf("span",{className:"notification-item-icon"},i.type==="success"?"✓":"×"),hf("span",{className:"notification-item-message"},i.message),hf("button",{className:"notification-item-dismiss",onClick:()=>l(i.id)},"×")))))}function gL({notification:u}){let{removeNotification:f}=Dl();return P$.default.useEffect(()=>{let l=setTimeout(()=>{f(u.id)},3000);return()=>clearTimeout(l)},[u.id,f]),hf("div",{className:`notification-banner ${u.type}`,role:"alert"},hf("span",{className:"notification-banner-icon"},u.type==="success"?"✓":"×"),hf("span",{className:"notification-banner-message"},u.message),hf("button",{className:"notification-banner-dismiss",onClick:()=>f(u.id)},"×"))}function yw(u,f){let l=document.getElementById("root")?.getAttribute(u);if(!l)return f;try{let r=JSON.parse(l);return typeof r==="object"&&r!==null&&!Array.isArray(r)?r:f}catch{return f}}var su=yw("data-config",{apiBaseUrl:"/api",authUsername:"admin"}),MS=yw("data-codex-overview",null),t=In.default.createElement,{useEffect:J0,useMemo:R$}=In.default,hu=In.default.useState,o9=In.default.createContext(!1),Vr=bQ(l6),CS={id:"code-queue",name:"Code Queue",providerId:"D601",description:"Code Queue",repository:{containerName:"code-queue-backend"},backend:{nodeBaseUrl:"http://host.docker.internal:4222",nodeBindHost:"127.0.0.1",nodePort:4222,public:!1},runtime:{providerStatus:"loading",providerName:"D601"}};function sL(){return typeof document>"u"||document.visibilityState!=="hidden"}function RS(u,f){if(u==="ops"&&f==="status")return 5000;if(u==="nodes"&&f==="monitor")return 5000;if(u==="tasks"&&(f==="dispatch"||f==="scheduled"||f==="pending"))return 5000;if(u==="nodes"||u==="ops")return 1e4;if(u==="apps")return 15000;if(u==="tasks")return 15000;return 30000}async function xS(u){if(!u?._summaryOnly||!u?.id)return u;return(await Eu(`${su.apiBaseUrl}/tasks/${encodeURIComponent(String(u.id))}`))?.task||u}function x$(u){return u?._summaryOnly?{...u,_loadRaw:()=>xS(u)}:u}function h0(u){if(!Number.isFinite(u))return"--";let f=Math.max(0,u);if(f===0)return"0s";if(f<0.01)return"<0.01s";if(f<0.1)return`${f.toFixed(2)}s`;if(f<1)return`${f.toFixed(1)}s`;if(f<10&&!Number.isInteger(f))return`${f.toFixed(1)}s`;if(f<60)return`${Math.round(f)}s`;let l=Math.floor(f);if(l<3600)return`${Math.floor(l/60)}m ${l%60}s`;return`${Math.floor(l/3600)}h ${Math.floor(l%3600/60)}m`}function Qr(u){let f=Number(u);if(!Number.isFinite(f))return"--";if(f<1)return`${Math.max(0,f).toFixed(1)}ms`;if(f<10)return`${f.toFixed(1)}ms`;if(f<1000)return`${Math.round(f)}ms`;return h0(f/1000)}function zl(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=["B","KB","MB","GB","TB"],r=f,n=0;while(r>=1024&&n0)return l[r]}return"任务失败但 provider 未返回明确原因"}function x1(u){if(u===null||u===void 0)return"--";if(typeof u==="boolean")return u?"是":"否";if(typeof u==="number")return String(u);if(typeof u==="string")return u.length>80?`${u.slice(0,77)}...`:u;if(Array.isArray(u))return`${u.length} 项`;if(typeof u==="object")return`${Object.keys(u).length} 字段`;return String(u)}function bS(u,f){let l=u.replace(/[-_\s]/g,"").toLowerCase(),r=l==="ts"||l.endsWith("at")||l.endsWith("timestamp")||l.endsWith("heartbeat");if((typeof f==="string"||typeof f==="number")&&r){let n=Nu(f);if(n!=="--")return n}if(u==="bodyText"&&typeof f==="string")return`${/^\s*[{[]/.test(f)?"JSON":"HTTP"} body ${f.length} chars`;return x1(f)}function tw(u){if(!u||typeof u!=="object"||Array.isArray(u))return[];return Object.entries(u)}function dl(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function e9(u,f){return u&&typeof u==="object"&&!Array.isArray(u)?u[f]:void 0}function V8(u,f,l="未知"){let r=e9(u?.labels,f);return typeof r==="string"&&r.length>0?r:l}function Aw(u){return V8(u,"providerGatewayVersion")}function C$(u){return V8(u,"providerGatewayUpgradePolicy")}function aL(u){return V8(u,"providerGatewayStartedAt","")}function cw(u){let f=e9(u?.labels,"unideskCapabilities");if(typeof f==="string")return f.split(",").map((l)=>l.trim()).filter(Boolean);return Array.isArray(f)?f.filter((l)=>typeof l==="string"):[]}function jw(u,f){return cw(u).includes(f)}function oL(u,f){let l=e9(u?.labels,f);return l===!0||l==="true"||l==="1"}function vS(u){if(!jw(u,"host.ssh"))return{tone:"fail",label:"不可用",detail:"未声明 host.ssh"};if(!oL(u,"hostSshConfigured"))return{tone:"warn",label:"未配置",detail:"缺少 SSH 环境变量"};if(!oL(u,"hostSshKeyPresent"))return{tone:"warn",label:"缺 key",detail:"私钥未挂载"};return{tone:"ok",label:"可用",detail:V8(u,"hostSshTarget","host.ssh ready")}}function kS(u){if(!jw(u,"provider.upgrade"))return{tone:"fail",label:"不可用",detail:"未声明 provider.upgrade"};let f=C$(u);if(f!=="always-enabled")return{tone:"warn",label:"待确认",detail:`策略 ${f}`};return{tone:"ok",label:"可用",detail:"always-enabled"}}function u7(u){let f=typeof u==="string"&&u.length>0?u:"未知";if(f==="未知")return"版本未知";return f.startsWith("v")?f:`v${f}`}function Fw(u){return u?.payload&&typeof u.payload==="object"&&!Array.isArray(u.payload)?u.payload:{}}function D8(u){return u?.result&&typeof u.result==="object"&&!Array.isArray(u.result)?u.result:{}}function B8(u){let f=Fw(u),l=D8(u);return(f.mode??l.mode)==="schedule"?"schedule":"plan"}function IS(u){let f=Fw(u).source;return typeof f==="string"&&f.length>0?f:"unknown"}function gS(u){let f=D8(u),l=f.plan&&typeof f.plan==="object"&&!Array.isArray(f.plan)?f.plan:{},r=f.policy??l.policy;return typeof r==="string"&&r.length>0?r:"--"}function Jw(u){let f=D8(u),l=f.plan&&typeof f.plan==="object"&&!Array.isArray(f.plan)?f.plan:{},r=f.targetProviderGatewayVersion??f.providerGatewayVersion??l.targetProviderGatewayVersion??l.providerGatewayVersion;return typeof r==="string"&&r.length>0?u7(r):"版本未知"}function Uw(u){if(String(u?.status||"").toLowerCase()==="failed")return $w(u);if(Wy(u))return"等待 provider 回传升级终态";let l=D8(u);if(typeof l.updaterContainerId==="string"&&l.updaterContainerId.length>0)return`updater ${l.updaterContainerId.slice(0,18)}`;if(typeof l.message==="string"&&l.message.length>0)return l.message;if(l.plan)return"升级计划已生成";return"无升级结果摘要"}function Qw(u,f){return u.filter((l)=>l?.providerId===f&&l?.command==="provider.upgrade").sort((l,r)=>(U0(r.updatedAt)??0)-(U0(l.updatedAt)??0))}function sS(u){return u.find((f)=>B8(f)==="schedule")||u[0]||null}function qw(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function dL(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function aS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Lf({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return t("span",{className:`status-badge ${l}`},f||u||"unknown")}function Af({label:u,value:f,hint:l,tone:r,onClick:n,testId:i}){let y=typeof n==="function";return t("article",{className:`metric-card ${r||""} ${y?"clickable":""}`,role:y?"button":void 0,tabIndex:y?0:void 0,"data-testid":i,onClick:n,onKeyDown:y?(_)=>{if(_.key==="Enter"||_.key===" ")_.preventDefault(),n()}:void 0},t("div",{className:"metric-label"},u),t("div",{className:"metric-value"},f),t("div",{className:"metric-hint"},l))}function ou({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){let y=In.default.useContext(o9),_=Boolean(i)||y;return t("section",{className:`panel ${n||""}`},t("div",{className:"panel-head"},t("div",null,f?t("p",{className:"panel-eyebrow"},f):null,t(nf,{title:u,loading:_})),l?t("div",{className:"panel-actions"},l):null),t("div",{className:"panel-body"},r))}function bf({title:u,data:f,onOpen:l,testId:r}){let[n,i]=hu(!1),y=f&&typeof f==="object"&&typeof f._loadRaw==="function"?f._loadRaw:null;async function _(){if(!y){l(u,f);return}i(!0);try{l(u,await y())}catch($){l(u,{ok:!1,error:Zu($,"读取原始 JSON 失败"),fallback:f})}finally{i(!1)}}return t("button",{type:"button",className:"ghost-btn","data-testid":r,disabled:n,onClick:()=>void _()},n?"读取中":"查看原始JSON")}function oS({raw:u,onClose:f}){if(!u)return null;return t("div",{className:"modal-backdrop",role:"presentation"},t("section",{className:"raw-dialog",role:"dialog","aria-modal":"true","aria-label":u.title},t("div",{className:"raw-dialog-head"},t("h2",null,u.title),t("button",{type:"button",className:"ghost-btn",onClick:f},"关闭")),t("pre",{className:"raw-json","data-testid":"raw-json"},JSON.stringify(u.data,null,2))))}function Nw({labels:u,limit:f=8}){let l=tw(u).slice(0,f);if(l.length===0)return t("span",{className:"muted"},"无标签");return t("div",{className:"chip-row"},l.map(([r,n])=>t("span",{key:r,className:"data-chip"},t("b",null,r),t("span",null,x1(n)))))}function Ny({node:u}){let f=Aw(u);return t("span",{className:`version-chip ${f==="未知"?"unknown":""}`,"data-testid":`gateway-version-${dl(u?.providerId||"unknown")}`},u7(f))}function eL({title:u,state:f,testId:l}){return t("span",{className:`capability-badge ${f.tone}`,title:f.detail,"data-testid":l},t("b",null,u),t("strong",null,f.label),t("small",null,f.detail))}function f7({node:u}){let f=dl(u?.providerId||"unknown");return t("div",{className:"node-availability-strip"},t(eL,{title:"SSH 透传",state:vS(u),testId:`ssh-availability-${f}`}),t(eL,{title:"远程更新",state:kS(u),testId:`upgrade-availability-${f}`}))}function gn({data:u,empty:f="无数据"}){if(u===null||u===void 0)return t("span",{className:"muted"},f);if(typeof u!=="object")return t("span",{className:"summary-value"},x1(u));if(Array.isArray(u))return t("span",{className:"summary-value"},`${u.length} 项列表`);let l=Object.entries(u).slice(0,5);if(l.length===0)return t("span",{className:"muted"},f);return t("div",{className:"summary-grid"},l.map(([r,n])=>t("span",{key:r,className:"summary-item"},t("b",null,r),t("span",null,bS(r,n)))))}function jf({title:u,text:f}){return t("div",{className:"empty-state"},t("strong",null,u),t("span",null,f))}function dS({onLogin:u}){let[f,l]=hu(su.authUsername||"admin"),[r,n]=hu(""),[i,y]=hu(""),[_,$]=hu(!1);async function A(c){c.preventDefault(),$(!0),y("");try{let j=await Eu("/login",{method:"POST",body:JSON.stringify({username:f,password:r})});u(j)}catch(j){y(Zu(j,"登录失败"))}finally{$(!1)}}return t("main",{className:"login-screen","data-testid":"login-screen"},t("section",{className:"login-card"},t("div",{className:"login-brand"},t("span",{className:"brand-mark"},"UD"),t("div",null,t("h1",null,"UniDesk"),t("p",null,"Control Plane Login"))),t("form",{className:"login-form",onSubmit:A},t("label",null,"账号",t("input",{name:"username",autoComplete:"username",value:f,onChange:(c)=>l(c.target.value)})),t("label",null,"密码",t("input",{name:"password",type:"password",autoComplete:"current-password",value:r,onChange:(c)=>n(c.target.value)})),t(yf,{error:i}),t("button",{type:"submit",disabled:_},_?"登录中":"登录")),t("div",{className:"login-note"},"默认账号由 config.json 注入;公网入口只暴露前端登录面。")))}function eS({connection:u,lastRefresh:f,onRefresh:l,onLogout:r,session:n,clock:i,activeStatusItems:y=[],onNotificationToggle:_,unreadCount:$=0}){let A=[{key:"core",label:"核心",value:u.text,tone:u.ok?"ok":"fail",testId:"conn-text"},...Array.isArray(y)?y:[],{key:"refresh",label:"刷新",value:f?$f(f):"未刷新"},{key:"clock",label:_3,value:$f(i)},{key:"user",label:"用户",value:n?.user?.username||"--",tone:"user"}];return t("header",{className:"topbar"},t("div",null,t("p",{className:"eyebrow"},"Distributed Work Platform"),t("h1",null,"UniDesk 控制平面")),t(kL,{className:"global-top-status",title:"状态",items:A,actions:[t("button",{key:"notification",type:"button",className:`notification-icon-btn ${$>0?"has-unread":""}`,onClick:_,"aria-label":"通知"},"\uD83D\uDD14",$>0?t("span",{key:"badge",className:"notification-badge"},$>99?"99+":$):null),t("button",{key:"refresh",type:"button",className:"ghost-btn",onClick:l},"刷新"),t("button",{key:"logout",type:"button",className:"ghost-btn danger",onClick:r},"退出")]}))}function up(u){return!u.defaultPrevented&&u.button===0&&!u.metaKey&&!u.altKey&&!u.ctrlKey&&!u.shiftKey&&u.currentTarget.target!=="_blank"}function Ww({moduleId:u,tabId:f,className:l,active:r=!1,title:n,testId:i,onNavigate:y,children:_}){let $=r6(Vr,u,f);return t("a",{href:$,role:"button",className:l,title:n,"aria-current":r?"page":void 0,"data-testid":i,"data-route":$,onClick:(A)=>{if(!up(A))return;A.preventDefault(),y(u,f)}},_)}function fp({activeModule:u,activeTabs:f,onNavigate:l,collapsed:r,onToggle:n}){return t("aside",{className:`rail ${r?"collapsed":""}`,"aria-label":"主模块"},t("div",{className:"brand"},t("span",{className:"brand-mark"},"UD"),t("span",{className:"brand-text"},"UniDesk"),t("button",{type:"button",className:"rail-toggle",onClick:n,"aria-label":r?"展开左侧边栏":"收起左侧边栏","data-testid":"rail-toggle"},r?"»":"«")),l6.map((i)=>{let y=f[i.id]||I_[i.id]||i.tabs[0]?.id||"";return t(Ww,{key:i.id,moduleId:i.id,tabId:y,className:`module ${u===i.id?"active":""}`,active:u===i.id,title:i.label,onNavigate:l},t("span",{className:"module-code"},i.code),t("span",null,i.label))}))}function lp({module:u,activeTab:f,onNavigate:l}){return t("nav",{className:"tabs","aria-label":`${u.label} 子功能`},u.tabs.map((r)=>t(Ww,{key:r.id,moduleId:u.id,tabId:r.id,className:`tab ${f===r.id?"active":""}`,active:f===r.id,onNavigate:l},r.label)))}function rp({data:u,onRaw:f,onNavigate:l}){let r=u.overview||{},n=u.nodes.filter((U)=>U.status==="online"),i=u.pendingTasks||u.tasks.filter(Wy),y=r.pendingTaskCount??i.length,_=u.tasks.slice(0,5),$=r.pgdata||{},A=r.microserviceAvailability||{},c=Mu(A.totalCount),j=Mu(A.healthyCount),F=Mu(A.unhealthyCount);return t("div",{className:"page-grid overview-grid","data-testid":"overview-page"},t(ou,{title:"核心指标",eyebrow:"Control"},t("div",{className:"metric-grid"},t(Af,{label:"数据库",value:r.dbReady?"READY":"WAIT",hint:"PostgreSQL internal network",tone:r.dbReady?"ok":"warn"}),t(Af,{label:"PGDATA",value:zl($.databaseBytes),hint:`${$.volumeName||"unidesk_pgdata_10gb"} / ${$.databasePretty||"--"}`,tone:"ok",testId:"pgdata-usage-card"}),t(Af,{label:"在线节点",value:r.onlineNodeCount??0,hint:`${r.nodeCount??0} registered`,tone:"ok"}),t(Af,{label:"WebSocket",value:r.activeSocketCount??0,hint:"Provider ingress sockets"}),t(Af,{label:"用户服务可用",value:c>0?`${j}/${c}`:"--",hint:c>0?`healthyCount ${j} · unhealthyCount ${F}`:"strict /health probes",tone:c>0&&F===0?"ok":"warn",testId:"microservice-availability-card"}),t(Af,{label:"待处理任务",value:y,hint:y>0?"点击查看具体任务":`timeout ${h0(Math.floor((r.taskPendingTimeoutMs??0)/1000))}`,tone:y>0?"warn":"ok",onClick:()=>l("tasks","pending"),testId:"pending-task-card"}))),t(ou,{title:"本机 Provider",eyebrow:"Self Connected"},n.length===0?t(jf,{title:"暂无在线节点",text:"provider-gateway 未完成自接入"}):t("div",{className:"node-card-list"},n.slice(0,4).map((U)=>t(np,{key:U.providerId,node:U,onRaw:f})))),t(ou,{title:"待处理任务明细",eyebrow:`${y} Pending`,actions:t("button",{type:"button",className:"ghost-btn",onClick:()=>l("tasks","pending"),"data-testid":"pending-task-detail-link"},"进入任务调度")},i.length===0?t(jf,{title:"当前无待处理",text:"queued / dispatched / running 超时后会自动转为 failed,避免总览长期卡住"}):t("div",{className:"compact-list"},i.slice(0,5).map((U)=>t(rw,{key:U.id,task:U,onRaw:f})))),t(ou,{title:"最近任务",eyebrow:"Dispatch"},_.length===0?t(jf,{title:"暂无任务",text:"可以在任务调度模块发起 docker.ps 或 echo"}):t("div",{className:"compact-list"},_.map((U)=>t(rw,{key:U.id,task:U,onRaw:f})))))}function np({node:u,onRaw:f}){return t("article",{className:"node-card"},t("div",{className:"node-card-head"},t("div",null,t("strong",null,u.name),t("code",null,u.providerId)),t(Lf,{status:u.status})),t("div",{className:"node-version-line"},t(Ny,{node:u}),t("span",null,`升级策略 ${C$(u)}`)),t(f7,{node:u}),t(Nw,{labels:u.labels,limit:6}),t("div",{className:"node-card-foot"},t("span",null,`心跳 ${Nu(u.lastHeartbeat)}`),t(bf,{title:`Provider ${u.providerId}`,data:u,onOpen:f,testId:`raw-node-${dl(u.providerId)}`})))}function ip({events:u,onRaw:f}){return t(ou,{title:"事件摘要",eyebrow:"Latest 100"},u.length===0?t(jf,{title:"暂无事件",text:"Provider 注册、心跳超时和任务状态会写入事件流"}):t("div",{className:"table-wrap"},t("table",null,t("thead",null,t("tr",null,t("th",null,"ID"),t("th",null,"类型"),t("th",null,"来源"),t("th",null,"摘要"),t("th",null,"时间"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.id},t("td",null,t("code",null,l.id)),t("td",null,t(Lf,{status:l.type},l.type)),t("td",null,t("code",null,l.source)),t("td",null,t(gn,{data:l.payload})),t("td",null,Nu(l.createdAt)),t("td",null,t(bf,{title:`Event ${l.id}`,data:l,onOpen:f}))))))))}function yp({logs:u,onRaw:f}){return t(ou,{title:"服务日志",eyebrow:"Core Recent"},u.length===0?t(jf,{title:"暂无日志",text:"backend-core 内存日志会在请求和 provider 事件后出现"}):t("div",{className:"log-list"},u.slice(-80).reverse().map((l,r)=>t("article",{key:r,className:`log-row ${l.level||"info"}`},t("span",null,Nu(l.ts)),t("b",null,l.level||"info"),t("strong",null,l.message||"log"),t(gn,{data:l.data,empty:"无附加字段"}),t(bf,{title:`Log ${l.message||r}`,data:l,onOpen:f})))))}function _p({nodes:u,onRaw:f}){return t(ou,{title:"节点清单",eyebrow:`${u.length} Providers`},u.length===0?t(jf,{title:"暂无 Provider 节点",text:"确认 provider-gateway 已连接 provider ingress"}):t("div",{className:"table-wrap"},t("table",{className:"node-list-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"Provider"),t("th",null,"网关版本"),t("th",null,"运维可用性"),t("th",null,"资源标签"),t("th",null,"连接时间"),t("th",null,"最后心跳"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.providerId},t("td",null,t(Lf,{status:l.status})),t("td",null,t("strong",null,l.name),t("code",null,l.providerId)),t("td",null,t("div",{className:"gateway-cell"},t(Ny,{node:l}),t("span",null,C$(l)))),t("td",null,t(f7,{node:l})),t("td",null,t(Nw,{labels:l.labels,limit:5})),t("td",null,Nu(l.connectedAt)),t("td",null,Nu(l.lastHeartbeat)),t("td",null,t(bf,{title:`Provider ${l.providerId}`,data:l,onOpen:f,testId:`raw-node-table-${dl(l.providerId)}`}))))))))}function $p({nodes:u}){let f=R$(()=>{let l=[];for(let r of u)for(let[n,i]of tw(r.labels))l.push({providerId:r.providerId,name:r.name,key:n,value:i});return l},[u]);return t(ou,{title:"资源标签",eyebrow:"Structured Labels"},f.length===0?t(jf,{title:"暂无标签",text:"provider-gateway 注册消息会同步资源标签"}):t("div",{className:"label-matrix"},f.map((l)=>t("article",{key:`${l.providerId}-${l.key}`,className:"label-card"},t("span",null,l.key),t("strong",null,x1(l.value)),t("code",null,l.providerId)))))}function tp({nodes:u}){return t(ou,{title:"心跳状态",eyebrow:"Provider Liveness"},u.length===0?t(jf,{title:"无心跳",text:"等待 provider 注册和 heartbeat"}):t("div",{className:"heartbeat-list"},u.map((f)=>t("article",{key:f.providerId,className:"heartbeat-row"},t("span",{className:`pulse ${f.status}`}),t("div",null,t("strong",null,f.name),t("code",null,f.providerId)),t("div",null,t("span",null,"connected"),t("b",null,Nu(f.connectedAt))),t("div",null,t("span",null,"last heartbeat"),t("b",null,Nu(f.lastHeartbeat)))))))}function Ap({nodes:u,systemStatuses:f,tasks:l,onRaw:r,refresh:n}){let[i,y]=hu(""),_=R$(()=>u.map((L)=>{let w=f.find((J)=>J.providerId===L.providerId);return{...L,systemCurrent:w?.current||null,systemHistory:w?.history||[],systemUpdatedAt:w?.updatedAt||null}}),[u,f]),$=_.find((L)=>L.providerId===i)||_[0]||null;if(J0(()=>{if(!i&&_[0])y(_[0].providerId)},[_.length,i]),!$)return t(jf,{title:"暂无资源监控",text:"等待 provider 上报 CPU、内存和硬盘指标"});let A=$.systemCurrent,c=$.systemHistory||[],j=A?.cpu||{},F=A?.memory||{},U=A?.disk||{},Q=c.length>0?c:A?[{at:A.collectedAt,cpuPercent:Mu(j.percent),memoryPercent:Mu(F.percent),diskPercent:Mu(U.percent)}]:[];return t("div",{className:"monitor-page","data-testid":"node-monitor-page"},t("div",{className:"docker-node-strip"},_.map((L)=>t("button",{key:L.providerId,type:"button",className:`docker-node-tile ${$.providerId===L.providerId?"active":""}`,onClick:()=>y(L.providerId)},t("span",{className:`pulse ${L.status}`}),t("strong",null,L.name),t("code",null,L.providerId),t("span",null,L.systemCurrent?`CPU ${kn(L.systemCurrent.cpu?.percent)} / MEM ${kn(L.systemCurrent.memory?.percent)}`:"等待指标")))),t("div",{className:"monitor-layout"},t(ou,{title:"任务管理器视图",eyebrow:$.name,className:"monitor-main-panel",actions:A?t(bf,{title:`System ${$.providerId}`,data:{current:A,history:c},onOpen:r}):null},!A?t(jf,{title:"系统指标未上报",text:"provider-gateway 会周期性采集 /proc 与 df,并保存历史曲线"}):t("div",null,t("div",{className:"monitor-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Node Performance"),t("h3",null,$.name),t("div",{className:"docker-meta"},t("span",null,`${j.cores||0} CPU cores`),t("span",null,`load ${Mu(j.load1).toFixed(2)} / ${Mu(j.load5).toFixed(2)} / ${Mu(j.load15).toFixed(2)}`),t("span",null,`memory actual ${zl(F.usedBytes)} / ${zl(F.totalBytes)}`),t("span",null,`disk ${zl(U.usedBytes)} / ${zl(U.totalBytes)}`))),t(Lf,{status:A.ok?"online":"warn"},A.ok?"METRICS READY":"METRICS DEGRADED")),t("div",{className:"monitor-chart-grid"},t(s9,{title:"CPU",metricKey:"cpuPercent",current:j.percent,points:Q,detail:`${j.cores||0} cores / load ${Mu(j.load1).toFixed(2)}`,tone:"cpu",testId:"metric-chart-cpu"}),t(s9,{title:"Memory",metricKey:"memoryPercent",current:F.percent,points:Q,detail:`${zl(F.usedBytes)} actual / ${zl(F.cacheBytes)} cache excluded`,tone:"memory",testId:"metric-chart-memory"}),t(s9,{title:"Disk",metricKey:"diskPercent",current:U.percent,points:Q,detail:`${U.path||"/"} mounted ${U.mount||"--"}`,tone:"disk",testId:"metric-chart-disk"})),t("div",{className:"monitor-summary-grid"},t(Af,{label:"CPU 当前",value:kn(j.percent),hint:`history ${Q.length} samples`,tone:"ok"}),t(Af,{label:"实际内存",value:zl(F.usedBytes),hint:`${kn(F.percent)} 不含缓存`}),t(Af,{label:"硬盘已用",value:zl(U.usedBytes),hint:kn(U.percent)}),t(Af,{label:"更新时间",value:Nu($.systemUpdatedAt||A.collectedAt),hint:$.providerId})),t(cp,{current:A,onRaw:r}))),t("div",{className:"monitor-side-stack"},t(Wp,{provider:$,refresh:n,onRaw:r}),t(Lp,{provider:$,tasks:l,onRaw:r,limit:5}),t(ou,{title:"采样说明",eyebrow:"Retention"},t("div",{className:"monitor-note-list"},t("article",null,t("b",null,"CPU"),t("span",null,"从 /proc/stat 计算相邻采样差值,首个采样用 load/cores 近似")),t("article",null,t("b",null,"Memory"),t("span",null,"实际内存 = MemTotal - MemFree - Buffers - Cached - SReclaimable + Shmem,不把 page cache / buffer 计入占用")),t("article",null,t("b",null,"Disk"),t("span",null,"使用 df -PB1 对配置路径采样,默认监控根文件系统")),t("article",null,t("b",null,"Process"),t("span",null,"从 /proc/[pid] 采集进程 CPU、实际内存 RSS、线程数和磁盘 I/O 速率;表格默认按内存占用降序")))))))}function uw(u,f){if(f==="memory")return Mu(u.rssBytes);if(f==="cpu")return Mu(u.cpuPercent);if(f==="disk")return Mu(u.readBytesPerSecond)+Mu(u.writeBytesPerSecond);if(f==="pid")return Mu(u.pid);if(f==="threads")return Mu(u.threads);if(f==="runtime")return Mu(u.elapsedSeconds);if(f==="user")return String(u.user||"");return String(u.name||u.command||"")}function fw({value:u,label:f,tone:l}){let r=Math.max(1,Math.min(100,Mu(u)));return t("div",{className:`process-meter ${l||""}`},t("span",{style:{width:`${r}%`}}),t("b",null,f))}function cp({current:u,onRaw:f}){let[l,r]=hu({key:"memory",direction:"desc"}),n=In.default.useContext(o9),i=u?.processSummary&&typeof u.processSummary==="object"?u.processSummary:{},y=Array.isArray(u?.processes)?u.processes:[],_=R$(()=>{let A=l.direction==="asc"?1:-1;return[...y].sort((c,j)=>{let F=uw(c,l.key),U=uw(j,l.key);if(typeof F==="string"||typeof U==="string")return String(F).localeCompare(String(U),"zh-CN")*A;return(F-U)*A||Mu(c.pid)-Mu(j.pid)})},[y,l.key,l.direction]),$=(A,c)=>{let j=l.key===c,F=j?l.direction==="asc"?"ascending":"descending":"none";return t("th",{"aria-sort":F},t("button",{type:"button",className:`process-sort-button ${j?"active":""}`,"data-testid":`process-sort-${c}`,onClick:()=>r((U)=>({key:c,direction:U.key===c&&U.direction==="desc"?"asc":"desc"}))},A,t("span",null,j?l.direction==="desc"?"↓":"↑":"↕")))};return t("section",{className:"process-resource-panel","data-testid":"process-resource-panel"},t("div",{className:"process-resource-head"},t("div",null,t("p",{className:"panel-eyebrow"},"Windows Resource Monitor Style"),t(nf,{title:"进程资源占用",level:3,loading:n})),t("div",{className:"process-resource-actions"},t("span",{className:"data-chip"},"默认按内存排序"),t("span",{className:"data-chip"},`${Mu(i.visible,_.length)} / ${Mu(i.total,_.length)} 进程`),t(bf,{title:"Process Resource Snapshot",data:{processSummary:i,processes:y},onOpen:f,testId:"raw-process-resources"}))),_.length===0?t(jf,{title:"暂无进程资源数据",text:"等待 provider-gateway 上报 /proc/[pid] 采样;旧版 provider 需要先升级到支持进程资源表的版本"}):t("div",{className:"process-table-wrap"},t("table",{className:"process-resource-table","data-testid":"process-resource-table"},t("thead",null,t("tr",null,$("进程","name"),$("PID","pid"),$("用户","user"),t("th",null,"状态"),$("CPU","cpu"),$("内存","memory"),t("th",null,"RSS"),$("磁盘 I/O","disk"),$("线程","threads"),$("运行时长","runtime"))),t("tbody",null,_.map((A)=>{let c=Mu(A.readBytesPerSecond)+Mu(A.writeBytesPerSecond);return t("tr",{key:`${A.pid}-${A.startedAt}`,"data-testid":`process-row-${dl(A.pid)}`,"data-memory-bytes":String(Mu(A.rssBytes)),"data-cpu-percent":String(Mu(A.cpuPercent)),"data-disk-bps":String(c),"data-pid":String(Mu(A.pid))},t("td",null,t("div",{className:"process-name-cell"},t("strong",null,A.name||"--"),t("span",{className:"process-command"},A.command||"--"))),t("td",null,t("code",null,A.pid||"--")),t("td",null,A.user||`uid:${A.uid??"--"}`),t("td",null,t("span",{className:`process-state state-${dl(A.state||"unknown")}`},A.state||"?")),t("td",null,t(fw,{value:A.cpuPercent,label:hS(A.cpuPercent),tone:"cpu"})),t("td",null,t(fw,{value:A.memoryPercent,label:kn(A.memoryPercent),tone:"memory"})),t("td",null,zl(A.rssBytes)),t("td",null,t("div",{className:"process-io-cell"},t("strong",null,g9(c)),t("span",null,`R ${g9(A.readBytesPerSecond)} / W ${g9(A.writeBytesPerSecond)}`))),t("td",null,A.threads||0),t("td",null,h0(Mu(A.elapsedSeconds))))})))))}function s9({title:u,metricKey:f,current:l,points:r,detail:n,tone:i,testId:y}){let _=r.map((F)=>Math.max(0,Math.min(100,Mu(F[f])))),$=_.length>1?_:[_[0]||0,_[0]||0],A=$.length<=1?100:100/($.length-1),c=$.map((F,U)=>`${(U*A).toFixed(2)},${(46-F*0.42).toFixed(2)}`).join(" "),j=`0,48 ${c} 100,48`;return t("article",{className:`metric-chart ${i}`,"data-testid":y},t("div",{className:"metric-chart-head"},t("div",null,t("span",null,u),t("strong",null,kn(l))),t("code",null,`${r.length} pts`)),t("svg",{viewBox:"0 0 100 48",preserveAspectRatio:"none",role:"img","aria-label":`${u} usage curve`},t("polygon",{points:j}),t("polyline",{points:c}),t("line",{x1:"0",x2:"100",y1:"24",y2:"24"})),t("div",{className:"metric-chart-foot"},t("span",null,"0%"),t("span",null,n),t("span",null,"100%")))}function b0(u){return Array.isArray(u)?u:[]}function jp(u){let f=b0(u?.core?.requests?.componentSummary);return[...b0(u?.frontend?.requests?.componentSummary),...f].sort((r,n)=>Mu(n.requestCount)-Mu(r.requestCount))}function Fp(u){let f=b0(u?.core?.operations?.summary);return[...b0(u?.frontend?.operations?.summary),...f].sort((r,n)=>Mu(n.count)-Mu(r.count))}function Jp(u){let f=b0(u?.core?.requests?.recentFailures).map((r)=>({source:"backend",...r}));return[...b0(u?.frontend?.requests?.recentFailures).map((r)=>({source:"frontend",...r})),...f].sort((r,n)=>(U0(n.at)??0)-(U0(r.at)??0)).slice(0,20)}function Up(u){let f=b0(u?.core?.operations?.recentSlowOperations);return[...b0(u?.frontend?.operations?.recentSlowOperations),...f].sort((r,n)=>Mu(n.durationMs)-Mu(r.durationMs)).slice(0,20)}function Qp(u){let f=performance.memory,l=Number(f?.usedJSHeapSize);if(Number.isFinite(l)&&l>0)return l;let r=Number(u?.appBundleBytes);if(Number.isFinite(r)&&r>0)return r;return Mu(u?.process?.heapUsedBytes)}function qp({points:u}){let f=b0(u),l=f.map((F)=>Mu(F.mb)),r=Math.max(1,...l),n=Math.max(0,Math.min(...l,0)),i=Math.max(1,r-n),y=f.length>1?f:[...f,...f],_=y.length<=1?100:100/(y.length-1),$=y.map((F,U)=>{let Q=Mu(F.mb);return`${(U*_).toFixed(2)},${(48-(Q-n)/i*42).toFixed(2)}`}).join(" "),A=`0,50 ${$} 100,50`,c=f.at(-1),j=f[0];return t("article",{className:"performance-memory-card","data-testid":"performance-memory-chart"},t("div",{className:"performance-memory-head"},t("strong",null,`Bwebui: ${c?`${Mu(c.mb).toFixed(1)}MB`:"--"}`),t("span",null,f.length>0?`${f.length} samples`:"等待采样")),t("svg",{viewBox:"0 0 100 50",preserveAspectRatio:"none",role:"img","aria-label":"Bwebui memory trend"},t("polygon",{points:A}),t("polyline",{points:$}),t("line",{x1:"0",x2:"100",y1:"25",y2:"25"})),t("div",{className:"performance-axis-row"},t("span",null,j?$f(new Date(j.at)):"--"),t("span",null,"时间"),t("span",null,c?$f(new Date(c.at)):"--")),t("div",{className:"performance-axis-row"},t("span",null,`${n.toFixed(1)}`),t("span",null,"(MB)"),t("span",null,`${r.toFixed(1)}`)))}function Np({onRaw:u}){let[f,l]=hu({core:null,frontend:null}),[r,n]=hu([]),[i,y]=hu(""),[_,$]=hu(!1),[A,c]=hu(null),[j,F]=hu(!1);async function U(){$(!0),y("");try{let[Y,p]=await Promise.all([Eu(`${su.apiBaseUrl}/performance`,{cache:"no-store"}),Eu(`${su.apiBaseUrl}/frontend-performance`,{cache:"no-store"})]);l({core:Y,frontend:p});let O=Qp(p);n((m)=>[...m,{at:new Date().toISOString(),mb:O/1048576}].slice(-80))}catch(Y){y(Zu(Y,"性能指标加载失败"))}finally{$(!1)}}J0(()=>{U();let Y=setInterval(()=>void U(),5000);return()=>clearInterval(Y)},[]);async function Q(){F(!0),y(""),c(null);try{let Y=await Eu(`${su.apiBaseUrl}/code-queue-load-test`,{method:"POST",body:JSON.stringify({targetMs:1000,timeoutMs:90000,url:su.frontendPublicUrl||window.location.origin})});c(Y),U()}catch(Y){y(Zu(Y,"Code Queue Playwright 测量失败"))}finally{F(!1)}}let L=jp(f),w=Jp(f),J=Fp(f),N=Up(f),q=f.core?.process||{},W=f.frontend?.process||{},z=f.core?.database?.codeQueueStorage||{},Z=Mu(z.total),H=A?.result||{},E=Mu(H.wallMs,NaN),D=Mu(H.networkIdleMs,NaN),h=H.withinTarget===!0,V=j?"running":A===null?"idle":A.measurementOk===!0?h?"passed":"slow":"failed";return t("div",{className:"performance-page","data-testid":"performance-page"},t("div",{className:"performance-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Unified Performance"),t(nf,{title:"性能面板",loading:_||j}),t("p",null,"按组件统计 HTTP 请求、失败率、P95 延迟,并汇总 backend/frontend 内部操作耗时。")),t("div",{className:"inline-actions"},t("button",{type:"button",className:"ghost-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-button"},j?"测试中...":"测试 Code Queue 加载"),t("button",{type:"button",className:"ghost-btn",onClick:()=>void U(),disabled:_,"data-testid":"performance-refresh-button"},_?"刷新中":"刷新"),t(bf,{title:"Performance Snapshot",data:f,onOpen:u,testId:"raw-performance"}))),t(yf,{error:i}),t("div",{className:"performance-top-grid"},t(qp,{points:r}),t("div",{className:"performance-metric-stack"},t(Af,{label:"backend RSS",value:zl(q.rssBytes),hint:`heap ${zl(q.heapUsedBytes)}`}),t(Af,{label:"frontend RSS",value:zl(W.rssBytes),hint:`bundle ${zl(f.frontend?.appBundleBytes)}`}),t(Af,{label:"Codex PG 任务",value:Z||"--",hint:z.ok?"unidesk_code_queue_tasks":"等待表初始化",tone:z.ok?"ok":"warn"}),t(Af,{label:"请求样本",value:Mu(f.core?.requests?.sampleCount)+Mu(f.frontend?.requests?.sampleCount),hint:"rolling window 3000"}))),t(ou,{title:"Code Queue 加载基准",eyebrow:"Playwright / target <1s",className:"codex-load-test-panel",loading:j,actions:t("div",{className:"panel-actions"},t("button",{type:"button",className:"primary-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-panel-button"},j?"正在运行 Playwright...":"手动触发测试"),A?t(bf,{title:"Code Queue Load Test",data:A,onOpen:u,testId:"raw-code-queue-load-test"}):null)},t("div",{className:"codex-load-test-grid","data-testid":"code-queue-load-test-result"},t(Af,{label:"总耗时",value:j?"运行中":Number.isFinite(E)?Qr(E):"--",hint:A===null?"点击按钮启动远端 Playwright":`目标 ${Qr(H.targetMs||1000)} / ${H.url||"Code Queue"}`,tone:V==="passed"?"ok":V==="failed"||V==="slow"?"warn":""}),t(Af,{label:"判定",value:j?"RUNNING":V==="passed"?"PASS <1s":V==="slow"?"SLOW":V==="failed"?"FAILED":"--",hint:A?.measurementOk===!1?String(A.error||H.error||"measurement failed").slice(0,120):"导航开始 -> DOMContentLoaded -> data-load-state=complete",tone:V==="passed"?"ok":V==="idle"||V==="running"?"":"fail"}),t(Af,{label:"Network idle",value:Number.isFinite(D)?Qr(D):"--",hint:`DOMContentLoaded ${Qr(H.domContentLoadedMs)} / ${H.networkIdleReached===!1?"未在 5s 内空闲":"已空闲"}`,tone:Number.isFinite(D)&&D<=1000?"ok":"warn"}),t(Af,{label:"组件耗时",value:Number.isFinite(Mu(H.componentLoadMs,NaN))?Qr(H.componentLoadMs):"--",hint:`queue ${Qr(H.queueMs)} / detail ${Qr(H.detailMs)}`,tone:Mu(H.componentLoadMs)>1000?"warn":"ok"}),t(Af,{label:"Trace 规模",value:Number.isFinite(Mu(H.transcriptRows,NaN))?String(H.transcriptRows):"--",hint:`${H.visibleTaskCount??0} visible tasks / ${H.partial?"preview":"complete"}`})),j?t("div",{className:"performance-empty-line"},"正在通过 main-server Host SSH 启动 Playwright,完成后会显示 wall time、组件耗时和最慢 API。"):null,A&&Array.isArray(H.slowestApi)&&H.slowestApi.length>0?t("div",{className:"table-wrap performance-table-wrap compact codex-load-api-table"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["API","状态","耗时"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,H.slowestApi.slice(0,5).map((Y,p)=>t("tr",{key:`${Y.url}-${p}`},t("td",null,t("code",null,Y.url)),t("td",null,Y.status),t("td",null,Qr(Y.durationMs))))))):null),t("div",{className:"performance-grid"},t(ou,{title:"组件汇总",eyebrow:"Requests",loading:_},L.length===0?t(jf,{title:"暂无请求样本",text:"刷新几次或打开页面后会自动形成组件统计"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["组件","请求数","失败数","失败率","平均延迟","P95"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,L.map((Y)=>t("tr",{key:Y.component},t("td",null,t("code",null,Y.component)),t("td",null,Y.requestCount),t("td",null,Y.failureCount),t("td",null,kn(Mu(Y.failureRate)*100)),t("td",null,Qr(Y.averageLatencyMs)),t("td",null,Qr(Y.p95LatencyMs)))))))),t(ou,{title:"最近失败请求",eyebrow:"Failures",loading:_},w.length===0?t("div",{className:"performance-empty-line"},"最近没有失败请求"):t("div",{className:"table-wrap performance-table-wrap compact"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["时间","来源","组件","状态","路径"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,w.map((Y,p)=>t("tr",{key:`${Y.at}-${p}`},t("td",null,Nu(Y.at)),t("td",null,Y.source),t("td",null,t("code",null,Y.component)),t("td",null,t(Lf,{status:"failed"},Y.status)),t("td",null,t("code",null,Y.path)))))))),t(ou,{title:"内部操作汇总",eyebrow:"Operations",loading:_},J.length===0?t(jf,{title:"暂无内部操作样本",text:"API 查询和代理请求会自动记录内部操作耗时"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["服务","操作","次数","平均延迟","P95"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,J.map((Y)=>t("tr",{key:`${Y.service}-${Y.operation}`},t("td",null,Y.service),t("td",null,t("code",null,Y.operation)),t("td",null,Y.count),t("td",null,Qr(Y.averageLatencyMs)),t("td",null,Qr(Y.p95LatencyMs)))))))),t(ou,{title:"最近慢操作",eyebrow:"Slowest",loading:_},N.length===0?t(jf,{title:"暂无慢操作",text:"后端会记录最近窗口内耗时最高的内部操作"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["时间","操作","耗时","结果","细节"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,N.map((Y,p)=>t("tr",{key:`${Y.at}-${Y.operation}-${p}`},t("td",null,Nu(Y.at)),t("td",null,t("code",null,Y.operation)),t("td",null,Qr(Y.durationMs)),t("td",null,Y.ok?"成功":"失败"),t("td",null,Y.detail||"-")))))))))}function Wp({provider:u,refresh:f,onRaw:l}){let[r,n]=hu(""),[i,y]=hu(null),[_,$]=hu("");async function A(c){n(c),$("");try{let j=await Eu(`${su.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:u.providerId,command:"provider.upgrade",payload:{mode:c,source:"frontend-resource-monitor",requestedAt:new Date().toISOString()}})});y({mode:c,...j}),await f()}catch(j){$(Zu(j,"升级命令下发失败"))}finally{n("")}}return t(ou,{title:"Provider Gateway 升级",eyebrow:"Remote Control",loading:Boolean(r)},t("div",{className:"upgrade-control","data-testid":"provider-upgrade-control"},t("p",null,"通过 UniDesk WebSocket 向当前计算节点下发 provider.upgrade;预检只生成升级计划,执行升级会调度节点本地 updater 容器。"),t("div",{className:"upgrade-target-line"},t("span",null,"指定 Provider"),t("code",null,u.providerId),t(Ny,{node:u})),t("div",{className:"upgrade-actions"},t("button",{type:"button",className:"ghost-btn",disabled:Boolean(r),onClick:()=>A("plan"),"data-testid":"upgrade-plan-button"},r==="plan"?"预检中":"预检升级"),t("button",{type:"button",className:"ghost-btn danger",disabled:Boolean(r),onClick:()=>A("schedule"),"data-testid":"upgrade-schedule-button"},r==="schedule"?"调度中":"执行升级")),t(yf,{error:_}),i?t("div",{className:"upgrade-result"},t(Lf,{status:i.status||"queued"},i.status||"queued"),t("span",null,`${i.mode==="schedule"?"执行升级":"预检升级"} 已下发`),t("span",null,`指定版本 ${u7(Aw(u))}`),t("code",null,i.taskId||"--"),t(bf,{title:"Provider Upgrade Dispatch",data:i,onOpen:l})):t("span",{className:"muted"},"升级任务结果会进入任务历史;执行升级可能导致 provider 短暂重连。")))}function Lw({records:u,onRaw:f,compact:l=!1}){if(u.length===0)return t(jf,{title:"暂无远程更新记录",text:"该节点还没有 provider.upgrade 任务;执行预检或升级后会在这里形成结构化记录"});return t("div",{className:`upgrade-record-table-wrap table-wrap ${l?"compact":""}`},t("table",{className:"upgrade-record-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"模式"),t("th",null,"任务"),t("th",null,"来源"),t("th",null,"耗时"),t("th",null,"策略"),t("th",null,"Gateway 版本"),t("th",null,"结果记录"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,u.map((r)=>t("tr",{key:r.id,"data-testid":`gateway-upgrade-record-${dl(r.id)}`},t("td",null,t(Lf,{status:r.status})),t("td",null,t("span",{className:`mode-chip ${B8(r)}`},B8(r)==="schedule"?"执行升级":"预检")),t("td",null,t("strong",null,"provider.upgrade"),t("code",null,r.id)),t("td",null,IS(r)),t("td",null,t(Kw,{task:r})),t("td",null,gS(r)),t("td",null,t("span",{className:"version-chip"},Jw(r))),t("td",null,t("span",{className:`upgrade-outcome ${String(r.status||"").toLowerCase()}`},Uw(r))),t("td",null,Nu(r.updatedAt)),t("td",null,t(bf,{title:`Provider Upgrade Task ${r.id}`,data:x$(r),onOpen:f})))))))}function Lp({provider:u,tasks:f,onRaw:l,limit:r=5}){let n=Qw(f,u.providerId).slice(0,r);return t(ou,{title:"远程更新记录",eyebrow:u.providerId,actions:t(Ny,{node:u}),className:"provider-upgrade-records-panel"},t("div",{"data-testid":`provider-upgrade-records-${dl(u.providerId)}`},t(Lw,{records:n,onRaw:l,compact:!0})))}function wp({nodes:u,tasks:f,onRaw:l}){let r=R$(()=>u.map((i)=>{let y=Qw(f,i.providerId);return{node:i,records:y,latest:sS(y),capabilities:cw(i)}}),[u,f]),n=r.reduce((i,y)=>i+y.records.length,0);return t("div",{className:"gateway-page","data-testid":"gateway-version-page"},t(ou,{title:"Provider Gateway 版本",eyebrow:`${u.length} Providers / ${n} 更新记录`},u.length===0?t(jf,{title:"暂无 Provider 节点",text:"等待 provider-gateway 注册后显示版本号和升级记录"}):t("div",{className:"table-wrap gateway-version-table-wrap"},t("table",{className:"gateway-version-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"Provider"),t("th",null,"Gateway 版本"),t("th",null,"升级策略"),t("th",null,"运维可用性"),t("th",null,"运行时间"),t("th",null,"能力"),t("th",null,"最近远程更新"),t("th",null,"操作"))),t("tbody",null,r.map((i)=>t("tr",{key:i.node.providerId},t("td",null,t(Lf,{status:i.node.status})),t("td",null,t("strong",null,i.node.name),t("code",null,i.node.providerId)),t("td",null,t(Ny,{node:i.node})),t("td",null,C$(i.node)),t("td",null,t(f7,{node:i.node})),t("td",null,aL(i.node)?Nu(aL(i.node)):"待新版上报"),t("td",null,t("div",{className:"capability-row"},i.capabilities.length===0?t("span",{className:"muted"},"未声明"):i.capabilities.slice(0,5).map((y)=>t("span",{key:y,className:"data-chip"},y)))),t("td",null,i.latest?t("div",{className:"latest-upgrade-cell"},t(Lf,{status:i.latest.status}),t("span",null,`${B8(i.latest)==="schedule"?"执行升级":"预检"} / ${Nu(i.latest.updatedAt)}`),t("small",null,`Gateway ${Jw(i.latest)}`),t("small",null,Uw(i.latest))):t("span",{className:"muted"},"暂无记录")),t("td",null,t(bf,{title:`Provider ${i.node.providerId}`,data:i.node,onOpen:l})))))))),t(ou,{title:"远程更新记录",eyebrow:"Structured provider.upgrade records"},u.length===0?t(jf,{title:"暂无记录",text:"没有 provider 节点时不会生成远程更新记录"}):t("div",{className:"gateway-record-grid"},r.map((i)=>t("article",{key:i.node.providerId,className:"gateway-record-card","data-testid":`gateway-records-${dl(i.node.providerId)}`},t("div",{className:"gateway-record-head"},t("div",null,t("strong",null,i.node.name),t("code",null,i.node.providerId)),t(Ny,{node:i.node})),t("div",{className:"gateway-record-meta"},t("span",null,`心跳 ${Nu(i.node.lastHeartbeat)}`),t("span",null,`策略 ${C$(i.node)}`),t("span",null,`${i.records.length} 条记录`)),t(Lw,{records:i.records.slice(0,8),onRaw:l,compact:!0}))))))}function Kp(u){if(u==="running")return"online";if(u==="paused"||u==="restarting")return"warn";if(u==="exited"||u==="dead")return"offline";return"internal"}function ww(u){return/^[a-f0-9]{48,64}$/i.test(u)}function M$(u){let f=String(u?.name||""),l=String(u?.labels||"");return f==="unidesk_pgdata_10gb"||l.includes("com.docker.compose.volume=unidesk_pgdata_10gb")||f.toLowerCase().includes("pgdata")}function lw(u){let f=String(u?.name||""),l=String(u?.labels||"");if(M$(u))return 0;if(l.includes("com.docker.compose.project=unidesk"))return 1;if(!ww(f))return 2;return 3}function Gp(u){return[...u].sort((f,l)=>{let r=lw(f)-lw(l);if(r!==0)return r;return String(f.name||"").localeCompare(String(l.name||""))})}function zp({nodes:u,dockerStatuses:f,onRaw:l}){let[r,n]=hu(""),i=R$(()=>u.map((N)=>{let q=f.find((W)=>W.providerId===N.providerId);return{...N,dockerStatus:q?.dockerStatus||null,dockerUpdatedAt:q?.updatedAt||null}}),[u,f]),y=i.find((N)=>N.providerId===r)||i[0]||null;if(J0(()=>{if(!r&&i[0])n(i[0].providerId)},[i.length,r]),!y)return t(jf,{title:"暂无 Docker 节点",text:"等待 provider 上报 Docker daemon 状态"});let _=y.dockerStatus,$=y.providerId==="main-server",A=_?.counts||{},c=_?.daemon||{},j=_?.containers||[],F=_?.images||[],U=Gp(_?.volumes||[]),Q=$?U.find(M$):null,L=_?.networks||[],w=j.filter((N)=>N.state==="running"),J=j.filter((N)=>N.state!=="running");return t("div",{className:"docker-page","data-testid":"docker-status-page"},t("div",{className:"docker-node-strip"},i.map((N)=>t("button",{key:N.providerId,type:"button",className:`docker-node-tile ${y.providerId===N.providerId?"active":""}`,onClick:()=>n(N.providerId)},t("span",{className:`pulse ${N.status}`}),t("strong",null,N.name),t("code",null,N.providerId),t("span",null,N.dockerStatus?`Docker ${N.dockerStatus.ok?"ready":"degraded"}`:"等待上报")))),t("div",{className:"docker-layout"},t(ou,{title:"Docker Desktop 视图",eyebrow:y.name,className:"docker-main-panel",actions:_?t(bf,{title:`Docker ${y.providerId}`,data:_,onOpen:l}):null},!_?t(jf,{title:"Docker 状态未上报",text:"provider-gateway 会在连接后周期性采集 docker info / ps / images / volume / network"}):t("div",null,t("div",{className:"docker-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Daemon"),t("h3",null,c.name||y.providerId),t("div",{className:"docker-meta"},t("span",null,c.serverVersion?`Engine ${c.serverVersion}`:"Engine --"),t("span",null,c.operatingSystem||"OS --"),t("span",null,c.architecture||"arch --"),t("span",null,`${c.cpus||0} CPU / ${zl(c.memoryBytes)}`))),t(Lf,{status:_.ok?"online":"warn"},_.ok?"Docker Ready":"Docker Degraded")),t("div",{className:"docker-metrics"},t(Af,{label:"Containers",value:A.containers??j.length,hint:`${A.running??w.length} running / ${A.stopped??J.length} stopped`,tone:"ok"}),t(Af,{label:"Images",value:A.images??F.length,hint:`${A.daemonImages??A.images??F.length} daemon images`}),t(Af,{label:"Volumes",value:A.volumes??U.length,hint:$?Q?"database volume visible":"database volume missing":"node local volumes",tone:Q?"ok":""}),t(Af,{label:"Networks",value:A.networks??L.length,hint:c.driver?`driver ${c.driver}`:"docker networks"})),$?t(Tp,{volume:Q,volumeCount:U.length}):null,t("div",{className:"docker-section-head"},t("h3",null,"Containers"),t("span",null,`updated ${Nu(y.dockerUpdatedAt||_.collectedAt)}`)),t("div",{className:"docker-container-table table-wrap","data-testid":"docker-container-table"},t("table",null,t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"容器"),t("th",null,"镜像"),t("th",null,"端口"),t("th",null,"运行时间"),t("th",null,"重启策略"),t("th",null,"PID"),t("th",null,"大小"))),t("tbody",null,j.length===0?t("tr",null,t("td",{colSpan:8},"暂无容器")):j.map((N)=>t("tr",{key:`${N.id}-${N.name}`},t("td",null,t(Lf,{status:Kp(N.state)},N.state||"unknown")),t("td",null,t("strong",null,N.name||"--"),t("code",null,N.id||"--")),t("td",null,N.image||"--"),t("td",null,N.ports||t("span",{className:"muted"},"未发布")),t("td",null,N.runningFor||N.status||"--"),t("td",null,N.restartPolicy?t(Lf,{status:N.restartPolicy==="always"?"online":"warn"},N.restartPolicy):"--"),t("td",null,N.pidMode?t("code",null,N.pidMode):"--"),t("td",null,N.size||"--")))))))),t("div",{className:"docker-side-stack"},t(a9,{title:"Images",items:F,render:(N)=>t("article",{key:`${N.id}-${N.repository}`,className:"docker-side-row"},t("strong",null,`${N.repository}:${N.tag}`),t("span",null,N.size||"--"),t("code",null,N.id||"--"))}),t(a9,{title:"Volumes",items:U,limit:U.length,render:(N)=>t("article",{key:N.name,className:`docker-side-row volume-row ${$&&M$(N)?"database-volume":""}`,"data-testid":$&&M$(N)?"database-volume-row":void 0},t("strong",null,N.name),t("span",null,$&&M$(N)?"PostgreSQL":ww(String(N.name||""))?"anonymous":"named"),t("code",null,N.mountpoint||N.driver||N.scope||"--"))}),t(a9,{title:"Networks",items:L,render:(N)=>t("article",{key:N.id||N.name,className:"docker-side-row"},t("strong",null,N.name),t("span",null,N.driver||"--"),t("code",null,N.id||"--"))}))))}function Tp({volume:u,volumeCount:f}){return t("section",{className:`docker-volume-focus ${u?"ready":"missing"}`,"data-testid":"database-volume-card"},t("div",{className:"volume-focus-head"},t("span",{className:"panel-eyebrow"},"Database Named Volume"),t(Lf,{status:u?"online":"warn"},u?"FOUND":"MISSING")),u?t("div",{className:"volume-focus-body"},t("strong",null,u.name),t("span",null,"PostgreSQL data volume for unidesk-database"),t("div",{className:"volume-route"},t("code",null,u.mountpoint||"/var/lib/docker/volumes/unidesk_pgdata_10gb/_data"),t("span",null,"->"),t("code",null,"unidesk-database:/var/lib/postgresql/data")),t("div",{className:"docker-meta compact"},t("span",null,`driver ${u.driver||"--"}`),t("span",null,`scope ${u.scope||"--"}`),t("span",null,`${f} volumes reported`))):t("div",{className:"volume-focus-body"},t("strong",null,"unidesk_pgdata_10gb"),t("span",null,"当前 Docker 快照没有发现数据库命名卷;请检查 provider-gateway 的 Docker volume 上报。")))}function a9({title:u,items:f,render:l,limit:r}){let n=f.slice(0,r??12),i=Math.max(0,f.length-n.length);return t(ou,{title:u,eyebrow:`${f.length} items`,className:"docker-side-panel"},f.length===0?t(jf,{title:`暂无 ${u}`,text:"等待 Docker 状态采集"}):t("div",{className:"docker-side-list"},n.map(l),i>0?t("div",{className:"docker-side-more"},`+ ${i} more`):null))}function Ep({microservices:u,onRaw:f,onNavigate:l}){let r=u.filter((n)=>dL(n).public===!1);return t("div",{className:"microservice-page","data-testid":"microservice-catalog-page"},t(ou,{title:"用户服务目录",eyebrow:"Provider Mounted User Services"},t("div",{className:"metric-grid"},t(Af,{label:"服务总数",value:u.length,hint:"config.json 用户服务登记"}),t(Af,{label:"私有后端",value:r.length,hint:"不直接暴露公网",tone:"ok"}),t(Af,{label:"D601 服务",value:u.filter((n)=>n.providerId==="D601").length,hint:"compute-node docker"}),t(Af,{label:"集成前端",value:u.filter((n)=>n.frontend?.integrated).length,hint:"UniDesk React 页面"}))),t(ou,{title:"服务映射",eyebrow:"Repo Reference + Runtime"},u.length===0?t(jf,{title:"暂无用户服务",text:"在 config.json 的 microservices 中登记用户服务的 provider、仓库引用和后端映射"}):t("div",{className:"table-wrap"},t("table",{className:"microservice-table"},t("thead",null,t("tr",null,t("th",null,"服务"),t("th",null,"Provider"),t("th",null,"代码引用"),t("th",null,"Docker 引用"),t("th",null,"后端映射"),t("th",null,"开发入口"),t("th",null,"运行态"),t("th",null,"操作"))),t("tbody",null,u.map((n)=>{let i=qw(n),y=aS(n),_=dL(n),$=i.availability||{},A=$.status||(i.providerStatus==="online"?"unknown":"unhealthy");return t("tr",{key:n.id,"data-testid":`microservice-row-${dl(n.id)}`},t("td",null,t("strong",null,n.name),t("code",null,n.id)),t("td",null,t("strong",null,i.providerName||n.providerId),t("code",null,n.providerId)),t("td",null,t("span",null,y.url||"--"),t("code",null,y.commitId||"--")),t("td",null,t("span",null,y.composeFile||"--"),t("code",null,`${y.composeService||"--"} / ${y.containerName||"--"}`)),t("td",null,t(Lf,{status:_.public?"warn":"online"},_.public?"public":"private"),t("code",null,`${_.nodeBindHost||"--"}:${_.nodePort||"--"} -> ${_.proxyMode||"--"}`)),t("td",null,t("span",null,n.development?.sshPassthrough?"SSH 透传":"未配置"),t("code",null,n.development?.worktreePath||"--")),t("td",null,t(Lf,{status:A==="healthy"?"online":A==="unknown"?"warn":"failed"},A),t("span",null,$.reason||i.providerStatus||"unknown"),t(gn,{data:i.container,empty:"容器快照未上报"})),t("td",null,t("div",{className:"microservice-actions"},n.id==="findjob"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","findjob"),"data-testid":"open-findjob-button"},"打开"):null,n.id==="pipeline"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","pipeline"),"data-testid":"open-pipeline-button"},"打开"):null,n.id==="todo-note"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","todo-note"),"data-testid":"open-todo-note-button"},"打开"):null,n.id==="met-nonlinear"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","met-nonlinear"),"data-testid":"open-met-nonlinear-button"},"打开"):null,n.id==="claudeqq"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","claudeqq"),"data-testid":"open-claudeqq-button"},"打开"):null,n.id==="baidu-netdisk"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","baidu-netdisk"),"data-testid":"open-baidu-netdisk-button"},"打开"):null,n.id==="oa-event-flow"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","oa-event-flow"),"data-testid":"open-oa-event-flow-button"},"打开"):null,n.id==="code-queue"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","code-queue"),"data-testid":"open-code-queue-button"},"打开"):null,n.id==="project-manager"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","project-manager"),"data-testid":"open-project-manager-button"},"打开"):null,t(bf,{title:`用户服务 ${n.id}`,data:n,onOpen:f}))))}))))))}function Zp({nodes:u,onDispatched:f,onRaw:l}){let r=u.filter((V)=>V.status==="online"),[n,i]=hu(r[0]?.providerId||u[0]?.providerId||""),[y,_]=hu("docker.ps"),[$,A]=hu("frontend"),[c,j]=hu("operator-check"),[F,U]=hu("normal"),[Q,L]=hu(!1),[w,J]=hu(""),[N,q]=hu(!1),[W,z]=hu(null),[Z,H]=hu("");J0(()=>{if(!n&&(r[0]?.providerId||u[0]?.providerId))i(r[0]?.providerId||u[0].providerId)},[u.length,r.length,n]);function E(){return{source:$,note:c,priority:F}}function D(){J(JSON.stringify(E(),null,2)),L(!0)}async function h(V){V.preventDefault(),q(!0),H("");try{let Y=Q?JSON.parse(w||"{}"):E(),p=await Eu(`${su.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:n,command:y,payload:Y})});z(p),await f()}catch(Y){H(Zu(Y,"下发失败"))}finally{q(!1)}}return t("div",{className:"page-grid dispatch-grid"},t(ou,{title:"下发任务",eyebrow:"Real WebSocket Dispatch"},t("form",{className:"dispatch-form",onSubmit:h},t("label",null,"Provider",t("select",{value:n,onChange:(V)=>i(V.target.value)},u.map((V)=>t("option",{key:V.providerId,value:V.providerId},`${V.name} / ${V.providerId}`)))),t("label",null,"Command",t("select",{value:y,onChange:(V)=>_(V.target.value)},t("option",{value:"docker.ps"},"docker.ps"),t("option",{value:"host.ssh"},"host.ssh"),t("option",{value:"microservice.http"},"microservice.http"),t("option",{value:"echo"},"echo"))),t("label",null,"来源",t("input",{value:$,onChange:(V)=>A(V.target.value)})),t("label",null,"备注",t("input",{value:c,onChange:(V)=>j(V.target.value)})),t("label",null,"优先级",t("select",{value:F,onChange:(V)=>U(V.target.value)},t("option",{value:"normal"},"normal"),t("option",{value:"low"},"low"),t("option",{value:"urgent"},"urgent"))),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",onClick:D},"查看原始JSON"),t("button",{type:"submit",disabled:N||!n},N?"下发中":"下发任务")),Q?t("label",{className:"raw-editor-label"},"高级 Payload",t("textarea",{className:"raw-editor",value:w,onChange:(V)=>J(V.target.value)})):null,t(yf,{error:Z,wide:!0}))),t(ou,{title:"下发结果",eyebrow:"Response"},W?t("div",{className:"result-card"},t(Lf,{status:W.status||"queued"},W.status||"queued"),t("dl",null,t("dt",null,"Task ID"),t("dd",null,t("code",null,W.taskId||"--")),t("dt",null,"Provider 在线"),t("dd",null,x1(W.providerOnline))),t(bf,{title:"Dispatch Response",data:W,onOpen:l})):t(jf,{title:"等待操作",text:"任务响应会以结构化结果卡展示"})))}function rw({task:u,onRaw:f}){return t("article",{className:"compact-row"},t(Lf,{status:u.status}),t("div",null,t("strong",null,u.command),t("code",null,u.id)),t("span",null,Wy(u)?`已等待 ${d9(u.updatedAt)}`:`耗时 ${h0(_w(u)??0)}`),t(bf,{title:`Task ${u.id}`,data:x$(u),onOpen:f}))}function Kw({task:u}){let f=_w(u),l=Wy(u);return t("div",{className:"task-duration"},t("strong",null,f===null?"--":h0(f)),t("span",null,l?`已运行 / 创建 ${Nu(u.createdAt)}`:`创建 ${Nu(u.createdAt)}`))}function Op({task:u}){let f=String(u?.status||"").toLowerCase(),l=u?.result,r=l&&typeof l==="object"&&!Array.isArray(l)?l:{},i=["exitCode","code","signal","timeoutMs","previousStatus","mode"].filter((y)=>r[y]!==void 0&&r[y]!==null);if(f==="failed"){let y=$w(u);return t("div",{className:"task-diagnostic failed"},t("b",null,"失败原因"),t("span",{className:"diagnostic-reason"},x1(y)),i.length>0?t("div",{className:"diagnostic-meta"},i.map((_)=>t("span",{key:_,className:"data-chip"},t("b",null,_),t("span",null,x1(r[_]))))):null)}if(Wy(u))return t("div",{className:"task-diagnostic warn"},t("b",null,"等待终态"),t("span",null,`最后更新 ${d9(u.updatedAt)} 前`));return t("div",{className:"task-diagnostic ok"},t("b",null,"完成摘要"),t(gn,{data:l,empty:"无执行输出"}))}function Hp({tasks:u,onRaw:f}){let l=u.filter(Wy);return t("div",{"data-testid":"pending-task-page"},t(ou,{title:"待处理任务",eyebrow:`${l.length} Pending`},l.length===0?t(jf,{title:"当前无待处理任务",text:"queued / dispatched / running 会在超时后自动转为 failed;历史记录仍可在任务历史中查看"}):t("div",{className:"table-wrap","data-testid":"pending-task-table"},t("table",null,t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"Provider"),t("th",null,"已等待"),t("th",null,"载荷摘要"),t("th",null,"操作"))),t("tbody",null,l.map((r)=>t("tr",{key:r.id},t("td",null,t(Lf,{status:r.status})),t("td",null,t("strong",null,r.command),t("code",null,r.id)),t("td",null,t("code",null,r.providerId)),t("td",null,d9(r.updatedAt)),t("td",null,t(gn,{data:r.payload})),t("td",null,t(bf,{title:`Pending Task ${r.id}`,data:x$(r),onOpen:f})))))))))}function Bp({tasks:u,onRaw:f}){return t("div",{"data-testid":"task-history-page"},t(ou,{title:"任务历史",eyebrow:`${u.length} Tasks`},u.length===0?t(jf,{title:"暂无任务",text:"下发任务后会在这里看到生命周期"}):t("div",{className:"table-wrap"},t("table",{className:"task-history-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"Provider"),t("th",null,"任务耗时"),t("th",null,"载荷摘要"),t("th",null,"诊断信息"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.id,"data-testid":`task-row-${dl(l.id)}`},t("td",null,t(Lf,{status:l.status})),t("td",null,t("strong",null,l.command),t("code",null,l.id)),t("td",null,t("code",null,l.providerId)),t("td",null,t(Kw,{task:l})),t("td",null,t(gn,{data:l.payload})),t("td",null,t(Op,{task:l})),t("td",null,Nu(l.updatedAt)),t("td",null,t(bf,{title:`Task ${l.id}`,data:x$(l),onOpen:f})))))))))}function Vp({tasks:u,onRaw:f}){let l=u.filter((r)=>["succeeded","failed"].includes(r.status));return t(ou,{title:"执行结果",eyebrow:"Finished Tasks"},l.length===0?t(jf,{title:"暂无结果",text:"任务完成后展示 provider 返回的结构化摘要"}):t("div",{className:"result-grid"},l.map((r)=>t("article",{key:r.id,className:"result-card"},t("div",{className:"node-card-head"},t("strong",null,r.command),t(Lf,{status:r.status})),t("code",null,r.id),t(gn,{data:r.result,empty:"无执行输出"}),t(bf,{title:`Task Result ${r.id}`,data:x$(r),onOpen:f})))))}function Dp(u){if(!u||typeof u!=="object")return"--";if(u.type==="interval")return`每 ${h0(Number(u.everySeconds||0))}`;return`每天 ${u.timeOfDay||"03:00"} UTC`}function Xp(u){if(!u||typeof u!=="object")return"--";if(u.type==="pgdata_backup")return`PGDATA -> ${u.remoteBaseDir||"/SERVER_DATA/UNIDESK_PG_DATA"}`;if(u.type==="dispatch")return`${u.providerId||"--"} / ${u.command||"--"}`;return String(u.type||"--")}function Yp(u){let f=String(u||"").toLowerCase();if(f==="succeeded")return"online";if(f==="failed")return"failed";if(f==="running"||f==="queued")return"warn";return f}function Sp(u){let f=Number(u?.durationMs);if(Number.isFinite(f)&&f>=0)return h0(f/1000);let l=U0(u?.startedAt||u?.createdAt);if(l===null)return"--";let n=U0(u?.finishedAt)??Date.now();return h0(Math.max(0,(n-l)/1000))}function nw(u){return{id:"unidesk-pgdata-baidu-daily",name:"PGDATA daily Baidu Netdisk backup",description:"Daily PostgreSQL physical base backup uploaded to Baidu Netdisk /SERVER_DATA with monthly rotation.",enabled:!0,timeOfDay:"03:30",actionType:"pgdata_backup",providerId:u[0]?.providerId||"main-server",command:"echo",payloadJson:JSON.stringify({source:"scheduled-task",message:"hello from scheduler"},null,2),remoteBaseDir:"/SERVER_DATA/UNIDESK_PG_DATA",stagingSubdir:"server-data/unidesk-pg-data",timeoutMs:"3600000"}}function pp({schedules:u,scheduleRuns:f,nodes:l,refresh:r,onRaw:n}){let[i,y]=hu(nw(l||[])),[_,$]=hu(!1),[A,c]=hu(""),[j,F]=hu(""),U=[...f||[]].sort((W,z)=>(U0(z.updatedAt)??0)-(U0(W.updatedAt)??0));function Q(W,z){y((Z)=>({...Z,[W]:z}))}function L(W){let z=W?.action||{};y({id:W?.id||"",name:W?.name||"",description:W?.description||"",enabled:W?.enabled!==!1,timeOfDay:W?.schedule?.timeOfDay||"03:30",actionType:z.type||"dispatch",providerId:z.providerId||l[0]?.providerId||"main-server",command:z.command||"echo",payloadJson:JSON.stringify(z.payload||{source:"scheduled-task"},null,2),remoteBaseDir:z.remoteBaseDir||"/SERVER_DATA/UNIDESK_PG_DATA",stagingSubdir:z.stagingSubdir||"server-data/unidesk-pg-data",timeoutMs:String(z.timeoutMs||3600000)}),F(`正在编辑 ${W?.id||""}`)}function w(){let W={id:i.id,name:i.name,description:i.description,enabled:i.enabled,concurrencyPolicy:"skip",schedule:{type:"daily",timeOfDay:i.timeOfDay,timezone:"Etc/UTC"}};if(i.actionType==="pgdata_backup")return{...W,action:{type:"pgdata_backup",volumeName:"unidesk_pgdata_10gb",remoteBaseDir:i.remoteBaseDir,stagingSubdir:i.stagingSubdir,timeoutMs:Number(i.timeoutMs)||3600000,cleanupLocal:!0}};return{...W,action:{type:"dispatch",providerId:i.providerId,command:i.command,payload:JSON.parse(i.payloadJson||"{}"),timeoutMs:Number(i.timeoutMs)||600000}}}async function J(W){W.preventDefault(),$(!0),c(""),F("");try{let z=w(),Z=encodeURIComponent(String(z.id));await Eu(`${su.apiBaseUrl}/schedules/${Z}`,{method:"PUT",body:JSON.stringify(z)}),F("定时任务已保存"),await r()}catch(z){c(Zu(z,"保存定时任务失败"))}finally{$(!1)}}async function N(W){if(!W?.id)return;$(!0),c(""),F("");try{await Eu(`${su.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}`,{method:"DELETE"}),F(`已删除 ${W.id}`),await r()}catch(z){c(Zu(z,"删除定时任务失败"))}finally{$(!1)}}async function q(W){if(!W?.id)return;$(!0),c(""),F("");try{let z=await Eu(`${su.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}/run`,{method:"POST",body:"{}"});F(`已触发 ${W.id} / ${z?.run?.id||"run"}`),await r()}catch(z){c(Zu(z,"触发定时任务失败"))}finally{$(!1)}}return t("div",{className:"page-grid scheduled-task-page","data-testid":"scheduled-task-page"},t(ou,{title:"定时任务",eyebrow:`${(u||[]).length} Schedules`},(u||[]).length===0?t(jf,{title:"暂无定时任务",text:"创建 daily / dispatch / PGDATA backup 任务后会在这里展示下一次执行时间和最近结果"}):t("div",{className:"schedule-card-grid"},(u||[]).map((W)=>t("article",{key:W.id,className:"schedule-card","data-testid":`schedule-row-${dl(W.id)}`},t("div",{className:"node-card-head"},t("strong",null,W.name||W.id),t(Lf,{status:W.enabled?"online":"warn"},W.enabled?"enabled":"disabled")),t("code",null,W.id),t("dl",null,t("dt",null,"计划"),t("dd",null,Dp(W.schedule)),t("dt",null,"动作"),t("dd",null,Xp(W.action)),t("dt",null,"下次执行"),t("dd",null,Nu(W.nextRunAt)),t("dt",null,"最近执行"),t("dd",null,W.lastRunAt?`${Nu(W.lastRunAt)} / ${W.lastRunId||"--"}`:"--")),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>L(W)},"编辑"),t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>q(W),"data-testid":`schedule-run-${dl(W.id)}`},"手动触发"),t("button",{type:"button",className:"ghost-btn danger",disabled:_,onClick:()=>N(W)},"删除"),t(bf,{title:`Schedule ${W.id}`,data:W,onOpen:n})))))),t(ou,{title:i.id?"配置定时任务":"新建定时任务",eyebrow:"CRUD"},t("form",{className:"dispatch-form schedule-form",onSubmit:J},t("label",null,"ID",t("input",{value:i.id,onChange:(W)=>Q("id",W.target.value)})),t("label",null,"名称",t("input",{value:i.name,onChange:(W)=>Q("name",W.target.value)})),t("label",null,"每日执行时间 UTC",t("input",{value:i.timeOfDay,placeholder:"03:30",onChange:(W)=>Q("timeOfDay",W.target.value)})),t("label",null,"启用",t("select",{value:i.enabled?"true":"false",onChange:(W)=>Q("enabled",W.target.value==="true")},t("option",{value:"true"},"enabled"),t("option",{value:"false"},"disabled"))),t("label",null,"动作类型",t("select",{value:i.actionType,onChange:(W)=>Q("actionType",W.target.value)},t("option",{value:"pgdata_backup"},"PGDATA 备份到百度网盘"),t("option",{value:"dispatch"},"Provider Dispatch"))),i.actionType==="pgdata_backup"?[t("label",{key:"remote"},"网盘根目录",t("input",{value:i.remoteBaseDir,onChange:(W)=>Q("remoteBaseDir",W.target.value)})),t("label",{key:"staging"},"本地 staging 子目录",t("input",{value:i.stagingSubdir,onChange:(W)=>Q("stagingSubdir",W.target.value)}))]:[t("label",{key:"provider"},"Provider",t("select",{value:i.providerId,onChange:(W)=>Q("providerId",W.target.value)},(l||[]).map((W)=>t("option",{key:W.providerId,value:W.providerId},`${W.name} / ${W.providerId}`)))),t("label",{key:"command"},"Command",t("select",{value:i.command,onChange:(W)=>Q("command",W.target.value)},t("option",{value:"echo"},"echo"),t("option",{value:"docker.ps"},"docker.ps"),t("option",{value:"host.ssh"},"host.ssh"),t("option",{value:"microservice.http"},"microservice.http"))),t("label",{key:"payload",className:"raw-editor-label"},"Payload JSON",t("textarea",{className:"raw-editor",value:i.payloadJson,onChange:(W)=>Q("payloadJson",W.target.value)}))],t("label",null,"超时 ms",t("input",{value:i.timeoutMs,onChange:(W)=>Q("timeoutMs",W.target.value)})),t("label",{className:"raw-editor-label"},"描述",t("textarea",{className:"raw-editor compact",value:i.description,onChange:(W)=>Q("description",W.target.value)})),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>y(nw(l||[]))},"重置"),t("button",{type:"submit",disabled:_||!i.id},_?"保存中":"保存任务")),j?t("p",{className:"muted paragraph"},j):null,t(yf,{error:A,wide:!0}))),t(ou,{title:"历史执行记录",eyebrow:`${U.length} Runs`},U.length===0?t(jf,{title:"暂无执行记录",text:"定时触发或手动触发后会生成 run history"}):t("div",{className:"table-wrap"},t("table",{className:"task-history-table schedule-run-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"触发"),t("th",null,"耗时"),t("th",null,"结果摘要"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,U.map((W)=>t("tr",{key:W.id,"data-testid":`schedule-run-row-${dl(W.id)}`},t("td",null,t(Lf,{status:Yp(W.status)},W.status)),t("td",null,t("strong",null,W.scheduleId),t("code",null,W.id),W.taskId?t("code",null,W.taskId):null),t("td",null,W.trigger||"--"),t("td",null,Sp(W)),t("td",null,t(gn,{data:W.result||W.error,empty:"无结果"})),t("td",null,Nu(W.updatedAt)),t("td",null,t(bf,{title:`Schedule Run ${W.id}`,data:W,onOpen:n})))))))))}function mp({data:u}){let f=u.overview||{};return t("div",{className:"page-grid topology-grid"},t(ou,{title:"公开入口",eyebrow:"Public"},t("div",{className:"endpoint-list"},t("article",null,t("b",null,"Frontend"),t("span",null,su.frontendPublicUrl||window.location.origin),t(Lf,{status:"online"},"public")),t("article",null,t("b",null,"Provider Ingress"),t("span",null,su.providerIngressPublicUrl||"ws://public/ws/provider"),t(Lf,{status:"online"},"public")))),t(ou,{title:"内部服务",eyebrow:"Docker Network Only"},t("div",{className:"endpoint-list"},t("article",null,t("b",null,"backend-core API"),t("span",null,"http://backend-core:8080"),t(Lf,{status:"internal"},"internal")),t("article",null,t("b",null,"database"),t("span",null,"postgres://database:5432/unidesk"),t(Lf,{status:"internal"},"internal")))),t(ou,{title:"运行态",eyebrow:"Runtime"},t("div",{className:"metric-grid"},t(Af,{label:"DB Ready",value:f.dbReady?"YES":"NO",hint:"internal health"}),t(Af,{label:"Online Nodes",value:f.onlineNodeCount??0,hint:"provider-gateway self-link"}))))}function Pp({session:u}){return t(ou,{title:"认证策略",eyebrow:"Frontend Login"},t("div",{className:"policy-grid"},t("article",null,t("span",null,"默认账号"),t("strong",null,su.authUsername||"admin")),t("article",null,t("span",null,"当前会话"),t("strong",null,u?.user?.username||"--")),t("article",null,t("span",null,"Session TTL"),t("strong",null,`${su.sessionTtlSeconds||0}s`)),t("article",null,t("span",null,"API 访问"),t("strong",null,"同源 Cookie 保护"))),t("p",{className:"muted paragraph"},"浏览器只访问 frontend 同源接口;frontend 容器使用 Docker 内网代理 backend-core API。"))}function Mp(){return t(ou,{title:"安全边界",eyebrow:"Exposure Rule"},t("div",{className:"security-board"},t("article",{className:"allow"},t("b",null,"允许公网"),t("span",null,"frontend 登录入口"),t("span",null,"provider ingress WebSocket/health")),t("article",{className:"deny"},t("b",null,"禁止公网"),t("span",null,"backend-core REST API"),t("span",null,"PostgreSQL database")),t("article",null,t("b",null,"数据库卷"),t("span",null,"named volume unidesk_pgdata_10gb"),t("span",null,"CLI stop/start 不删除数据卷"))))}function Cp({activeModule:u,activeTab:f,data:l,session:r,refresh:n,onRaw:i,onNavigate:y}){if(u==="ops"&&f==="status")return t(rp,{data:l,onRaw:i,onNavigate:y});if(u==="ops"&&f==="performance")return t(Np,{onRaw:i});if(u==="ops"&&f==="events")return t(ip,{events:l.events,onRaw:i});if(u==="ops"&&f==="logs")return t(yp,{logs:l.logs,onRaw:i});if(u==="nodes"&&f==="list")return t(_p,{nodes:l.nodes,onRaw:i});if(u==="nodes"&&f==="monitor")return t(Ap,{nodes:l.nodes,systemStatuses:l.systemStatuses,tasks:l.tasks,onRaw:i,refresh:n});if(u==="nodes"&&f==="docker")return t(zp,{nodes:l.nodes,dockerStatuses:l.dockerStatuses,onRaw:i});if(u==="nodes"&&f==="gateway")return t(wp,{nodes:l.nodes,tasks:l.tasks,onRaw:i});if(u==="nodes"&&f==="labels")return t($p,{nodes:l.nodes});if(u==="nodes"&&f==="heartbeats")return t(tp,{nodes:l.nodes});if(u==="tasks"&&f==="dispatch")return t(Zp,{nodes:l.nodes,onDispatched:n,onRaw:i});if(u==="tasks"&&f==="scheduled")return t(pp,{schedules:l.schedules,scheduleRuns:l.scheduleRuns,nodes:l.nodes,refresh:n,onRaw:i});if(u==="tasks"&&f==="pending")return t(Hp,{tasks:l.pendingTasks,onRaw:i});if(u==="tasks"&&f==="history")return t(Bp,{tasks:l.tasks,onRaw:i});if(u==="tasks"&&f==="results")return t(Vp,{tasks:l.tasks,onRaw:i});if(u==="apps"&&f==="catalog")return t(Ep,{microservices:l.microservices,onRaw:i,onNavigate:y});if(u==="apps"&&f==="todo-note")return t(hL,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl});if(u==="apps"&&f==="findjob")return t(pQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl});if(u==="apps"&&f==="pipeline")return t(SL,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl});if(u==="apps"&&f==="met-nonlinear")return t(RQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl});if(u==="apps"&&f==="claudeqq")return t(cU,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl});if(u==="apps"&&f==="baidu-netdisk")return t($U,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl});if(u==="apps"&&f==="filebrowser")return t(SQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl});if(u==="apps"&&f==="oa-event-flow")return t(gQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl});if(u==="apps"&&f==="code-queue")return t(HQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl,initialTasksData:MS});if(u==="apps"&&f==="project-manager")return t(PL,{microservices:l.microservices,onRaw:i,apiBaseUrl:su.apiBaseUrl});if(u==="config"&&f==="topology")return t(mp,{data:l});if(u==="config"&&f==="auth")return t(Pp,{session:r});if(u==="config"&&f==="security")return t(Mp);return t(jf,{title:"未找到页面",text:"请选择左侧主模块和顶部子功能标签"})}function Rp({session:u,onLogout:f}){let l=$A(Vr,window.location.pathname),[r,n]=hu(l.moduleId),[i,y]=hu({...I_,[l.moduleId]:l.tabId}),[_,$]=hu({overview:null,nodes:[],systemStatuses:[],dockerStatuses:[],microservices:[],events:[],tasks:[],pendingTasks:[],schedules:[],scheduleRuns:[],logs:[]}),[A,c]=hu({ok:!1,text:"连接中"}),[j,F]=hu(null),[U,Q]=hu(new Date),[L,w]=hu(null),[J,N]=hu(!1),[q,W]=hu(!1),z=In.default.useRef(!1),Z=Vr.moduleById[r]||Vr.modules[0],H=i[r]||I_[r]||Z.tabs[0].id,E=Array.isArray(_.microservices)?_.microservices:[],D=E.length===0&&r==="apps"&&H==="code-queue"?[CS]:E,h=D===E?_:{..._,microservices:D},V=r==="apps"?D.find((o)=>String(o?.id||"")===H):null,Y=V?qw(V):{},p=Z.tabs.find((o)=>o.id===H)?.label||H,O=V?[{key:"microservice",label:"用户服务",value:`${p} ${Y.providerStatus==="online"?"在线":Y.providerStatus||"未知"}`,tone:Y.providerStatus==="online"?"ok":"warn",testId:"active-microservice-status"}]:[];async function m(){if(z.current)return;z.current=!0,W(!0);try{let o=[],g=(ju,Gu)=>{o.push([ju,Eu(Gu)])},x=r==="ops"&&H==="status",fu=x||r==="config"&&H==="topology",$u=x||r==="nodes"||r==="tasks"&&(H==="dispatch"||H==="scheduled"),tu=r==="apps"&&H!=="code-queue";if(fu)g("overview",`${su.apiBaseUrl}/overview`);if($u)g("nodes",`${su.apiBaseUrl}/nodes`);if(r==="nodes"&&H==="monitor")g("systemStatuses",`${su.apiBaseUrl}/nodes/system-status?limit=60`),g("tasks",`${su.apiBaseUrl}/tasks?limit=120&summary=1`);else if(r==="nodes"&&H==="docker")g("dockerStatuses",`${su.apiBaseUrl}/nodes/docker-status`);else if(r==="nodes"&&H==="gateway")g("tasks",`${su.apiBaseUrl}/tasks?limit=300&summary=1`);else if(r==="tasks"&&H==="scheduled")g("schedules",`${su.apiBaseUrl}/schedules?limit=100`),g("scheduleRuns",`${su.apiBaseUrl}/schedules/runs?limit=100`);else if(r==="tasks"&&H==="pending")g("pendingTasks",`${su.apiBaseUrl}/tasks?status=pending&limit=100&summary=1`);else if(r==="tasks"&&(H==="history"||H==="results"))g("tasks",`${su.apiBaseUrl}/tasks?limit=300&summary=1`);else if(x)g("tasks",`${su.apiBaseUrl}/tasks?limit=8&lite=1`),g("pendingTasks",`${su.apiBaseUrl}/tasks?status=pending&limit=20&lite=1`);if(tu)g("microservices",`${su.apiBaseUrl}/microservices`);if(r==="ops"&&H==="events")g("events",`${su.apiBaseUrl}/events?limit=100`);if(r==="ops"&&H==="logs")g("logs","/logs?limit=100");await Promise.all(o.map(async([ju,Gu])=>{let qu=await Gu,P={};if(ju==="overview")P.overview=qu;if(ju==="nodes")P.nodes=qu.nodes||[];if(ju==="systemStatuses")P.systemStatuses=qu.systemStatuses||[];if(ju==="dockerStatuses")P.dockerStatuses=qu.dockerStatuses||[];if(ju==="microservices")P.microservices=qu.microservices||[];if(ju==="events")P.events=qu.events||[];if(ju==="tasks")P.tasks=qu.tasks||[];if(ju==="pendingTasks")P.pendingTasks=qu.tasks||[];if(ju==="schedules")P.schedules=qu.schedules||[];if(ju==="scheduleRuns")P.scheduleRuns=qu.runs||[];if(ju==="logs")P.logs=qu.logs||[];$((e)=>({...e,...P}))})),c({ok:!0,text:"核心在线"}),F(new Date)}catch(o){if(c({ok:!1,text:Zu(o,"连接失败")}),o.status===401)f(!1)}finally{z.current=!1,W(!1)}}J0(()=>{let o=()=>{if(!sL())return;m()};o();let g=setInterval(o,RS(r,H)),x=()=>{if(sL())o()};return document.addEventListener("visibilitychange",x),()=>{clearInterval(g),document.removeEventListener("visibilitychange",x)}},[r,H]),J0(()=>{let o=setInterval(()=>Q(new Date),1000);return()=>clearInterval(o)},[]),J0(()=>{let o=vQ(Vr,window.location.pathname);if(o&&window.location.pathname!==o)window.history.replaceState(null,"",o)},[]),J0(()=>{let o=()=>{let g=$A(Vr,window.location.pathname);n(g.moduleId),y((x)=>({...x,[g.moduleId]:g.tabId})),w(null)};return window.addEventListener("popstate",o),()=>window.removeEventListener("popstate",o)},[]),J0(()=>{window.scrollTo({top:0,left:0,behavior:"auto"})},[r,H]);function X(o,g,x="push"){let fu=Vr.moduleById[o]?o:Vr.fallbackTarget.moduleId,$u=Vr.moduleById[fu]?.tabs.some((ju)=>ju.id===g)?g:I_[fu]||Vr.moduleById[fu]?.tabs[0]?.id||Vr.fallbackTarget.tabId;n(fu),y((ju)=>({...ju,[fu]:$u}));let tu=r6(Vr,fu,$u);if(window.location.pathname!==tu){let ju=x==="replace"?"replaceState":"pushState";window.history[ju](null,"",tu)}}function v(o,g){w({title:o,data:g})}let[T,S]=hu(!1),{unreadCount:k,notifications:I}=Dl(),b=I.length>0?I[I.length-1]:null;return t("div",{className:`shell ${J?"rail-collapsed":""}`,"data-testid":"app-shell"},t(fp,{activeModule:r,activeTabs:i,onNavigate:X,collapsed:J,onToggle:()=>N((o)=>!o)}),t("main",{className:"workspace"},t(eS,{connection:A,lastRefresh:j,onRefresh:m,onLogout:()=>f(!0),session:u,clock:U,activeStatusItems:O,onNotificationToggle:()=>S((o)=>!o),unreadCount:k}),t(lp,{module:Z,activeTab:H,onNavigate:X}),t(o9.Provider,{value:q},t(Cp,{activeModule:r,activeTab:H,data:h,session:u,refresh:m,onRaw:v,onNavigate:X}))),t(oS,{raw:L,onClose:()=>w(null)}),b&&t(gL,{key:b.id,notification:b}),T&&t(IL,{onClose:()=>S(!1)}))}function xp(){let[u,f]=hu(!0),[l,r]=hu(null);async function n(){f(!0);try{let y=await Eu("/api/session");r(y.authenticated?y:null)}catch{r(null)}finally{f(!1)}}async function i(y){if(y)try{await Eu("/logout",{method:"POST"})}catch{}r(null)}if(J0(()=>{n()},[]),u)return t("main",{className:"loading-screen"},t("div",{className:"brand-mark"},"UD"),t("span",null,"加载会话"));if(!l)return t(dS,{onLogin:r});return t(_U,null,t(Rp,{session:l,onLogout:i}))}var Gw=document.getElementById("root");if(Gw===null)throw Error("root element not found");iw.createRoot(Gw).render(t(xp));})(); diff --git a/src/components/frontend/src/app.tsx b/src/components/frontend/src/app.tsx index 034de763..1e11ae39 100644 --- a/src/components/frontend/src/app.tsx +++ b/src/components/frontend/src/app.tsx @@ -42,18 +42,18 @@ const ROUTE_REGISTRY = createRouteRegistry(MODULES); const fastCodeQueueService = { id: "code-queue", name: "Code Queue", - providerId: "main-server", + providerId: "D601", description: "Code Queue", repository: { containerName: "code-queue-backend" }, backend: { - nodeBaseUrl: "http://code-queue:4222", - nodeBindHost: "code-queue", + nodeBaseUrl: "http://host.docker.internal:4222", + nodeBindHost: "127.0.0.1", nodePort: 4222, public: false, }, runtime: { providerStatus: "loading", - providerName: "main-server", + providerName: "D601", }, }; diff --git a/src/components/frontend/src/code-queue-entry.tsx b/src/components/frontend/src/code-queue-entry.tsx index 2acff0ee..20bb2965 100644 --- a/src/components/frontend/src/code-queue-entry.tsx +++ b/src/components/frontend/src/code-queue-entry.tsx @@ -29,18 +29,18 @@ const apiBaseUrl = String(clientConfig.apiBaseUrl || "/api"); const standaloneCodeQueueService = { id: "code-queue", name: "Code Queue", - providerId: "main-server", + providerId: "D601", description: "Code Queue 独立入口,使用 summary 首屏和按需全量加载保持信息完整。", repository: { containerName: "code-queue-backend" }, backend: { - nodeBaseUrl: "http://code-queue:4222", - nodeBindHost: "code-queue", + nodeBaseUrl: "http://host.docker.internal:4222", + nodeBindHost: "127.0.0.1", nodePort: 4222, public: false, }, runtime: { providerStatus: "online", - providerName: "main-server", + providerName: "D601", }, }; diff --git a/src/components/frontend/src/code-queue.tsx b/src/components/frontend/src/code-queue.tsx index 187dfbf7..1cb40ab5 100644 --- a/src/components/frontend/src/code-queue.tsx +++ b/src/components/frontend/src/code-queue.tsx @@ -1253,11 +1253,11 @@ function codexProviderOptions(queue: any, currentProviderId: string): any[] { kind: String(item?.kind || "").trim(), })) .filter((item: any) => item.id.length > 0); - const fallbackMain = String(queue?.mainProviderId || queue?.defaultProviderId || "main-server").trim() || "main-server"; + const fallbackMain = String(queue?.mainProviderId || queue?.defaultProviderId || "D601").trim() || "D601"; const byId = new Map(); for (const item of [ ...rows, - { id: fallbackMain, label: `${fallbackMain} (master)`, defaultWorkdir: String(queue?.defaultWorkdir || "/root/unidesk"), supportsWindowsNativeCodex: false, windowsNativeDefaultWorkdir: "", kind: "local" }, + { id: fallbackMain, label: `${fallbackMain} (local)`, defaultWorkdir: String(queue?.defaultWorkdir || "/workspace"), supportsWindowsNativeCodex: false, windowsNativeDefaultWorkdir: "", kind: "local" }, currentProviderId ? { id: currentProviderId, label: currentProviderId, defaultWorkdir: providerDefaultWorkdir(queue, currentProviderId), supportsWindowsNativeCodex: currentProviderId !== fallbackMain, windowsNativeDefaultWorkdir: String(queue?.windowsNativeCodexDefaultWorkdir || "/mnt/f/Work/ConStart"), kind: "" } : null, ].filter(Boolean) as any[]) { if (!byId.has(item.id)) byId.set(item.id, item); @@ -1278,7 +1278,7 @@ function codexExecutionModeOptions(queue: any, currentMode: string): any[] { })) .filter((item: any) => item.id.length > 0); const fallback = [ - { id: "default", label: "默认容器/本机", description: "主 server 用本机 Codex;远程 Provider 用执行容器 Codex。", defaultWorkdir: "", requiresProvider: false, requiresWindowsCwd: false }, + { id: "default", label: "默认容器/本机", description: "Code Queue 所在节点用本机 Codex;远程 Provider 用执行容器 Codex。", defaultWorkdir: "", requiresProvider: false, requiresWindowsCwd: false }, { id: "windows-native", label: "Windows 原生 Codex", description: "启动执行容器,但容器只做 stdio relay,Codex 运行在 Provider 的 Windows 宿主。", defaultWorkdir: String(queue?.windowsNativeCodexDefaultWorkdir || "/mnt/f/Work/ConStart"), requiresProvider: true, requiresWindowsCwd: true }, ]; const byId = new Map(); @@ -1301,8 +1301,8 @@ function providerDefaultWorkdir(queue: any, providerId: string): string { if (typeof map[id] === "string" && String(map[id]).trim().length > 0) return String(map[id]).trim(); const option = Array.isArray(queue?.executionProviders) ? queue.executionProviders.find((item: any) => String(item?.id || "") === id) : null; if (typeof option?.defaultWorkdir === "string" && option.defaultWorkdir.trim().length > 0) return option.defaultWorkdir.trim(); - const mainProvider = String(queue?.mainProviderId || queue?.defaultProviderId || "main-server"); - return id === mainProvider ? String(queue?.defaultWorkdir || "/root/unidesk") : String(queue?.remoteDefaultWorkdir || "/home/ubuntu"); + const mainProvider = String(queue?.mainProviderId || queue?.defaultProviderId || "D601"); + return id === mainProvider ? String(queue?.defaultWorkdir || "/workspace") : String(queue?.remoteDefaultWorkdir || "/home/ubuntu"); } function taskStepCount(task: any): number | null { @@ -1375,7 +1375,7 @@ function TaskCard({ task, selected, onSelect, onCopy, onReference, onMarkRead, c h("strong", null, shortText(taskDisplayPrompt(task), 120) || "空任务"), h("div", { className: "codex-task-meta" }, h("span", null, `queue=${taskQueueLabel(task)}`), - h("span", null, `provider=${task?.providerId || "main-server"}`), + h("span", null, `provider=${task?.providerId || "D601"}`), h("span", null, `mode=${task?.executionMode || "default"}`), h("span", null, task?.model || "--"), h("span", null, taskDurationLabel(task)), @@ -1952,16 +1952,18 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi const [searchTasksData, setSearchTasksData] = useState(null); const [searchLoading, setSearchLoading] = useState(false); const [searchLoadingMoreTasks, setSearchLoadingMoreTasks] = useState(false); + const initialQueueConfig = initialTasksData?.queue || {}; + const initialProviderId = String(initialQueueConfig?.mainProviderId || initialQueueConfig?.defaultProviderId || "D601").trim() || "D601"; const [prompt, setPrompt] = useState(""); const [referenceTaskId, setReferenceTaskId] = useState(""); const [queueId, setQueueId] = useState("default"); const [selectedQueueId, setSelectedQueueId] = useState(allQueuesId); const [mergeDialogOpen, setMergeDialogOpen] = useState(false); const [mergeSourceQueueId, setMergeSourceQueueId] = useState(""); - const [providerId, setProviderId] = useState("main-server"); + const [providerId, setProviderId] = useState(initialProviderId); const [executionMode, setExecutionMode] = useState("default"); const [model, setModel] = useState("gpt-5.5"); - const [cwd, setCwd] = useState("/root/unidesk"); + const [cwd, setCwd] = useState(executionModeDefaultWorkdir(initialQueueConfig, "default", initialProviderId) || "/workspace"); const [maxAttempts, setMaxAttempts] = useState(99); const [repeatCount, setRepeatCount] = useState(1); const [batchConfirmed, setBatchConfirmed] = useState(false); @@ -2108,7 +2110,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi } function changeSubmitProvider(nextProviderId: string): void { - const next = String(nextProviderId || queue?.mainProviderId || "main-server").trim() || "main-server"; + const next = String(nextProviderId || queue?.mainProviderId || "D601").trim() || "D601"; setProviderId(next); setCwd(executionModeDefaultWorkdir(queue, executionMode, next)); } @@ -3383,7 +3385,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi h("span", { className: "codex-trace-status-chip queued" }, h("b", null, "排队"), String(overallQueuedCount)), h("span", { className: "codex-trace-status-chip running" }, h("b", null, "运行"), String(overallRunningCount)), h("span", { className: `codex-trace-status-chip unread ${overallUnreadTerminalCount > 0 ? "warn" : ""}` }, h("b", null, "结束未读"), String(overallUnreadTerminalCount)), - h("span", { className: "codex-trace-status-chip service" }, h("b", null, "服务"), `${runtime.providerStatus || "unknown"} · ${service?.providerId || "main-server"} · ${backend.public ? "公网暴露" : "仅 UniDesk frontend 代理访问"}`), + h("span", { className: "codex-trace-status-chip service" }, h("b", null, "服务"), `${runtime.providerStatus || "unknown"} · ${service?.providerId || "D601"} · ${backend.public ? "公网暴露" : "仅 UniDesk frontend 代理访问"}`), h("span", { className: "codex-trace-status-chip" }, h("b", null, "执行节点"), providerOptions.map((provider: any) => provider.id).join(" / ")), h("span", { className: "codex-trace-status-chip" }, h("b", null, "执行模式"), executionModeRows.map((mode: any) => mode.id).join(" / ")), h("span", { className: "codex-trace-status-chip" }, h("b", null, "模型"), codexModels.join(" / ")), @@ -3393,7 +3395,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi const sessionPanel = h(Panel, { title: selectedTask ? `Trace ${String(selectedTask.id).slice(0, 22)}` : "Trace 输出", - eyebrow: selectedTask ? `${selectedTask.status} / view=${selectedQueueName} / task queue=${taskQueueLabel(selectedTask)} / provider=${selectedTask.providerId || "main-server"} / mode=${selectedTask.executionMode || "default"} / ${selectedTask.model} / agent loop trace` : `Agent loop trace / view=${selectedQueueName}`, + eyebrow: selectedTask ? `${selectedTask.status} / view=${selectedQueueName} / task queue=${taskQueueLabel(selectedTask)} / provider=${selectedTask.providerId || "D601"} / mode=${selectedTask.executionMode || "default"} / ${selectedTask.model} / agent loop trace` : `Agent loop trace / view=${selectedQueueName}`, summary: traceStatusSummary, loading: selectedDetailLoading || loadingMoreTasks || searchLoading || searchLoadingMoreTasks || loadStats?.phase === "loading", actions: h("div", { className: "panel-actions" }, @@ -3520,7 +3522,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi ), ), h("label", null, "执行 Provider", - h("select", { value: providerId, disabled: submitting, onChange: (event: any) => changeSubmitProvider(String(event.target.value || "main-server")), "data-testid": "codex-provider-select" }, + h("select", { value: providerId, disabled: submitting, onChange: (event: any) => changeSubmitProvider(String(event.target.value || "D601")), "data-testid": "codex-provider-select" }, providerOptions.map((provider: any) => h("option", { key: provider.id, value: provider.id }, `${provider.label || provider.id} · ${provider.defaultWorkdir || providerDefaultWorkdir(queue, provider.id)}${provider.supportsWindowsNativeCodex ? " · Windows native" : ""}`)), ), ), @@ -3529,7 +3531,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi executionModeRows.map((mode: any) => h("option", { key: mode.id, value: mode.id }, `${mode.label || mode.id}${mode.id === "windows-native" ? " · 宿主 Codex" : ""}`)), ), ), - h("label", null, "工作目录", h("input", { value: cwd, disabled: submitting, onChange: (event: any) => setCwd(event.target.value), placeholder: currentProviderDefaultWorkdir || queue?.defaultWorkdir || "/root/unidesk", "data-testid": "codex-cwd-input" })), + h("label", null, "工作目录", h("input", { value: cwd, disabled: submitting, onChange: (event: any) => setCwd(event.target.value), placeholder: currentProviderDefaultWorkdir || queue?.defaultWorkdir || "/workspace", "data-testid": "codex-cwd-input" })), h("label", null, "最大尝试", h("input", { type: "number", min: 1, max: 99, value: maxAttempts, disabled: submitting, onChange: (event: any) => setMaxAttempts(Number(event.target.value)), "data-testid": "codex-max-attempts-input" })), h("label", null, "入队份数", h("input", { type: "number", min: 1, max: 50, value: repeatCount, disabled: submitting, onChange: (event: any) => setRepeatCount(Number(event.target.value)), "data-testid": "codex-repeat-count-input" })), ), diff --git a/src/components/frontend/src/index.ts b/src/components/frontend/src/index.ts index c1641d50..4c431ffd 100644 --- a/src/components/frontend/src/index.ts +++ b/src/components/frontend/src/index.ts @@ -99,7 +99,8 @@ async function refreshCodeQueueOverview(pathWithQuery: string, timeoutMs = 800): async function refreshCodeQueueOverviewUncached(pathWithQuery: string, timeoutMs = 800): Promise { const started = performance.now(); try { - const response = await fetch(`http://code-queue:4222${pathWithQuery}`, { + const upstreamUrl = new URL(`/api/microservices/code-queue/proxy${pathWithQuery}`, config.coreInternalUrl); + const response = await fetch(upstreamUrl, { signal: AbortSignal.timeout(timeoutMs), headers: { accept: "application/json" }, }); @@ -718,7 +719,7 @@ async function proxyCodeQueueDirect(req: Request, url: URL): Promise { return new Response(cached.text, { headers: { "content-type": "application/json; charset=utf-8" } }); } } - const upstreamUrl = new URL(`${suffix}${url.search}`, "http://code-queue:4222"); + const upstreamUrl = new URL(`/api/microservices/code-queue/proxy${suffix}${url.search}`, config.coreInternalUrl); const headers = new Headers(req.headers); headers.delete("host"); headers.delete("connection"); diff --git a/src/components/microservices/code-queue/docker-compose.d601.yml b/src/components/microservices/code-queue/docker-compose.d601.yml new file mode 100644 index 00000000..eef7e294 --- /dev/null +++ b/src/components/microservices/code-queue/docker-compose.d601.yml @@ -0,0 +1,72 @@ +services: + code-queue: + image: unidesk-code-queue:d601 + build: + context: ../../../.. + dockerfile: src/components/microservices/code-queue/Dockerfile + container_name: code-queue-backend + restart: unless-stopped + mem_limit: "${CODE_QUEUE_MEM_LIMIT:-3g}" + memswap_limit: "${CODE_QUEUE_MEMSWAP_LIMIT:-4g}" + env_file: + - path: ${CODE_QUEUE_ENV_FILE:-../../../../.state/code-queue-d601.env} + required: false + ports: + - "127.0.0.1:${CODE_QUEUE_HOST_PORT:-4222}:4222" + environment: + HOST: "0.0.0.0" + PORT: "4222" + CODE_QUEUE_DATA_DIR: "/var/lib/unidesk/code-queue" + CODE_QUEUE_WORKDIR: "${CODE_QUEUE_WORKDIR:-/workspace}" + CODE_QUEUE_CODEX_HOME: "/var/lib/unidesk/code-queue/codex-home" + CODE_QUEUE_OPENCODE_XDG_DIR: "/var/lib/unidesk/code-queue/opencode-xdg" + CODE_QUEUE_SOURCE_CODEX_CONFIG: "/root/.codex/config.toml" + CODE_QUEUE_DEFAULT_MODEL: "${CODE_QUEUE_DEFAULT_MODEL:-gpt-5.5}" + CODE_QUEUE_MODELS: "${CODE_QUEUE_MODELS:-gpt-5.5,gpt-5.4-mini,gpt-5.4,minimax-m2.7}" + CODE_QUEUE_MODEL_REASONING_EFFORTS: "${CODE_QUEUE_MODEL_REASONING_EFFORTS:-gpt-5.5=xhigh}" + CODE_QUEUE_SANDBOX: "${CODE_QUEUE_SANDBOX:-danger-full-access}" + CODE_QUEUE_APPROVAL_POLICY: "${CODE_QUEUE_APPROVAL_POLICY:-never}" + CODE_QUEUE_MAX_ATTEMPTS: "${CODE_QUEUE_MAX_ATTEMPTS:-99}" + CODE_QUEUE_MAX_ACTIVE_QUEUES: "${CODE_QUEUE_MAX_ACTIVE_QUEUES:-0}" + NODE_OPTIONS: "${CODE_QUEUE_NODE_OPTIONS:---max-old-space-size=1024}" + CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS: "${CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS:-10}" + CODE_QUEUE_IN_MEMORY_EVENT_RECORDS: "${CODE_QUEUE_IN_MEMORY_EVENT_RECORDS:-10}" + CODE_QUEUE_CODEX_SQLITE_LOG_EXPORT_BATCH_SIZE: "${CODE_QUEUE_CODEX_SQLITE_LOG_EXPORT_BATCH_SIZE:-500}" + CODE_QUEUE_MAIN_PROVIDER_ID: "${CODE_QUEUE_MAIN_PROVIDER_ID:-D601}" + CODE_QUEUE_REMOTE_WORKDIR: "${CODE_QUEUE_REMOTE_WORKDIR:-/home/ubuntu}" + CODE_QUEUE_EXECUTION_PROVIDER_IDS: "${CODE_QUEUE_EXECUTION_PROVIDER_IDS:-D601}" + CODE_QUEUE_DEV_CONTAINER_MASTER_HOST: "${CODE_QUEUE_DEV_CONTAINER_MASTER_HOST:-74.48.78.17}" + CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID: "${CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID:-D601}" + CODE_QUEUE_DEV_CONTAINER_IMAGE: "${CODE_QUEUE_DEV_CONTAINER_IMAGE:-}" + CODE_QUEUE_DEV_CONTAINER_WORKDIR: "${CODE_QUEUE_DEV_CONTAINER_WORKDIR:-/home/ubuntu}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_DEFAULT_WORKDIR: "${CODE_QUEUE_WINDOWS_NATIVE_CODEX_DEFAULT_WORKDIR:-/mnt/f/Work/ConStart}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_BRIDGE_DIR: "${CODE_QUEUE_WINDOWS_NATIVE_CODEX_BRIDGE_DIR:-/home/ubuntu/.unidesk/code-queue/windows-native-codex}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_COMMAND: "${CODE_QUEUE_WINDOWS_NATIVE_CODEX_COMMAND:-codex app-server --listen stdio://}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_CONNECT_HOST: "${CODE_QUEUE_WINDOWS_NATIVE_CODEX_CONNECT_HOST:-host.docker.internal}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_IDLE_TIMEOUT_MS: "${CODE_QUEUE_WINDOWS_NATIVE_CODEX_IDLE_TIMEOUT_MS:-600000}" + OA_EVENT_FLOW_BASE_URL: "${OA_EVENT_FLOW_BASE_URL:-http://74.48.78.17:4255}" + CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED:-true}" + CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL:-http://host.docker.internal:3290}" + CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE:-private}" + CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID:-645275593}" + CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID:-}" + CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS:-12000}" + CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS:-15000}" + CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS:-3}" + LOG_FILE: "/var/log/unidesk/code-queue.jsonl" + UNIDESK_LOG_RETENTION_BYTES: "${UNIDESK_LOG_RETENTION_BYTES:-1GiB}" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ${CODE_QUEUE_WORKSPACE_PATH:-../../../..}:/root/unidesk + - ${CODE_QUEUE_WORKSPACE_PATH:-../../../..}:/workspace + - ${CODE_QUEUE_CODEX_CONFIG_PATH:-/home/ubuntu/.codex/config.toml}:/root/.codex/config.toml:ro + - ${CODE_QUEUE_SSH_DIR:-/home/ubuntu/.ssh}:/root/.ssh:ro + - ${CODE_QUEUE_LOG_DIR:-../../../../.state/code-queue/logs}:/var/log/unidesk + - ${CODE_QUEUE_STATE_DIR:-../../../../.state/code-queue}:/var/lib/unidesk/code-queue + extra_hosts: + - "host.docker.internal:host-gateway" + healthcheck: + test: ["CMD-SHELL", "curl -fsS --max-time 2 http://127.0.0.1:4222/health >/dev/null"] + interval: 5s + timeout: 3s + retries: 20 diff --git a/src/components/microservices/code-queue/src/code-agent/common.ts b/src/components/microservices/code-queue/src/code-agent/common.ts index caeebe3a..151fbbeb 100644 --- a/src/components/microservices/code-queue/src/code-agent/common.ts +++ b/src/components/microservices/code-queue/src/code-agent/common.ts @@ -65,7 +65,7 @@ export function codeExecutionModeInfo(mode: CodeExecutionMode): Record 执行过程 Summary 1 -> finalresponse1 -> judge1 -> 执行过程 Summary 2 -> finalresponse2 judge2 还不够,还要有 judge feedback prompt,例如 originprompt -> 执行过程 Summary 1 -> finalresponse1 -> judge1 -> judge feedback prompt -> 执行过程 Summary 2 -> finalresponse2 judge2", - finalResponse: "已把 Trace 顶级链路补成:origin prompt -> Summary 1 -> final response 1 -> judge 1 -> judge feedback prompt -> Summary 2 -> final response 2 -> judge 2。后端扩展 attempt 数据,trace-summary 现在返回 feedback prompt preview/chars/lines/source,/api/tasks/:id/prompt?part=feedback&attempt=N 支持按需拉取完整内容,前端显示 feedback prompt cards。验证已通过:bun run --cwd src/components/microservices/code-queue check、bun run --cwd src/components/frontend check、bun scripts/cli.ts check、git diff --check。当前 git diff clean。我没有重建运行中的容器。若要上线验证:1. bun scripts/cli.ts server rebuild code-queue 2. bun scripts/cli.ts server rebuild frontend。", + finalResponse: "已把 Trace 顶级链路补成:origin prompt -> Summary 1 -> final response 1 -> judge 1 -> judge feedback prompt -> Summary 2 -> final response 2 -> judge 2。后端扩展 attempt 数据,trace-summary 现在返回 feedback prompt preview/chars/lines/source,/api/tasks/:id/prompt?part=feedback&attempt=N 支持按需拉取完整内容,前端显示 feedback prompt cards。验证已通过:bun run --cwd src/components/microservices/code-queue check、bun run --cwd src/components/frontend check、bun scripts/cli.ts check、git diff --check。当前 git diff clean。我没有重建运行中的容器。若要上线验证:1. 在 D601 用 docker compose 重建 code-queue-backend 2. bun scripts/cli.ts server rebuild frontend。", expected: "retry", terminalStatus: "completed", outputs: [ diff --git a/src/components/microservices/code-queue/src/judge.ts b/src/components/microservices/code-queue/src/judge.ts index d81c3eac..f764c1b1 100644 --- a/src/components/microservices/code-queue/src/judge.ts +++ b/src/components/microservices/code-queue/src/judge.ts @@ -118,7 +118,8 @@ function fallbackJudge(result: CodexRunResult, minimaxError?: string | JudgeFail } export const retryInstruction = "这是同一个 Codex thread 的 continuation,不是新任务。请基于上文继续完成原始任务;只做最小必要状态核查,避免从头重新摸索、避免重复已经完成的修改。"; -const codeQueueRestartSafetyGuidance = "Code Queue 服务具备 restart-recovery,允许在任何时候重启、重建或替换 `code-queue-backend`;当当前任务修改 Code Queue 自身时,禁止等待当前 Code Queue task 退出或等待队列归零后再重启,因为这会等待自己退出形成自锁。正确做法是直接触发 `server rebuild code-queue` 或等价 no-deps force-recreate,并在恢复后用 live health/task 查询验证。"; +const codeQueueD601DeployCommand = "bun scripts/cli.ts ssh D601 'cd /home/ubuntu/unidesk-code-queue-deploy && CODE_QUEUE_ENV_FILE=/home/ubuntu/unidesk-code-queue-deploy/.state/code-queue-d601.env docker compose -f src/components/microservices/code-queue/docker-compose.d601.yml up -d --build --force-recreate code-queue'"; +const codeQueueRestartSafetyGuidance = `Code Queue 服务具备 restart-recovery,允许在任何时候重启、重建或替换 D601 的 \`code-queue-backend\`;当当前任务修改 Code Queue 自身时,禁止等待当前 Code Queue task 退出或等待队列归零后再重启,因为这会等待自己退出形成自锁。正确做法是在 D601 直接执行 \`${codeQueueD601DeployCommand}\` 或等价 no-deps force-recreate,并在恢复后用 live health/task 查询验证。`; export function explicitUserInterrupt(task: QueueTask, result: CodexRunResult): boolean { return result.terminalStatus === "interrupted" @@ -278,7 +279,7 @@ function judgePrompt(task: QueueTask, result: CodexRunResult): string { "列出缺失的验收证据,并要求下一轮在最终回复中给出真实命令/API/UI 结果。", "如果 agent 在交付中途停下来询问用户如何处理一个它本不需要触碰的并发修改文件,continuePrompt 必须要求它忽略该并发文件并继续交付自己的变更范围,而不是让用户选择。", "对于未部署/未上线的服务或 WebUI 工作,continuePrompt 必须明确要求重建/重启所有受影响的 service/container/bundle,并在部署后验证运行中的真实行为。", - "如果受影响服务包含 Code Queue 和 frontend,部署反馈应点名 `bun scripts/cli.ts server rebuild code-queue`、`bun scripts/cli.ts server rebuild frontend`,并按场景要求 live API/WebUI 验证,例如 `/api/judge/probe`、`/trace-summary` 或已服务的 Code Queue 页面。", + `如果受影响服务包含 Code Queue 和 frontend,部署反馈应点名 D601 Code Queue 重建命令 \`${codeQueueD601DeployCommand}\` 和 \`bun scripts/cli.ts server rebuild frontend\`,并按场景要求 live API/WebUI 验证,例如 \`/api/judge/probe\`、\`/trace-summary\` 或已服务的 Code Queue 页面。`, "如果受影响服务包含 Code Queue 自身,continuePrompt 禁止要求等待当前 task 结束、等待 queue idle 或等待 `0 running` 后再重启;这会形成自锁。应明确 Code Queue 可以立即重启/重建,并依赖 restart-recovery 恢复本任务后继续验证。", ], hallucinationNoiseGuardrails: [ @@ -348,7 +349,7 @@ function judgePrompt(task: QueueTask, result: CodexRunResult): string { }, { pattern: "原始任务要求 Code Queue 在 trace 链路和 WebUI 中暴露 judge feedback prompt,例如 task codex_1778476426776_a2bf19。", - incompleteEvidence: "执行代理编辑 backend/frontend 源码并通过 type check,但没有 `server rebuild code-queue`,没有 `server rebuild frontend` 或等价 served bundle 部署,也没有 live API/UI 验证证明 `/trace-summary` 或 WebUI 包含 judge feedback prompt。最终回复说“我没有重建运行中的容器”,或把 rebuild/deploy 当作建议/未来工作。", + incompleteEvidence: "执行代理编辑 backend/frontend 源码并通过 type check,但没有重建 D601 `code-queue-backend`,没有 `server rebuild frontend` 或等价 served bundle 部署,也没有 live API/UI 验证证明 `/trace-summary` 或 WebUI 包含 judge feedback prompt。最终回复说“我没有重建运行中的容器”,或把 rebuild/deploy 当作建议/未来工作。", requiredDecision: "retry", requiredContinuePrompt: "请让同一个 Codex thread 部署已修改的 Code Queue/frontend 服务,然后在声明完成前验证 live API/UI 证据。", reason: "这是 service/UI 功能。只有运行中的 Code Queue backend 和 served frontend 已更新并验证后才算完成;否则用户仍看不到该功能。", @@ -357,7 +358,7 @@ function judgePrompt(task: QueueTask, result: CodexRunResult): string { pattern: "原始任务要求修改或验证 Code Queue 自身,并且完成条件需要重启/重建 `code-queue-backend`。", incompleteEvidence: "执行代理表示要等当前 Code Queue task 结束、等队列空闲、等 0 running、或等自己退出后再重启 Code Queue,因此没有执行重启/重建和恢复后 live 验证。", requiredDecision: "retry", - requiredContinuePrompt: "不要等待当前 Code Queue task 退出;Code Queue 可随时重启/重建。请直接执行 `server rebuild code-queue` 或等价 no-deps force-recreate,依赖 restart-recovery 恢复本任务,然后验证 live health/task 证据。", + requiredContinuePrompt: `不要等待当前 Code Queue task 退出;D601 Code Queue 可随时重启/重建。请直接执行 \`${codeQueueD601DeployCommand}\` 或等价 no-deps force-recreate,依赖 restart-recovery 恢复本任务,然后验证 live health/task 证据。`, reason: "等待当前任务结束后再重启 Code Queue 会让任务等待自己退出,属于自锁;正确交付路径是先重启/重建再由 restart-recovery 继续。", }, ], @@ -755,7 +756,7 @@ function deploymentFeedbackPrompt(task: QueueTask, reason: string): string { `judge 未完成原因:${judgeReasonForPrompt(reason)}`, "请先确认受影响范围;凡是 Code Queue、frontend、backend-core、provider-gateway 或其他运行服务/前端 bundle 的行为变化,都必须更新运行中的服务后再验收。", "若受影响的是 Code Queue 自身,不要等待当前 Code Queue task 退出或等待队列空闲;可以立即重启/重建 `code-queue-backend`,由 restart-recovery 恢复本任务后继续验证。", - "如果本轮改动影响 Code Queue 和 frontend,请执行并记录真实结果:`bun scripts/cli.ts server rebuild code-queue`、`bun scripts/cli.ts server rebuild frontend`。", + `如果本轮改动影响 Code Queue 和 frontend,请执行并记录真实结果:\`${codeQueueD601DeployCommand}\`、\`bun scripts/cli.ts server rebuild frontend\`。`, "部署后必须做 live verification:至少用运行中的 API 或公网 WebUI 证明目标行为已经生效,例如 Code Queue `/api/judge/probe` 命中该样例、`/trace-summary` 返回 judge feedback prompt,或 served Code Queue 页面展示对应 feedback prompt。", "最终 response 必须列出实际执行的部署命令和 live verification 结果;如果不能上线或验证,请说明阻塞并保持 retry 语义。", "原始任务摘要/按需查询:", diff --git a/src/components/microservices/code-queue/src/provider-runtime.ts b/src/components/microservices/code-queue/src/provider-runtime.ts index be0aa6fe..2afc0d9b 100644 --- a/src/components/microservices/code-queue/src/provider-runtime.ts +++ b/src/components/microservices/code-queue/src/provider-runtime.ts @@ -70,7 +70,7 @@ function executionProviderOptions(): JsonValue[] { ].map(normalizeProviderId).filter((value): value is string => value !== null))); return ids.map((providerId) => ({ id: providerId, - label: providerIsMain(providerId) ? `${providerId} (master)` : providerId, + label: providerIsMain(providerId) ? `${providerId} (local)` : providerId, kind: providerIsMain(providerId) ? "local" : "remote-dev-container", defaultWorkdir: defaultWorkdirForProvider(providerId), supportsWindowsNativeCodex: !providerIsMain(providerId),