diff --git a/AGENTS.md b/AGENTS.md index d01f960c..d8ccb630 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,9 +25,9 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - `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 重建主 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 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 维护私钥挂载和 loopback egress proxy 端口,规则见 `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/Todo Note/Baidu Netdisk on main-server 与 Code Queue/FindJob/Pipeline/MET Nonlinear on D601 的规则见 `docs/reference/microservices.md`。 +- `bun scripts/cli.ts microservice list/status/health/proxy`:管理和验证挂载在主 server、计算节点 Docker 或 v3s 控制面上的用户服务,OA Event Flow/Todo Note/Baidu Netdisk on main-server、V3S Control/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` 复核。 @@ -38,12 +38,12 @@ 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 后端和 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`。 +- `docker-compose.yml`:主 server 统一编排 core、frontend、database、本机 provider gateway、Todo Note 后端、Baidu Netdisk 后端和 OA Event Flow 后端;Code Queue 由 D601 v3s/k8s 控制面代管,并经 `v3sctl-adapter` 的 Kubernetes API service proxy 单一路径接入,服务拓扑见 `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、V3S Control 等业务页必须拆到独立 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`。 - `src/components/provider-gateway`:当前主 server `74.48.78.17` 也作为 provider gateway 接入 UniDesk,外部节点通过 `ws://74.48.78.17:18082/ws/provider` 接入,必须以 `restart: always` 部署 always-enabled 远程升级、sleep-and-validate 回滚保护和 Host SSH / WSL SSH 透传并完成自测,部署与 Playwright 公网前端验证方法见 `docs/reference/provider-gateway.md`。 -- `microservices`:用户服务配置命名仍保留 `microservices`;用户服务指挂载在 UniDesk 核心服务上的用户业务能力,缺少这些服务时核心仍可运行。主 server 本地开发边界固定为只开发 UniDesk frontend;非 UniDesk 核心业务后端、Dockerfile、GPU/训练调试必须在目标计算节点通过 SSH 透传完成,Todo Note 这类明确写入主 server 的例外需单独登记,规则见 `docs/reference/microservices.md`。 +- `microservices`:用户服务配置命名仍保留 `microservices`;用户服务指挂载在 UniDesk 核心服务上的用户业务能力,支持 `unidesk-direct` 与 `v3sctl-managed` 两种部署模式;v3s 代管必须使用标准 k3s/k8s 对象和 Kubernetes API service proxy,禁止业务容器直连、NodePort 和隐藏 fallback;缺少这些服务时核心仍可运行。主 server 本地开发边界固定为只开发 UniDesk frontend;非 UniDesk 核心业务后端、Dockerfile、GPU/训练调试必须在目标计算节点通过 SSH 透传或 v3s 控制面完成,Todo Note 这类明确写入主 server 的例外需单独登记,规则见 `docs/reference/microservices.md`。 - `docs/reference/e2e.md`:交付前必须执行的自测门禁、Playwright 登录、资源监控进程排序、JSON 展示断言和数据库命名卷持久化要求。 ## Architecture Docs @@ -51,7 +51,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - `docs/reference/arch.md`:UniDesk 分布式工作平台的长期架构约束。 - `docs/reference/repo-tree.md`:仓库结构目标与组件边界。 - `docs/reference/observability.md`:服务日志、任务活性、通用性能指标 API 和性能面板的可观测性规则。 -- `docs/reference/microservices.md`:用户服务(兼容命名 `microservice`)的配置、代理、安全边界、Todo Note/Baidu Netdisk on main-server、FindJob/Pipeline/MET Nonlinear on D601 和验证规则。 +- `docs/reference/microservices.md`:用户服务(兼容命名 `microservice`)的配置、代理、安全边界、unidesk-direct/v3sctl-managed 部署模式、Todo Note/Baidu Netdisk on main-server、V3S Control/Code Queue/FindJob/Pipeline/MET Nonlinear on D601 和验证规则。 - `docs/reference/windows-passthrough.md`:WSL provider 通过 SSH 透传调用 Windows cmd/PowerShell、Keil、COM 串口和 Windows 侧 skill 的长期规则。 - `docs/reference/constar-d601.md`:D601 上 ConStart/constar 固件工作区的 UniDesk SSH 入口、WSL skill wrapper、Keil 编译下载和串口/JSON-RPC 验证简要引导。 - `docs/reference/oa-event-flow.md`:统一 OA 事件流微服务、事件表、tag 订阅、Trace/STEP 统计中心和前端可见性规则。 diff --git a/TEST.md b/TEST.md index 93821954..956772d3 100644 --- a/TEST.md +++ b/TEST.md @@ -99,7 +99,7 @@ ## 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=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` 可访问;这些映射不得成为任意公网入口。 +阅读 `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`、v3s/k8s `v3s://unidesk/code-queue:4222` 逻辑服务映射、`deployment.mode=v3sctl-managed`、`runtime.orchestrator=v3sctl` 且无业务直连容器摘要;在 D601 v3s/k8s 控制面中使用 `src/components/microservices/v3sctl-adapter/v3s/code-queue.k8s.yaml` 重建/启动 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/overview?limit=5&transcriptLimit=1&compact=1&afterSeq=0&preferId='` 和 `bun scripts/cli.ts codex task <已有taskId>`,确认链路通过 backend-core、v3sctl-adapter、Kubernetes API service proxy 和 D601 active Code Queue Service,且 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、源码或测试文档。 diff --git a/config.json b/config.json index 95d1e435..303fcf17 100644 --- a/config.json +++ b/config.json @@ -29,7 +29,8 @@ "restrictedHostAccess": { "bindHost": "0.0.0.0", "allowedSourceCidrs": [ - "36.49.30.105/32" + "36.49.30.105/32", + "59.72.97.73/32" ] } }, @@ -108,6 +109,9 @@ "frontend": { "route": "/apps/findjob", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" } }, { @@ -151,6 +155,9 @@ "frontend": { "route": "/apps/pipeline", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" } }, { @@ -194,6 +201,9 @@ "frontend": { "route": "/apps/met-nonlinear", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" } }, { @@ -238,6 +248,9 @@ "frontend": { "route": "/apps/claudeqq", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" } }, { @@ -280,6 +293,9 @@ "frontend": { "route": "/apps/todo-note", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" } }, { @@ -325,6 +341,9 @@ "frontend": { "route": "/apps/project-manager", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" } }, { @@ -369,6 +388,9 @@ "frontend": { "route": "/apps/baidu-netdisk", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" } }, { @@ -413,6 +435,9 @@ "frontend": { "route": "/apps/filebrowser", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" } }, { @@ -457,6 +482,9 @@ "frontend": { "route": "/apps/filebrowser", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" } }, { @@ -500,26 +528,77 @@ "frontend": { "route": "/apps/oa-event-flow", "integrated": true + }, + "deployment": { + "mode": "unidesk-direct" + } + }, + { + "id": "v3sctl-adapter", + "name": "V3S Control Plane", + "providerId": "D601", + "description": "v3sctl-adapter 是 UniDesk 直管的 v3s 控制平面适配微服务,连接 D601 原生 v3s/v3sctl 控制平面,并通过 v3s 标准服务路由代理 D601/D518 等节点上的代管微服务。", + "repository": { + "url": "https://github.com/pikasTech/unidesk", + "commitId": "local", + "dockerfile": "src/components/microservices/v3sctl-adapter/Dockerfile", + "composeFile": "src/components/microservices/v3sctl-adapter/docker-compose.d601.yml", + "composeService": "v3sctl-adapter", + "containerName": "v3sctl-adapter" + }, + "backend": { + "nodeBaseUrl": "http://host.docker.internal:4266", + "nodeBindHost": "127.0.0.1", + "nodePort": 4266, + "proxyMode": "provider-gateway-http", + "frontendOnly": true, + "public": false, + "allowedMethods": [ + "GET", + "HEAD", + "POST", + "DELETE", + "PATCH" + ], + "allowedPathPrefixes": [ + "/health", + "/logs", + "/api/" + ], + "healthPath": "/health", + "timeoutMs": 30000 + }, + "deployment": { + "mode": "unidesk-direct" + }, + "development": { + "providerId": "D601", + "sshPassthrough": true, + "worktreePath": "/home/ubuntu/cq-deploy" + }, + "frontend": { + "route": "/apps/v3sctl", + "integrated": true } }, { "id": "code-queue", "name": "Code Queue", "providerId": "D601", - "description": "Code Queue 是部署在 D601 的平台无关代码代理队列用户服务,通过 D601 本机端口、主 PostgreSQL 端口映射和 OA/ClaudeQQ 私有链路提供串行任务队列、运行中输出、追加 prompt、打断会话、异常中断判定和自动重试。", + "description": "Code Queue 是由 D601 v3s 控制平面代管的代码代理队列用户服务,UniDesk 只通过 v3sctl-adapter 访问其标准服务路由;D601/D518 实例由 v3s 管理,provider-gateway 只保留维护用途。", "repository": { "url": "https://github.com/pikasTech/unidesk", "commitId": "cbbed004a6c84a7dbc554bb90692bd80b4384e67", "dockerfile": "src/components/microservices/code-queue/Dockerfile", - "composeFile": "src/components/microservices/code-queue/docker-compose.d601.yml", + "composeFile": "src/components/microservices/v3sctl-adapter/v3s/code-queue.v3s.json", "composeService": "code-queue", - "containerName": "code-queue-backend" + "containerName": "v3s:code-queue" }, "backend": { - "nodeBaseUrl": "http://code-queue:4222", - "nodeBindHost": "127.0.0.1", + "nodeBaseUrl": "v3s://code-queue", + "nodeBindHost": "v3s://unidesk/code-queue", "nodePort": 4222, - "proxyMode": "provider-gateway-http", + "proxyMode": "v3sctl-adapter-http", "frontendOnly": true, "public": false, "allowedMethods": [ @@ -545,6 +624,17 @@ "frontend": { "route": "/apps/code-queue", "integrated": true + }, + "deployment": { + "mode": "v3sctl-managed", + "adapterServiceId": "v3sctl-adapter", + "v3sServiceId": "code-queue", + "namespace": "unidesk", + "expectedNodeIds": [ + "D601", + "D518" + ], + "activeNodeId": "D601" } } ], diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 4dd17dfc..0379e6d4 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -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` 命令理解成“前一个重建已完成”,因为两个命令只是在快速创建异步 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` 手工兜底当成正式交付步骤。 +`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 v3s/k8s 控制面代管,用 `src/components/microservices/v3sctl-adapter/v3s/code-queue.k8s.yaml` 重建,再用 `microservice health code-queue` 和 `microservice proxy code-queue /api/tasks/overview` 验证。不得把 `docker rm` 手工兜底当成正式交付步骤。 ## Output Contract diff --git a/docs/reference/config.md b/docs/reference/config.md index 95ff1f5e..a103d069 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -26,7 +26,7 @@ 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=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 操作。 +主 server 承载的 Todo Note 用户服务使用 `providerId=main-server`、`nodeBaseUrl=http://todo-note:4211` 和 `allowedMethods=["GET","HEAD","POST","DELETE"]`,数据库使用主 PostgreSQL;Code Queue 使用 `deployment.mode=v3sctl-managed`、`backend.proxyMode=v3sctl-adapter-http` 和 `nodeBaseUrl=v3s://code-queue`,只允许通过 frontend/backend-core -> `v3sctl-adapter` -> Kubernetes API service proxy -> v3s/k8s Service 单一路径访问,不能配置业务容器直连、NodePort 或 provider-gateway direct path;D601 的 FindJob 只允许 `GET/HEAD` 展示型读取路径;D601 的 Pipeline 允许 `GET/HEAD/POST`,其中 `POST` 只用于 Pipeline 后端 `/api/node-control/...` 的 append prompt、guide 和 redo/restart 等受控 node 操作。 ## Compose Env Generation diff --git a/docs/reference/deployment.md b/docs/reference/deployment.md index d6313390..1b971934 100644 --- a/docs/reference/deployment.md +++ b/docs/reference/deployment.md @@ -1,21 +1,22 @@ # UniDesk Deployment Reference -主 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` 接入。 +主 server 使用根目录 `docker-compose.yml` 统一编排 database、backend-core、frontend、provider-gateway 以及必须留在主 server 的用户服务。当前环境本身就是主 server,因此 provider-gateway 也在同一台机器上启动,用与普通计算节点相同的 WebSocket 方式接入 core。Code Queue 不再属于主 server Compose,也不再由 backend-core 通过 provider-gateway 直连业务容器;它作为 `v3sctl-managed` 用户服务经 D601 `v3sctl-adapter` 进入 v3s 标准服务路由。 ## Services - `database` 使用 `postgres:16-alpine`,数据保存到 named volume `unidesk_pgdata_10gb`,初始化 SQL 位于 `src/components/database/init/`。 - `backend-core` 是无状态核心服务,提供 Docker 内网 REST API、provider ingress WebSocket、任务调度入口和数据库访问层。 - `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`,不得作为自动任务调度主路径。 +- `provider-gateway` 是当前主 server 的本机计算节点代理,通过 WebSocket 主动连到 provider ingress,挂载 `/var/run/docker.sock` 作为自动任务执行主路径,使用 `pid: "host"` 读取节点级进程资源,并周期性上报系统资源指标、进程占用与 Docker daemon 状态;计算节点 provider-gateway 还必须把 egress proxy 仅发布到宿主 loopback `127.0.0.1:18789` 供本节点执行环境出网,维护用 Host SSH / WSL SSH 私钥目录只读挂载到 `/run/host-ssh`,不得作为自动任务调度主路径。 - `todo-note` 是主 server 承载的 Todo Note 纯后端用户服务,容器名 `todo-note-backend`,只在 Compose 内网暴露 `4211/tcp`,使用主 PostgreSQL 存储迁移后的 Todo Note 数据。 -- `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、打断和重试。 +- `v3sctl-adapter` 是 D601 上由 UniDesk 直管的 v3s 控制面适配微服务,容器名 `v3sctl-adapter`,只绑定 `127.0.0.1:4266`,由 UniDesk frontend/backend-core 通过用户服务代理访问并提供 `/api/control-plane` 可见性。 +- `code-queue` 是由 D601 v3s/k8s 控制面代管的 Codex/OpenCode 队列用户服务,active/standby 实例通过 `src/components/microservices/v3sctl-adapter/v3s/code-queue.v3s.json` 声明,运行对象通过 `code-queue.k8s.yaml` 创建 Kubernetes Deployment/ClusterIP Service;任务、queue、未读状态、控制状态和通知 outbox 一律写入主 PostgreSQL,不保留本地状态文件 fallback,浏览器只能通过 UniDesk frontend -> backend-core -> v3sctl-adapter -> Kubernetes API service proxy -> Code Queue Service 查看运行输出、追加 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 和 OA Event Flow 只允许为了 D601 Code Queue 使用受限端口映射,并必须由 `network.restrictedHostAccess.allowedSourceCidrs` 生成的 `DOCKER-USER` 规则限制到 D601 出口地址,不能作为浏览器或任意公网客户端入口。浏览器访问 core API 必须通过 frontend 的同源代理完成。 +Docker Compose 对最终用户只公开 frontend host port 和 provider ingress host port。backend-core REST API 仍不得映射公网;PostgreSQL 和 OA Event Flow 只允许为了受控 Code Queue active/standby 节点使用受限端口映射,并必须由 `network.restrictedHostAccess.allowedSourceCidrs` 生成的 `DOCKER-USER` 规则限制到 D601 出口地址,不能作为浏览器或任意公网客户端入口。浏览器访问 core API 必须通过 frontend 的同源代理完成。 计算节点上的用户服务后端也遵守同一边界:业务容器端口只绑定节点本机地址,并由 provider-gateway 主动连出 WebSocket 后接受 backend-core 的 `microservice.http` 调度访问。主 server 不为用户服务新增面向浏览器的公网反向代理端口;最终用户只通过 UniDesk frontend 的 React 页面访问结构化业务控件。 @@ -49,11 +50,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`,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` 的门禁作为最终判定。 +服务跑通的最低标准是:backend-core 内网 `/health` 返回 ok,frontend 公网 `/health` 返回 ok,provider ingress 公网 `/health` 返回 ok,database 在容器内 `pg_isready` 可用,Todo Note 后端 `/api/health` 返回 `storage=postgres`,`v3sctl-adapter` `/api/control-plane` 可见 Kubernetes API service proxy 状态、D601 active serving healthy、D518 expected/missing 节点状态和 no-fallback 路径,Code Queue `/health` 经 v3s active Service 返回轻量 readiness、默认模型和 `queue.storage`,`/api/tasks/overview` 返回 PostgreSQL 队列总览,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 快照。D518 未接入前不得用 D601->D518 直连或 NodePort 绕过,也不得把 D518 missing 当作 D601 active Service 不可用;接入验收应证明 D518 通过 k3s/k8s 原生 agent/proxy/tunnel 或显式 provider 维护代理进入控制面。交付前还必须运行 `bun scripts/cli.ts e2e run`,并以 `docs/reference/e2e.md` 的门禁作为最终判定。 ## Code Queue D601 Resource Budget -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 证明未重新引入内存爆炸风险。 +Code Queue 已从主 server 迁移到 D601 v3s/k8s,但仍必须保持明确的 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 读取必须优先从 PostgreSQL 直读或聚合,`/health` 只做轻量 readiness,不能为了性能便利在 Bun 进程内缓存全量历史。任何提高 Code Queue 热窗口、日志缓冲、Playwright/Codex 子进程常驻规模或容器上限的变更,或把 `CODE_QUEUE_MAX_ACTIVE_QUEUES` 显式改成正数,都必须在同一任务里说明 D601 资源预算来源,并通过 D601 `kubectl -n unidesk get deploy,svc,pod`、`kubectl -n unidesk top pod` 或等价 Docker stats、`microservice health code-queue` 和对应 E2E 证明未重新引入内存爆炸风险。 ## Database Connection Budget diff --git a/docs/reference/e2e.md b/docs/reference/e2e.md index a4a35bd2..43f95a96 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 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. +- Public exposure: Docker port summary must not show core REST, Code Queue NodePort, 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 controlled Code Queue nodes 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`, legacy Code Queue host ports 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` 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. +- User services: internal `/api/microservices` must include `todo-note` and `oa-event-flow` on `main-server`, canonical `filebrowser` on `D518`, plus `v3sctl-adapter`, `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/v3sctl-adapter/health` and `/api/microservices/v3sctl-adapter/proxy/api/control-plane` must expose the D601 v3s/k8s control plane, `kubeApiProxy.mode=kubernetes-api-service-proxy`, D601 active instance `servingHealthy=true`, D518 expected/missing state when D518 has not joined, `status=degraded` for incomplete topology, and `noFallback=true`; `/api/microservices/code-queue/health` must return the active Code Queue backend summary with default model `gpt-5.5`, and `/api/microservices/code-queue/proxy/api/tasks/overview` must return queue state through backend-core -> v3sctl-adapter -> Kubernetes API service proxy -> v3s/k8s Service, not through a `serviceId=code-queue` provider-gateway direct task or `/api/code-queue-direct`; `/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、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: 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`、`用户服务 / V3S Control`、`用户服务 / 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 表、V3S 控制面/D601-D518 实例/Kubernetes API service proxy/no-fallback 路径、Code Queue 队列/模型/输出/初始 `Submitted prompt`/终态任务自动加载完整 Trace/追加 prompt/打断控件、FindJob 指标和岗位预览、Pipeline 组件矩阵、MiniMax 限额卡片、结构化 OA 事件流诊断面板、React Flow 控制图、epoch 甘特图、甘特图渲染图导出、monitor 首列排序、长任务观察连线、无观察来源伪点、running node 实时闪动执行条和 OpenCode Trace、MET Nonlinear 项目库/Fork/待启动队列/当前队列/已完成/失败诊断/GPU/镜像都通过 React 控件展示。Playwright 还必须验证 Code Queue 页面所有 API 请求走 `/api/microservices/code-queue/proxy`,不得再出现 `/api/code-queue-direct`;深链接直达路由例如公网 `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 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. +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 controlled Code Queue nodes, and E2E must prove those mappings are unreachable to generic clients or protected by explicit source rules. ## Database Persistence Rule @@ -67,7 +67,7 @@ The PostgreSQL data volume is the named Docker volume `unidesk_pgdata_10gb`. CLI ## User Service Restart-Recovery Rule -Any new user service, service migration, or change to a service's Compose/docker run configuration must prove it can recover after container restart and Docker daemon restart. The delivery evidence must include the service's `config.json` id/provider/container mapping, restart policy, host-bound private port, persistent mounts or PostgreSQL tables, health readiness fields, and at least one post-restart `bun scripts/cli.ts microservice health ` plus a representative `microservice proxy` check through the real provider-gateway path. +Any new user service, service migration, or change to a service's Compose/docker run/k8s configuration must prove it can recover after container restart and Docker daemon restart. The delivery evidence must include the service's `config.json` id/provider/container or Kubernetes Service mapping, restart policy or Deployment replica policy, private port or ClusterIP Service, persistent mounts or PostgreSQL tables, health readiness fields, and at least one post-restart `bun scripts/cli.ts microservice health ` plus a representative `microservice proxy` check through the real UniDesk path. `v3sctl-managed` services must prove the proxy path through `v3sctl-adapter` and Kubernetes API service proxy, not the provider-gateway direct business path. D601 services have an extra gate because Windows, WSL and Docker Desktop are separate supervisors: record the Windows scheduled task or equivalent keepalive, run `docker inspect` to confirm `met-nonlinear-ts`, `claudeqq-backend`, `claudeqq-napcat` and any changed service have non-empty restart policies and host bind mounts for durable state, then verify MET Nonlinear queue/image health and ClaudeQQ logged-in NapCat HTTP/WebSocket state after the restart. A service that only becomes `running` but loses login, queue, token, subscription, data directory or pending work is not restart-recovery complete. diff --git a/docs/reference/frontend.md b/docs/reference/frontend.md index 18b392b3..6edb8ace 100644 --- a/docs/reference/frontend.md +++ b/docs/reference/frontend.md @@ -6,7 +6,7 @@ UniDesk 前端是 React 组件化工业控制台,不追求展示型大屏效 frontend 应用源码必须使用 TypeScript + React,禁止在 `src/components/frontend` 中维护手写 `.js` / `.jsx` 应用源码。浏览器请求的 `/app.js` 只能由 frontend Bun server 从 `src/components/frontend/src/app.tsx` 及其 TSX imports 转译生成;`public/` 目录只保存 HTML/CSS 等静态资产,不提交手写 `app.js`。 -`src/components/frontend/src/app.tsx` 只承担应用 shell、登录、全局数据加载、主模块/子标签路由和通用控制台页面。用户服务前端必须模块化到独立 TSX 文件,禁止继续把所有业务页面堆进 `app.tsx`。当前长期固定入口为:`todo-note.tsx` 承载 Todo Note 工作台,`findjob.tsx` 承载 FindJob 工作台,`pipeline.tsx` 承载 Pipeline 工作台,`met-nonlinear.tsx` 承载 MET Nonlinear 训练编排工作台,`claudeqq.tsx` 承载 ClaudeQQ QQ 消息网关工作台,`baidu-netdisk.tsx` 承载 Baidu Netdisk 存储工作台,`code-queue.tsx` 承载 Code Queue 控制台,`oa-event-flow.tsx` 承载统一 OA 事件流控制台;新增用户服务也必须按同样规则新增独立页面模块,并由 `app.tsx` 只做导入和路由分发。 +`src/components/frontend/src/app.tsx` 只承担应用 shell、登录、全局数据加载、主模块/子标签路由和通用控制台页面。用户服务前端必须模块化到独立 TSX 文件,禁止继续把所有业务页面堆进 `app.tsx`。当前长期固定入口为:`todo-note.tsx` 承载 Todo Note 工作台,`findjob.tsx` 承载 FindJob 工作台,`pipeline.tsx` 承载 Pipeline 工作台,`met-nonlinear.tsx` 承载 MET Nonlinear 训练编排工作台,`claudeqq.tsx` 承载 ClaudeQQ QQ 消息网关工作台,`baidu-netdisk.tsx` 承载 Baidu Netdisk 存储工作台,`code-queue.tsx` 承载 Code Queue 控制台,`oa-event-flow.tsx` 承载统一 OA 事件流控制台,`v3sctl.tsx` 承载 V3S Control Plane 页面;新增用户服务也必须按同样规则新增独立页面模块,并由 `app.tsx` 只做导入和路由分发。 ## Shared Dialog Component @@ -95,7 +95,8 @@ 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` 子标签必须把 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 应通过入队份数一次性生成多条任务,避免快速连点造成操作员误判。 + - `V3S Control` 子标签必须把 D601 `v3sctl-adapter` 控制面渲染为 UniDesk React 控件,包括 control plane 状态、manifest 列表、D601/D518 节点实例、active instance、single-writer/no-fallback 路径、Kubernetes API service proxy 状态、kubectl/v3s snapshot 摘要和显式原始 JSON 按钮;页面只能通过 `/api/microservices/v3sctl-adapter/proxy/api/control-plane` 取数,不得直接访问 provider-gateway、NodePort、业务容器端口或裸 v3s/kubectl API。 + - `Code Queue` 子标签必须把 D601 v3s/k8s `code-queue` Service 渲染为 UniDesk React 控件,前端 API 基址只能是 `/api/microservices/code-queue/proxy`,不能继续使用旧 `/api/code-queue-direct` 别名;页面包括多 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 d4408cb6..859d317d 100644 --- a/docs/reference/microservices.md +++ b/docs/reference/microservices.md @@ -7,9 +7,9 @@ UniDesk 用户服务是挂载到 UniDesk 核心服务上的、面向用户使用 ## Boundary - 用户服务后端端口默认只绑定计算节点本机地址,例如 `127.0.0.1:`,不得直接暴露公网。 -- 浏览器只访问 UniDesk frontend;frontend 通过同源 `/api/microservices/*` 代理到 backend-core,backend-core 再通过目标 provider-gateway 的 `microservice.http` 能力访问计算节点本机后端。 +- 浏览器只访问 UniDesk frontend;frontend 通过同源 `/api/microservices/*` 代理到 backend-core。`deployment.mode=unidesk-direct` 的用户服务由 backend-core 通过目标 provider-gateway 的 `microservice.http` 能力访问计算节点本机后端;`deployment.mode=v3sctl-managed` 的用户服务只允许经 `v3sctl-adapter` 微服务进入 v3s 标准服务路由,backend-core 不得直接向业务容器所在 provider 下发 `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` 这类节点本地地址,或明确登记为同一私有 Docker network 内的服务名;主 server 内置用户服务可使用同一 Compose 网络内的显式服务名,例如 `todo-note:4211`,D601 Code Queue 必须使用 provider-gateway network 内的 `code-queue:4222`。backend-core 还必须用 `allowedPathPrefixes` 和 `allowedMethods` 同时限制可代理路径和 HTTP 方法。 +- `microservice.http` 只允许 provider-gateway 访问 `http://127.0.0.1`、`http://localhost`、`http://host.docker.internal` 这类节点本地地址,或明确登记为同一私有 Docker network 内的服务名;主 server 内置用户服务可使用同一 Compose 网络内的显式服务名,例如 `todo-note:4211`。v3s 代管服务不得把业务容器地址登记成 provider-gateway 直连目标,`backend.proxyMode` 必须使用 `v3sctl-adapter-http`,`backend.nodeBaseUrl` 可使用 `v3s://` 这类逻辑服务名。backend-core 还必须用 `allowedPathPrefixes` 和 `allowedMethods` 同时限制可代理路径和 HTTP 方法。 ## Config Contract @@ -19,6 +19,7 @@ UniDesk 用户服务是挂载到 UniDesk 核心服务上的、面向用户使用 - `repository.url` 与 `repository.commitId`,用于记录业务代码的外部权威来源;UniDesk 不 vendoring 业务全量代码。 - `repository.dockerfile`、`repository.composeFile`、`repository.composeService` 和 `repository.containerName`,用于说明部署应复用业务仓库自身维护的 Dockerfile/docker-compose。 - `backend.nodeBaseUrl`、`backend.nodeBindHost`、`backend.nodePort`、`backend.proxyMode`、`backend.public=false`、`backend.frontendOnly=true`、`backend.allowedMethods`、`backend.allowedPathPrefixes` 和 `backend.healthPath`,用于定义计算节点端口到 UniDesk frontend-only 代理的映射。 +- `deployment.mode`,用于明确部署责任边界;`unidesk-direct` 表示 UniDesk 直接登记和探测目标 provider 上的容器,`v3sctl-managed` 表示 UniDesk 只登记逻辑服务并经 `deployment.adapterServiceId` 指向的 `v3sctl-adapter` 访问,代管条目还必须写明 `v3sServiceId`、`namespace`、`expectedNodeIds` 和当前 `activeNodeId`。 - `development.providerId`、`development.sshPassthrough=true` 和 `development.worktreePath`,用于说明开发调试入口必须在计算节点上通过 UniDesk SSH 透传完成。 - `frontend.route` 和 `frontend.integrated=true`,用于说明该业务前端已经整合到 UniDesk React 控制台,而不是继续公开业务自身前端。 @@ -122,32 +123,49 @@ 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 D601 +### V3S Control Plane Adapter On D601 -当前 Code Queue 作为 `id=code-queue` 的用户服务登记在 `config.json`,长期部署在 D601,并接入统一 `oa-event-flow` 发布 Trace/STEP 事实事件与读取统计中心: +`v3sctl-adapter` 是 UniDesk 直管的控制面适配微服务;它本身仍按 `deployment.mode=unidesk-direct` 登记在 D601,由 UniDesk 负责健康检查、重建和前端可见性,但它管理的业务服务必须走 v3s 标准服务路由,不得再被 backend-core 直接下发到业务容器所在 provider。 -- Provider:`D601`,由 D601 provider-gateway 通过 `microservice.http` 访问同一 provider-gateway Docker network 内的 `http://code-queue:4222`;`code-queue-backend` 仍可对 D601 host 绑定 `127.0.0.1:4222` 作为节点本地维护入口,但 UniDesk 正式代理链路不得依赖 `host.docker.internal:4222`,避免 Linux/Docker Desktop loopback 绑定差异导致 frontend 502。 -- 代码引用:`https://github.com/pikasTech/unidesk` 与配置中的 `repository.commitId`;服务源码位于 `src/components/microservices/code-queue`,属于 UniDesk 自有控制面组件。 -- 部署引用: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 运行时,必须用防火墙或等价策略限制来源,不得成为浏览器或任意公网客户端入口。 -- 默认出网代理:D601 `code-queue-backend` 必须默认把 `HTTP_PROXY`、`HTTPS_PROXY` 和 `ALL_PROXY` 注入给 Codex/OpenCode、`git`、`curl`、`npm` 等任务子进程;代理上游必须是 D601 provider-gateway 暴露在 provider-gateway Docker 网络内的 egress HTTP CONNECT 端口,而不是 Code Queue 自建伪 provider WebSocket 或交互 shell 临时 `export`。Code Queue Compose 必须加入 provider-gateway 网络,并通过 `CODE_QUEUE_EGRESS_PROXY_URL` 指向 `http://unidesk-provider-gateway-D601:18789`;provider-gateway 再复用已注册的 provider WebSocket 通道,把 TCP open/data/close 消息转发给主 server backend-core 出网,不依赖 D601 本地直连公网。`NO_PROXY` 必须覆盖 `localhost`、`127.0.0.1`、`host.docker.internal`、provider-gateway 容器名、主 server 地址和 UniDesk 内部服务名,避免 PostgreSQL、OA Event Flow、ClaudeQQ、microservice health 等内网链路绕远或递归进入代理;`/health` 必须暴露 egress proxy 的 `enabled`、`connected`、`proxyUrl`、`channel=provider-gateway` 和上游 provider-gateway health,作为 Codex 网络卡死排障的第一证据。远程开发/执行容器不得只依赖这些环境变量,必须在容器网络层用 TUN 默认路由和 OUTPUT 防火墙强制外网流量只能经 master TUN 出口。 -- 出网代理无 fallback 纪律:Code Queue 的运行时配置只允许一个默认出网路径,即 provider-gateway egress proxy;不得在代码中同时保留 Code Queue 自建 WebSocket proxy、临时 shell proxy、D601 本地直连公网、主 server direct HTTP proxy 等隐式分支。Compose 层必须显式设置大小写 `HTTP_PROXY`、`HTTPS_PROXY`、`ALL_PROXY` 和 `NO_PROXY`,服务启动后再把同一组变量写入 `process.env`,确保 service 自检、Codex/OpenCode app-server、任务 shell、`git`、`curl`、`npm` 使用一致路径。任何新增网络 fallback 都必须先进入本参考文档并配套 `/health` 可见状态,否则视为残留旧路径。 -- 上线纪律: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 上的 `~/cq-deploy` symlink 执行 `cd ~/cq-deploy && CODE_QUEUE_ENV_FILE=.state/code-queue-d601.env docker compose -f src/components/microservices/code-queue/docker-compose.d601.yml up -d --build --force-recreate code-queue` 或等价 build-first 路径,并用恢复后的 live API 或公网 frontend 证明任务和队列仍可读可继续;不要在 provider-gateway Host SSH 命令中使用 `/home/ubuntu/unidesk-code-queue-deploy` 全路径触发 provider-gateway 自保护误判。该命令必须由 D601 provider SSH 在宿主侧 detached 调度,不能从正在运行的 `code-queue-backend` 容器里以前台方式执行会重建自身的 Compose 命令;否则发起命令的容器被替换时可能中断远程任务并留下 `Created`/`Exited` 的半完成容器。若 registry metadata 临时不可达且只是恢复已构建镜像,可用同一路径的 `--no-build --force-recreate` 先恢复服务,再完成源码 build 验证。 -- 更名与灾备恢复:旧版 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 表。迁移完成后只允许在 D601 用 `docker compose -f src/components/microservices/code-queue/docker-compose.d601.yml up -d --build code-queue` 启动目标服务;禁止再通过主 server Compose 启动旧 `code-queue` service。 +- Provider:`D601`,由 D601 provider-gateway 仅维护和访问 `v3sctl-adapter` 的本机私有端口 `127.0.0.1:4266`;provider-gateway 不再作为 `code-queue` 业务请求的直接代理。 +- 代码引用:`https://github.com/pikasTech/unidesk` 与配置中的 `repository.commitId`;服务源码位于 `src/components/microservices/v3sctl-adapter`,属于 UniDesk 自有控制面组件。 +- 部署引用:UniDesk 仓库中的 `src/components/microservices/v3sctl-adapter/docker-compose.d601.yml`,Dockerfile 为 `src/components/microservices/v3sctl-adapter/Dockerfile`,容器名为 `v3sctl-adapter`。 +- v3s 实现:当前 `v3sctl-managed` 可以落到 k3s、k8s 或等价标准 Kubernetes 控制面,但必须使用 Kubernetes 原生命名空间、Deployment、Service、readiness/liveness probe、Kubernetes API service proxy 等规范对象;不得把裸容器端口、NodePort、SSH curl、provider-gateway `microservice.http` 或 host 直连地址伪装成 v3s 服务路由。 +- manifest:代管服务声明放在 `src/components/microservices/v3sctl-adapter/v3s/*.v3s.json`,adapter 启动时通过 `V3SCTL_MANIFEST_PATHS` 读取;manifest 是 D601/D518 实例、active instance、single writer、expected nodes 和 health policy 的权威来源。`V3SCTL_SERVICES_JSON` 不得承载 static HTTP 服务、不得覆盖同名服务、不得作为隐藏 fallback;如需追加服务也必须提供完整 `ManagedKubernetesService` manifest。 +- API:`GET /health` 只表示 adapter 控制面自身可用,并把代管服务 serving 健康作为 `managedServicesHealthy` 字段展示;`GET /api/control-plane` 返回控制面、manifest、kubectl/v3s snapshot 和代管服务状态;`GET /api/services` 返回代管服务列表;`GET|HEAD /api/services//health` 返回该 v3s 服务的 active serving 健康;`/api/services//proxy/*` 是业务请求进入 active service 的唯一代理入口。 +- 代理路径:adapter 访问代管业务服务的唯一正式路径是 Kubernetes API service proxy:`/api/v1/namespaces//services/:/proxy/...`。D601 与 D518 不要求能彼此直连;D518 加入时应优先通过 k3s/k8s 原生 agent/proxy/tunnel 能力让控制面可达该节点,必要时可用 provider 维护通道只承载控制面连接的建立和诊断,但业务请求不得退化为 provider-gateway 直连 Code Queue HTTP 端口。 +- 拓扑健康:`expectedNodeIds` 负责展示计划内节点,D518 尚未接入时必须保留 `missingNodeIds=["D518"]` 与 `status=degraded` 可见;只要 active D601 Service 通过 Kubernetes API service proxy 返回健康,`servingHealthy=true`、`healthy=true` 和 `managedServicesHealthy=true` 仍应成立。只有显式 `requireAllInstancesHealthy=true` 的服务才允许把缺失 standby/worker 节点提升为整体不健康。 +- 前端:`用户服务 / V3S Control` React 页面必须只通过 `/api/microservices/v3sctl-adapter/proxy/api/control-plane` 通信,展示控制面状态、manifest、D601/D518 实例、active instance、Kubernetes API service proxy/no-fallback 路径和显式原始 JSON 按钮;页面不得直接访问 provider-gateway、D601/D518 业务容器端口、NodePort 或 raw v3s/kubectl API。 + +### Code Queue V3S-Managed + +当前 Code Queue 作为 `id=code-queue` 的 `v3sctl-managed` 用户服务登记在 `config.json`,业务实例由 D601 v3s 控制面代管,并接入统一 `oa-event-flow` 发布 Trace/STEP 事实事件与读取统计中心: + +- Orchestrator:`deployment.mode=v3sctl-managed`,`deployment.adapterServiceId=v3sctl-adapter`,`deployment.v3sServiceId=code-queue`,`backend.proxyMode=v3sctl-adapter-http`,`backend.nodeBaseUrl=v3s://code-queue`;backend-core 对 Code Queue 的正式链路只能是 `frontend -> backend-core -> v3sctl-adapter -> Kubernetes API service proxy -> Kubernetes Service code-queue:4222`。 +- Direct path ban:`code-queue` 不得再登记 `http://code-queue:4222`、`http://host.docker.internal:4222`、NodePort 或 provider-gateway `microservice.http` 作为业务代理目标;frontend 也不得使用旧 `/api/code-queue-direct` 兼容别名作为 Code Queue 页面数据源。provider-gateway 只允许用于维护 D601/D518、部署 adapter、部署 v3s/k8s 节点或诊断节点本机容器。 +- 实例语义:D601 是默认 active/single-writer 实例,`CODE_QUEUE_INSTANCE_ID=D601` 且 `CODE_QUEUE_SCHEDULER_ENABLED=true`;D518 是 standby 实例,必须设置 `CODE_QUEUE_INSTANCE_ID=D518`、`CODE_QUEUE_SCHEDULER_ENABLED=false` 和 `CODE_QUEUE_STARTUP_OA_BACKFILL_ENABLED=false`,避免两个实例同时消费同一 PostgreSQL 队列或重复回放 OA 统计。D601 active 也默认关闭 `CODE_QUEUE_STARTUP_OA_BACKFILL_ENABLED`;历史 OA Trace/STEP 回填必须通过显式 `/api/oa/backfill` 运维动作触发,不能在每次 Pod 重启时自动批量发布旧事件。 +- 部署引用:Code Queue 镜像仍复用 `src/components/microservices/code-queue/Dockerfile`,Kubernetes 运行清单为 `src/components/microservices/v3sctl-adapter/v3s/code-queue.k8s.yaml`,`config.json` 对外记录 v3s manifest `src/components/microservices/v3sctl-adapter/v3s/code-queue.v3s.json`;主 server 根目录 `docker-compose.yml` 不包含 `code-queue` service,旧 D601 direct Compose 文件只作为迁移/本地诊断参考,不是正式运行入口。 +- 主服务依赖映射:Code Queue 仍以主 PostgreSQL 为权威数据库,`DATABASE_URL` 必须指向主 server 受限端口映射;`OA_EVENT_FLOW_BASE_URL` 必须指向主 server OA Event Flow 受限端口映射;D601 active 实例的 `CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL` 直接使用本机 ClaudeQQ 映射 `http://host.docker.internal:3290`。这些端口映射只服务受控节点运行时,必须用防火墙或等价策略限制来源,不得成为浏览器或任意公网客户端入口。 +- K8s 探针与启动维护:Kubernetes liveness/startup probe 必须使用轻量 `/live`,readiness 和用户服务健康使用 `/health`;`/health` 不得执行全量任务聚合、历史回填或长事务索引维护,历史任务总览应由 `/api/tasks/overview` 读取 PostgreSQL。启动时允许后台执行队列元数据 flush、通知 outbox 读取、任务表索引维护和 overview warmup,但这些维护不得阻塞 Bun server、readiness endpoint 或 frontend overview;通知表索引和大批量 OA backfill 不得作为默认启动副作用。 +- MiniMax/OpenCode 并发:`minimax-m2.7` 通过 OpenCode JSON 事件端口运行;每个 Code Queue task 必须使用独立的 OpenCode XDG data/config/cache/state 目录,禁止多队列并发任务共享同一个 OpenCode SQLite/WAL 状态目录,否则并发 smoke 会触发 `PRAGMA journal_mode = WAL` 之类的数据库锁或初始化错误。用于验证 v3s/k8s 链路的 MiniMax smoke 以“至少 4 个任务、分布到 2 个 queue、至少 2 个终态成功”为链路验收线;剩余失败如果是 OpenCode 最终回复捕获、业务任务判定或模型限流,应作为 Code Queue 执行可靠性问题单独排查,不能反推 v3s 代理链路失败。 +- 默认出网代理:D601 active Code Queue Pod 必须默认把 `HTTP_PROXY`、`HTTPS_PROXY` 和 `ALL_PROXY` 注入给 Codex/OpenCode、`git`、`curl`、`npm` 等任务子进程;当前唯一上游是 D601 provider-gateway 通过宿主 loopback 发布的 egress HTTP CONNECT 端口 `http://host.docker.internal:18789`,该端口只允许绑定 `127.0.0.1`,不得开放公网。这里的 provider-gateway 只承担出网代理,不承担 Code Queue 业务 HTTP 代理;业务访问仍只能走 Kubernetes API service proxy。k3s/k8s 原生 egress gateway、service mesh 或 CNI egress policy 只作为后续网络层增强方向,当前交付态不引入第二套出网控制面。远程开发/执行容器不得只依赖这些环境变量,必须在容器网络层用 TUN 默认路由和 OUTPUT 防火墙强制外网流量只能经 master TUN 出口。 +- 出网代理无 fallback 纪律:Code Queue 的运行时配置只允许一个默认出网路径,即 provider-gateway egress proxy;不得在代码中同时保留 Code Queue 自建 WebSocket proxy、临时 shell proxy、D601 本地直连公网、主 server direct HTTP proxy 等隐式分支。任何新增网络 fallback 都必须先进入本参考文档并配套 `/health` 可见状态,否则视为残留旧路径。 +- 上线纪律:Code Queue 相关的前端或后端改进必须在同一任务内正式上线并验证公网 frontend 或 live API,不能只停留在源码、构建产物或“后续再上线”。修改 Code Queue 自身时不得等待当前 Code Queue task 结束、等待 queue idle 或等待 `0 running` 后才重启;应通过 v3s 控制面或 D601/D518 维护入口做 build-first 替换,并用 v3s adapter、Code Queue live API 或公网 frontend 证明任务和队列仍可读可继续。 +- 更名与灾备恢复:旧版 Codex 队列服务名只允许作为兼容诊断和一次性迁移来源;`code-queue-backend` 容器自身 `/health` 正常但 `microservice health code-queue` 返回 provider 直连错误时,优先判定为 backend-core 仍加载旧 `MICROSERVICES_JSON` 或 adapter manifest 未刷新,必须刷新 `.state/docker-compose.env`、重建/替换 `backend-core` 与 `v3sctl-adapter`,随后用 `microservice list` 验证 `code-queue` 的 `runtime.orchestrator=v3sctl`、`backend.proxyMode=v3sctl-adapter-http` 和无业务容器直连摘要。 - 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++`、`iptables`、`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-`,并在 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 进程和旧 OUTPUT 跳转,缺失旧设备不能导致失败,冷启动运行时准备要有有界但足够的 timeout。TUN 建立后必须创建 `UD-CQ-EGRESS-` OUTPUT 链,规则只允许 loopback、既有连接、`tun` 出口以及到 master server 的 SSH tunnel 控制连接,随后 reject 其他 IPv4/IPv6 出站包;这条网络层封口是开发/执行容器的权威外网边界,不能用 `HTTP_PROXY`/`NO_PROXY` 环境变量替代,容器镜像也必须使用已解析出的唯一 `unidesk-code-queue:` 或显式 `image`,缺失时直接失败,禁止 provider-gateway image、`latest` 或其他隐式镜像 fallback。验收必须保留三类日志:容器建隧道后 `ping google.com` 成功、强制指定原 Docker 网卡直连外网被 `sealed_direct_ping=blocked_expected` 拦截、服务所在节点上对应 `UNIDESK-CODEX-DEV-` NAT 链或 `tun` 计数在 ping 前后增长;涉及 WSL 工作区任务时还必须在开发容器内验证目标 `/mnt/...` 路径可读。`GET /api/dev-containers//status` 必须展示默认路由、`route_8_8_8_8`、`egressFirewallChain` 和 OUTPUT 链跳转。开发容器代理密钥只生成到 `.state/code-queue/dev-proxy/` 与目标节点用户目录,不得提交到仓库。 - 远程维护桥调用:Code Queue 已迁移到 D601 后,`code-queue-backend` 容器内没有主 server 的 `unidesk-backend-core` 容器,不能再把 `bun scripts/cli.ts ssh ...` 实现为本地 `docker exec unidesk-backend-core`。Code Queue 后端发起的 provider 维护命令必须通过主 server frontend `/api/dispatch` 进入 backend-core,再由目标 provider-gateway 执行 `host.ssh`;需要传递脚本时必须使用 base64 临时文件,超过 Host SSH 单命令长度上限时分块上传到目标 `/tmp` 后再执行,避免恢复到本地 Docker broker、交互 stdin 或手工 shell fallback。 -- 远程 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 内返回,证明远程超时不会复发为全站刷新卡死。 +- 远程 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 或 frontend/core 用户服务代理等控制面请求等待远程 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 的状态,不能错误推进下一个任务或永久卡住。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 验收,不能把“避免重启”作为交付策略。 +- 稳定性与重启恢复: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` 再依赖后续命令补救,因为中断窗口会让 Pod/容器消失并触发 frontend/core 用户服务代理失败。重启后出现 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 验证。 - 内存优化过程与防回归: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 历史线性增长。 +- 列表/详情延迟优化原则:Code Queue 控制面交互的长期目标是常规历史规模下首屏、`GET /api/tasks/overview`、`POST /api/tasks//read` 和分页加载均在 1s 内完成;性能面板出现十几秒级 `core_proxy` 或 Code Queue 用户服务代理慢操作时,必须优先按后端查询形态和前后端通信策略定位,不能把问题归因于 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 用户服务代理 502、`/api/tasks/overview`/trace 接口成批超时,或容器内 `/health` 在 active output 持续追加时也卡住,优先按 Bun event-loop starvation/backpressure 排查,而不是先改 React 渲染;修复必须证明热路径不再随 output/archive 历史线性增长。 - Trace STEP 权威来源:`GET /api/tasks//trace-steps` 与 `GET /api/tasks//trace-step` 必须直接从 `oa-event-flow` 读取 `trace-step-created` 事实事件,并在响应中暴露 `source=oa-event-flow`;不得在 OA 事件缺失、读取失败或本地 transcript 数量更多/更少时静默回退到 `task-transcript`、Codex session JSONL、output archive 或内存热状态。OA 事件不可用应显式失败或返回空事实集,避免 STEP 计数和执行过程摘要重新形成双路径分叉。 - 完成判定: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 状态、错误名和响应预览。 - Judge 权威边界:MiniMax 成功返回可解析、预算内的 judge JSON 后,Code Queue 不得用旧 attempt 的 429/exceeded retry limit 证据、历史 output 字符串、面向特定任务的正则或 `hardCompletionBlockers`/`retryRequiredReasons` 覆盖一次协议有效的完成判定;尤其不能因为 attempt 1 的限流中断仍在历史输出里,就禁止 MiniMax 把 attempt 2 的正常完成判为 `complete`。允许的本地 safety override 必须限定为协议事实和系统交付纪律:用户显式打断、当前 attempt 未正常终止、当前 attempt 没有最终 assistant response、最终回复停在并发文件确认而非交付、或 runtime/UI/service 变更承认未部署验证。所有 override 都必须写入 `_safetyOverride`、生成紧凑 continuation prompt,并由自测或 judge probe 覆盖;不得把业务猜测伪装成本地硬门禁。 @@ -263,7 +281,8 @@ 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`:验证 D601 Code Queue 后端、主 PostgreSQL 强制持久化、统一 OA 事件发布和 D601 provider-gateway 私有代理链路;写入、追加 prompt、打断和 readAt/未读状态都必须由 backend 写入 PostgreSQL,frontend 不得用本地存储伪造成功状态。 +- `bun scripts/cli.ts microservice health v3sctl-adapter` 与 `bun scripts/cli.ts microservice proxy v3sctl-adapter /api/control-plane --raw`:验证 D601 v3s 控制面 adapter、manifest、D601/D518 实例状态和 no-fallback 运行路径。 +- `bun scripts/cli.ts microservice health code-queue` 与 `bun scripts/cli.ts microservice proxy code-queue /api/tasks/overview`:验证 Code Queue 经过 backend-core -> v3sctl-adapter -> v3s active service 的单一路径;输出不得出现 `serviceId=code-queue` 的 provider-gateway `microservice.http` 业务代理任务,写入、追加 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。 @@ -271,7 +290,7 @@ ClaudeQQ 在 UniDesk 语境中按消息网关后端服务管理:不得直接 ## Frontend Rules -用户服务前端必须整合到 `src/components/frontend/src/` 下的 TypeScript + React 模块中。`app.tsx` 只做 shell/router 和导入分发,业务页面必须拆成独立 TSX,例如 `todo-note.tsx`、`findjob.tsx`、`pipeline.tsx`、`met-nonlinear.tsx`、`code-queue.tsx`。默认展示必须是业务控件:指标卡、状态徽标、表格、草稿卡片、运行卡片、树形任务、表单控件、结构化材料索引、链接和字段摘要;只有操作员点击 `查看原始JSON` 时才允许打开原始 JSON 弹窗。日志、JSONL 和大块 JSON 不得在主界面按行展示,避免把裸数据伪装成 UI。 +用户服务前端必须整合到 `src/components/frontend/src/` 下的 TypeScript + React 模块中。`app.tsx` 只做 shell/router 和导入分发,业务页面必须拆成独立 TSX,例如 `todo-note.tsx`、`findjob.tsx`、`pipeline.tsx`、`met-nonlinear.tsx`、`code-queue.tsx`、`v3sctl.tsx`。默认展示必须是业务控件:指标卡、状态徽标、表格、草稿卡片、运行卡片、树形任务、表单控件、结构化材料索引、链接和字段摘要;只有操作员点击 `查看原始JSON` 时才允许打开原始 JSON 弹窗。日志、JSONL 和大块 JSON 不得在主界面按行展示,避免把裸数据伪装成 UI。 对于超大业务 JSON,backend-core 可把 `__unideskArrayLimit=:` 作为 frontend-only 代理参数传给 provider-gateway,由 provider-gateway 在返回前裁剪指定 JSON 数组并写入 `_unidesk.arrayLimits` 元数据。该参数只用于控制 UniDesk 展示预览,不能替代业务后端自身分页 API 的长期设计。CLI 的 `microservice proxy` 还会对超过默认阈值的 body 做二次有界预览,防止人工验证时输出爆炸;只有显式 `--raw` 才允许倾倒完整 body。 @@ -283,16 +302,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=D601`、`public=false`、`frontendOnly=true`、UniDesk 仓库 URL、`127.0.0.1:4222` 映射和 D601 `code-queue-backend` 容器摘要可见。 +- 在主 server 运行 `bun scripts/cli.ts microservice list`,确认 `v3sctl-adapter` 为 `providerId=D601`、`deployment.mode=unidesk-direct`、后端私有端口 `127.0.0.1:4266`,并确认 `code-queue` 为 `deployment.mode=v3sctl-managed`、`runtime.orchestrator=v3sctl`、`backend.proxyMode=v3sctl-adapter-http`、`backend.nodeBaseUrl=v3s://code-queue`,且不再显示业务容器直连摘要。 - 在主 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、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 v3sctl-adapter`、`bun scripts/cli.ts microservice proxy v3sctl-adapter /api/control-plane --raw`、`bun scripts/cli.ts microservice health code-queue` 与 `bun scripts/cli.ts microservice proxy code-queue /api/tasks/overview`,确认真实链路经过 backend-core -> v3sctl-adapter -> v3s active service;Code Queue `/health` 必须仍返回业务后端自己的 `queue.storage.primary=postgres`、`queue.storage.postgresReady=true` 和 `queue.notifications.claudeqq.outbox.storage=postgres`,不得被 adapter 聚合健康 JSON 替代。还必须在 active Code Queue Pod 内验证主 PostgreSQL 端口映射、主 OA Event Flow 端口映射和本机 ClaudeQQ `http://host.docker.internal:3290` 均可访问,并在 adapter 控制页确认 D601 active serving healthy、D518 expected/missing 可见且整体不退化为 hidden fallback。再通过公网 frontend 提交一个 `gpt-5.5` 小任务,确认队列串行推进、输出实时更新、结束后有 judge 判定,且运行中可追加 prompt 或打断。Code Queue 的重启恢复必须作为验收项:运行中任务存在时重启或重建 active 实例后,任务必须从 PostgreSQL 恢复到可继续执行状态,不能丢失 active task、`promptHistory`、后续 queued 任务、readAt/未读状态或已入 outbox 的 ClaudeQQ 通知。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、v3s adapter 私有代理、PostgreSQL 队列和任务列表都指向 `code-queue`。批量验收必须通过公网 frontend 设置 `入队份数=5` 或使用多段 prompt 分隔,一次性入队 5 条任务,并确认 5 条任务按顺序进入 running/judging/succeeded,而不是只运行第一条。 +- Code Queue 内存防回归验收:凡是改动 Code Queue 的持久化、scheduler、输出/Trace、health、列表/详情查询、日志导出或容器运行参数,交付前必须在 D601 用 `kubectl -n unidesk get deploy,pod,svc,endpoints -o wide`、`kubectl -n unidesk describe deploy/code-queue` 或等价 Docker inspect 确认 memory/swap 硬上限符合预算,运行 `kubectl -n unidesk top pod` 或 Docker stats 确认常驻内存、`OOMKilled=false` 和 `RestartCount` 未异常增长,再运行 `bun scripts/cli.ts microservice health code-queue` 确认 `/health` 是轻量 readiness 且暴露 PostgreSQL/notification/outbox 状态。验收还必须覆盖有历史任务存在时的 `/api/tasks/overview`、单任务详情和 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 Code Queue 请求路径,交付前必须在有历史任务数据且有 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 Pod `/health` 与 `/api/tasks/overview` curl、性能面板 `/api/performance` 与 `/api/frontend-performance` 失败/慢操作记录、`kubectl -n unidesk top pod` 或 Docker stats 补充后端耗时、代理 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/observability.md b/docs/reference/observability.md index ae653112..1bb66c13 100644 --- a/docs/reference/observability.md +++ b/docs/reference/observability.md @@ -30,8 +30,8 @@ backend-core 必须提供 `/api/performance`,返回滚动窗口内的 HTTP 组 frontend Bun server 必须提供同源 `/api/frontend-performance`,记录 webui 静态资源、登录/session、API 代理和 frontend->core 代理操作耗时。浏览器中的 `运行总览 / 性能面板` 必须把 frontend 与 backend-core 指标合并展示为 Bwebui 曲线、组件汇总、最近失败请求、内部操作汇总和最近慢操作;完整性能 JSON 只能通过显式 `查看原始JSON` 打开。 -性能优化必须先用这些指标锁定慢操作名称、路径、耗时和代理层级,再改后端查询或前后端通信策略;不得只凭主观体感改 UI。Code Queue 这类控制面页面出现 `code_queue_direct_proxy`、`core_proxy`、`GET /api/tasks/overview`、`POST /api/tasks//read` 等超过 1s 的慢操作时,应保留优化前后的性能面板证据,并同时记录 live API 耗时、容器内存、`/health` 存储摘要和是否仍通过 PostgreSQL/append-only archive 重建历史数据。短 TTL cache、warmup 或页面内存缓存只能作为重复请求抖动保护,性能证据必须证明数据库索引/聚合、分页和渐进式披露本身已把核心路径降到目标内,不能用长缓存遮蔽慢 SQL 或全量 JSON 物化。 +性能优化必须先用这些指标锁定慢操作名称、路径、耗时和代理层级,再改后端查询或前后端通信策略;不得只凭主观体感改 UI。Code Queue 这类控制面页面出现 `core_proxy`、`GET /api/microservices/code-queue/proxy/api/tasks/overview`、`POST /api/microservices/code-queue/proxy/api/tasks//read` 等超过 1s 的慢操作时,应保留优化前后的性能面板证据,并同时记录 live API 耗时、容器内存、`/health` 存储摘要和是否仍通过 PostgreSQL/append-only archive 重建历史数据。短 TTL cache、warmup 或页面内存缓存只能作为重复请求抖动保护,性能证据必须证明数据库索引/聚合、分页和渐进式披露本身已把核心路径降到目标内,不能用长缓存遮蔽慢 SQL 或全量 JSON 物化。 -当最近失败请求集中出现 frontend `webui_api_proxy` 502,路径为 `/api/code-queue-direct/...` 的 overview、trace 或 summary,且 `code-queue-backend` 容器仍在运行时,必须区分“上游进程不可达”和“上游 event loop 被热路径同步工作饿死”。排障顺序是同时查看 `/api/frontend-performance`、`/api/performance`、容器直连 `/health`/overview/trace-step curl、`docker stats`、容器 `RestartCount`/`OOMKilled` 和 Code Queue 日志;如果容器直连 `/health` 也超时,应优先检查实时 output/SSE 发布、archive 读取、transcript 构建、统计计算和远程 Provider 准备/SSH 子进程是否在 active output 追加或任务入队启动时阻塞 event loop,而不是先调整 frontend 渲染或代理超时。涉及 D601 等远程 Provider 时,还要检查 `runCodeQueueSsh`/开发容器准备是否仍存在同步子进程、无 timeout 的 SSH、无上限 stdout/stderr 或 stale TUN 重建等待;修复后必须在远程准备探针运行期间并发证明容器直连 `/health` 与 `/api/tasks/overview` 仍快速返回。 +当最近失败请求集中出现 frontend `core_proxy` 502,路径为 `/api/microservices/code-queue/proxy/...` 的 overview、trace 或 summary,且 v3s/k8s Pod 仍在运行时,必须区分“Kubernetes API service proxy 不可达”“Code Queue 进程不可达”和“Code Queue event loop 被热路径同步工作饿死”。排障顺序是同时查看 `/api/frontend-performance`、`/api/performance`、`v3sctl-adapter` `/api/control-plane`、Kubernetes Pod `/live`、`/health`、overview/trace-step curl、`kubectl top pod` 或 Docker stats、容器 `RestartCount`/`OOMKilled` 和 Code Queue 日志;如果 Pod 内 `/health` 也超时,应优先检查实时 output 发布、archive 读取、transcript 构建、统计计算、启动维护、历史 OA backfill 和远程 Provider 准备/SSH 子进程是否阻塞 event loop,而不是先调整 frontend 渲染或代理超时。Code Queue 默认不得在启动时自动执行历史 OA backfill 或通知表索引维护;显式 backfill 必须作为运维动作记录,并在运行期间并发证明 `/live`、`/health` 与 `/api/tasks/overview` 仍快速返回。涉及 D601 等远程 Provider 时,还要检查 `runCodeQueueSsh`/开发容器准备是否仍存在同步子进程、无 timeout 的 SSH、无上限 stdout/stderr 或 stale TUN 重建等待;修复后必须在远程准备探针运行期间并发证明 Pod `/health` 与 `/api/tasks/overview` 仍快速返回。 Code Queue task 明明产出最终回复却反复 `retry_wait` 时,应优先用任务详情里的 latest attempt 字段核查 `terminalStatus`、`transportClosedBeforeTerminal`、`appServerExitCode`、`finalResponseChars`、`judge.raw._safetyOverride` 和 attempt output。OpenCode 远程任务中,`opencode completed status=completed exit=0` 加当前 attempt 非空 assistant 输出应对应 `terminalStatus=completed`、`transportClosedBeforeTerminal=false`;如果因为缺少 `step_finish` 事件仍触发 `_safetyOverride=terminal_not_completed`,说明协议终态归一化有回归。相反,当前 attempt 没有最终 assistant response 时即使 tool/read/bash 证据完整,也必须 retry,不能用旧 `task.finalResponse` 或 reasoning/tool evidence 代替可见最终回复。 diff --git a/docs/reference/provider-gateway.md b/docs/reference/provider-gateway.md index 93c318e6..31f27e64 100644 --- a/docs/reference/provider-gateway.md +++ b/docs/reference/provider-gateway.md @@ -10,7 +10,7 @@ Provider Gateway 是计算节点侧容器。它只主动连出到主 server 暴 计算节点 `provider-gateway` 容器的重建和升级权威路径是 `provider.upgrade` 的 `mode: "schedule"`,或 frontend 中等价的显式升级调度。该路径由在线 provider 通过本地 Docker socket 启动 detached updater 容器,让升级动作脱离当前 WebSocket 与 SSH 透传会话的生命周期;重建目标只能是 `provider-gateway` service,并且必须带 `--no-deps` 与 `--force-recreate`,不得牵连 database、backend-core、frontend 或业务用户服务,也不得因为镜像 tag 未变而 no-op。 -远程升级必须采用 sleep-and-validate 回滚保护:旧 gateway 在成功调度 updater 后关闭当前 WebSocket 并进入最长 5 分钟的助眠期;updater 先构建新镜像,再用旧容器的环境变量、挂载、网络和 `extra_hosts` 拉起候选 gateway;候选 gateway 必须在日志中出现 `connect_open` 和 register ack 成功,才允许把候选容器 restart policy 改为 `always`、删除旧 gateway、并把候选容器改名为原容器名。候选验证失败时 updater 必须删除候选容器并退出失败,旧 gateway 到达助眠上限后自动重连主 server,形成自动回滚。backend-core 必须在同一 Provider ID 被新 WebSocket 替换后忽略旧 WebSocket 的 close 事件,避免候选已上线后又被旧连接关闭标记为 offline。 +远程升级必须采用 sleep-and-validate 回滚保护:旧 gateway 在成功调度 updater 后关闭当前 WebSocket 并进入最长 5 分钟的助眠期;updater 先构建新镜像,再用旧容器的环境变量、挂载、网络和 `extra_hosts` 拉起候选 gateway;候选 gateway 必须在日志中出现 `connect_open` 和 register ack 成功,才允许删除旧 service 容器和候选容器,并用原 Compose service 重新创建最终 provider-gateway 容器。最终容器必须重新验证 `restart=always` 与 `pid=host`,避免候选临时容器命名或端口映射残留成第二条运行路径。候选验证失败时 updater 必须删除候选容器并退出失败,旧 gateway 到达助眠上限后自动重连主 server,形成自动回滚。backend-core 必须在同一 Provider ID 被新 WebSocket 替换后忽略旧 WebSocket 的 close 事件,避免候选已上线后又被旧连接关闭标记为 offline。 禁止通过 UniDesk 自己的 Host SSH / WSL SSH 透传同步执行 `docker compose up -d --build provider-gateway`、`docker compose restart provider-gateway`、`docker rm -f ` 后再启动等自重建命令。原因是这条 SSH 透传连接正由被重建的旧 `provider-gateway` 容器承载;旧容器停止后会切断控制通道,可能把节点留在旧容器已停、新容器未起的不可达状态。SSH 透传只允许用于诊断、修复升级前置条件、查看本地状态和升级后验证,不允许作为计算节点 `provider-gateway` 正式重建/升级通道。 @@ -20,7 +20,7 @@ Provider Gateway 是计算节点侧容器。它只主动连出到主 server 暴 当前主 server 公网 IP 是 `74.48.78.17`,`config.json` 中的 `network.publicHost` 必须保持为该地址;公网 frontend 入口是 `http://74.48.78.17:18081/`,provider gateway 对外接入入口是 `ws://74.48.78.17:18082/ws/provider`,provider ingress 健康检查是 `http://74.48.78.17:18082/health`。主 server 本机 provider 由根目录 `docker-compose.yml` 的 `provider-gateway` 服务启动,容器内使用 Docker 内网地址 `ws://backend-core:8081/ws/provider` 自接入;外部计算节点部署 provider-gateway 时必须改用公网 provider ingress URL。 -新增计算节点推荐使用两项配置的简化挂载流程:在目标节点的 UniDesk 仓库根目录运行 `bun scripts/cli.ts provider attach --master-server http://74.48.78.17/ --up`;如果主 server 仍是默认地址,`--master-server` 可省略。该命令生成 `.state/provider-.env` 和 `provider-.yml`,env 文件默认只保留 `UNIDESK_MASTER_SERVER` 与 `PROVIDER_ID` 两项,Compose 固定 `restart: always`、`pid: "host"`、Docker socket、只读 `/workspace` 仓库挂载、日志目录和 `/run/host-ssh` 维护私钥目录。provider-gateway 会从 `UNIDESK_MASTER_SERVER=http://74.48.78.17/` 自动派生 `ws://74.48.78.17:18082/ws/provider`,并自动补齐 `PROVIDER_NAME`、默认 labels、心跳/重连参数、`DOCKER_SOCKET_PATH`、`MONITOR_DISK_PATH`、`PROVIDER_UPGRADE_*`、runner image 和日志路径;远程升级所需的宿主仓库路径会优先通过 Docker inspect 反查当前容器 `/workspace` 挂载源,避免手写 `/home/ubuntu/unidesk`、Compose project、env file 或 runner image 时出错。显式环境变量仍可覆盖这些默认值;如果主 server 的 provider token 已改成非默认值,挂载时只额外传一次 `--provider-token ` 或在 env 文件中加入 `PROVIDER_TOKEN`。 +新增计算节点推荐使用两项配置的简化挂载流程:在目标节点的 UniDesk 仓库根目录运行 `bun scripts/cli.ts provider attach --master-server http://74.48.78.17/ --up`;如果主 server 仍是默认地址,`--master-server` 可省略。该命令生成 `.state/provider-.env` 和 `provider-.yml`,env 文件默认只保留 `UNIDESK_MASTER_SERVER` 与 `PROVIDER_ID` 两项,Compose 固定 `restart: always`、`pid: "host"`、Docker socket、只读 `/workspace` 仓库挂载、日志目录、`/run/host-ssh` 维护私钥目录和 `127.0.0.1:18789->18789/tcp` loopback egress proxy 映射。provider-gateway 会从 `UNIDESK_MASTER_SERVER=http://74.48.78.17/` 自动派生 `ws://74.48.78.17:18082/ws/provider`,并自动补齐 `PROVIDER_NAME`、默认 labels、心跳/重连参数、`DOCKER_SOCKET_PATH`、`MONITOR_DISK_PATH`、`PROVIDER_UPGRADE_*`、runner image 和日志路径;远程升级所需的宿主仓库路径会优先通过 Docker inspect 反查当前容器 `/workspace` 挂载源,避免手写 `/home/ubuntu/unidesk`、Compose project、env file 或 runner image 时出错。显式环境变量仍可覆盖这些默认值;如果主 server 的 provider token 已改成非默认值,挂载时只额外传一次 `--provider-token ` 或在 env 文件中加入 `PROVIDER_TOKEN`。 手写 Compose 仍必须满足同一部署约束:挂载 `/var/run/docker.sock:/var/run/docker.sock` 作为 Docker 状态采集、任务执行和远程升级的唯一自动化通道,并让 provider-gateway 容器运行在宿主 PID namespace;Compose 写法是 `pid: "host"`,`docker run` 写法是 `--pid host`。缺少该配置时只能看到 provider 容器命名空间内的进程,不能视为完整节点资源监控。provider-gateway 容器必须使用 Docker restart policy `always`;`unless-stopped`、空 restart policy、手动 `docker stop` 后期待 Docker daemon 重启自动拉起,都不符合长期接入要求。长期接入节点必须保留只读 `/workspace` 仓库挂载,使 `provider.upgrade mode=schedule` 能构建候选 gateway 且只重建 `provider-gateway` service,不影响 database、backend-core、frontend 或业务用户服务。provider-gateway 部署必须同时交付 Host SSH / WSL SSH 透传维护桥;WSL 节点默认把私钥目录挂载到 `/run/host-ssh` 后,gateway 会在发现 `/run/host-ssh/id_ed25519` 时自动使用 `host.docker.internal:22`、从仓库路径推断 WSL 用户与默认工作目录,必要时仍可用 `HOST_SSH_HOST`、`HOST_SSH_PORT`、`HOST_SSH_USER`、`HOST_SSH_KEY`、`HOST_REMOTE_CWD` 显式覆盖。 @@ -40,7 +40,7 @@ WSL 节点应优先使用 WSL 内部原生 Docker Engine 和 `/var/run/docker.so WSL provider 的最小环境文件应放在节点本地私有路径,例如 `/home/ubuntu/unidesk/.state/provider-.env`,并由生成的 `provider-.yml` 或 `docker run --env-file` 读取。新挂载默认只写 `UNIDESK_MASTER_SERVER` 与 `PROVIDER_ID`;如果需要覆盖 labels,`PROVIDER_LABELS_JSON` 在 Docker env-file 中可以写成单行 JSON,临时用 shell `source` 调试时必须对整段 JSON 加引号,否则 shell 会按 `{}` 和逗号拆分导致 JSON 解析失败。不写 labels 时 provider-gateway 会根据 Provider ID、Docker、WSL 内核和 `/etc/os-release` 自动生成 `host`、`role`、`docker`、`wsl`、`distro` 与 `attachMode=simple`,并在运行时追加 `runtime`、`dockerSocketPresent`、gateway 版本和 `gatewayUptimeSeconds`。`.state/provider-.env`、`provider-.yml`、`logs/provider-/` 和容器日志属于节点本地运行态,必须保持在 `.gitignore` 覆盖范围内,不能提交 provider token、登录态或运行日志。 -长期运行推荐用 systemd 管理 provider-gateway 容器,而不是只在交互 shell 中运行 Bun 进程。systemd unit 的稳定形态是:`ExecStartPre=-docker rm -f unidesk-provider-gateway-` 清理同名旧容器,`ExecStart=docker run --restart always --pid host --name unidesk-provider-gateway- --env-file ... -v /var/run/docker.sock:/var/run/docker.sock -v /home/ubuntu/unidesk:/workspace:ro -v /home/ubuntu/unidesk/logs/provider-:/var/log/unidesk -v :/run/host-ssh:ro unidesk_provider-gateway:`,`ExecStop=docker stop unidesk-provider-gateway-`,并设置 `Restart=always`。临时部署也必须使用 `docker run -d --restart always --pid host`,并保证容器名、env 文件、日志目录、SSH 私钥只读挂载和镜像 tag 都带上节点 ID,便于 frontend、Docker 状态、SSH 透传、进程资源表和本地排障互相对应。`provider.upgrade` 是长期接入节点的必备能力,provider-gateway 不提供 `PROVIDER_UPGRADE_ENABLED` 或等价禁用开关;如果节点缺少升级环境变量或 SSH 透传环境变量,必须修正节点部署,而不是在服务端接受只能预检、不能升级或不能维护透传的半成品状态。 +长期运行推荐用 systemd 管理 provider-gateway 容器,而不是只在交互 shell 中运行 Bun 进程。systemd unit 的稳定形态是:`ExecStartPre=-docker rm -f unidesk-provider-gateway-` 清理同名旧容器,`ExecStart=docker run --restart always --pid host --name unidesk-provider-gateway- --env-file ... -p 127.0.0.1:18789:18789 -v /var/run/docker.sock:/var/run/docker.sock -v /home/ubuntu/unidesk:/workspace:ro -v /home/ubuntu/unidesk/logs/provider-:/var/log/unidesk -v :/run/host-ssh:ro unidesk_provider-gateway:`,`ExecStop=docker stop unidesk-provider-gateway-`,并设置 `Restart=always`。临时部署也必须使用 `docker run -d --restart always --pid host -p 127.0.0.1:18789:18789`,并保证容器名、env 文件、日志目录、SSH 私钥只读挂载和镜像 tag 都带上节点 ID,便于 frontend、Docker 状态、SSH 透传、进程资源表和本地排障互相对应。`provider.upgrade` 是长期接入节点的必备能力,provider-gateway 不提供 `PROVIDER_UPGRADE_ENABLED` 或等价禁用开关;如果节点缺少升级环境变量或 SSH 透传环境变量,必须修正节点部署,而不是在服务端接受只能预检、不能升级或不能维护透传的半成品状态。 WSL 本身会在没有前台进程时被 Windows 回收;如果该节点要作为长期在线算力,必须通过 Windows 启动项、计划任务或后台 `wsl.exe -d -u root -- bash -lc "systemctl start docker unidesk-provider-gateway-.service; exec sleep infinity"` 这类 keepalive 进程保持发行版运行。仅启用 WSL 内 systemd service 不等价于 Windows 层面的常驻守护。 @@ -86,17 +86,17 @@ 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 后端可使用 Compose 服务名 `http://todo-note:4211`,D601 Code Queue 必须使用 D601 本机映射 `http://host.docker.internal:4222`。该能力不打开 provider-gateway 入站端口,也不替代业务仓库自身 Dockerfile/docker-compose。 +`microservice.http` 是 provider-gateway 给 `deployment.mode=unidesk-direct` 用户服务使用的私有后端访问能力。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`。`deployment.mode=v3sctl-managed` 的 Code Queue 不得通过 provider-gateway `microservice.http` 直连业务容器,正式路径只能是 backend-core -> `v3sctl-adapter` -> Kubernetes API service proxy -> v3s/k8s Service。该能力不打开 provider-gateway 入站端口,也不替代业务仓库自身 Dockerfile/docker-compose。 超大 JSON 响应可以使用 `jsonArrayLimits` 在 provider-gateway 返回前裁剪指定数组,并在响应体中写入 `_unidesk.arrayLimits` 元数据,便于 UniDesk frontend 预览列表而不展示裸 JSON。长期应优先推动业务后端提供分页 API;裁剪只是 UniDesk 集成层的展示保护。 ## Egress Proxy -provider-gateway 可以在节点本地 Docker 网络内提供 egress HTTP CONNECT 代理,用于让 Code Queue、Pipeline runner 等节点侧执行容器通过既有 provider WebSocket 通道出网。代理默认监听容器内 `0.0.0.0:18789`,不需要公网端口;使用方必须加入 provider-gateway 的 Docker network,并把 `HTTP_PROXY`、`HTTPS_PROXY`、`ALL_PROXY` 指向 provider-gateway 容器名。代理只负责把本地 CONNECT/absolute HTTP 请求转换为 `egress_tcp_open`、`egress_tcp_data`、`egress_tcp_close` 消息;backend-core 在主 server 侧建立真实 TCP 连接并把数据回传,避免 D601 等计算节点本地网络不可达时卡死 Codex/Git/NPM。 +provider-gateway 可以提供 egress HTTP CONNECT 代理,用于让 Code Queue、Pipeline runner 等节点侧执行环境通过既有 provider WebSocket 通道出网。代理默认监听容器内 `0.0.0.0:18789`,节点部署必须只发布为宿主 loopback `127.0.0.1:18789->18789/tcp`,不得开放公网端口;普通 Docker 执行容器可通过同一私有 Docker network 访问 provider-gateway 容器名,v3s/k8s Pod 统一通过 `host.docker.internal:18789` 访问该 loopback 映射。代理只负责把本地 CONNECT/absolute HTTP 请求转换为 `egress_tcp_open`、`egress_tcp_data`、`egress_tcp_close` 消息;backend-core 在主 server 侧建立真实 TCP 连接并把数据回传,避免 D601 等计算节点本地网络不可达时卡死 Codex/Git/NPM。 该能力属于 provider-gateway 通道能力,register/heartbeat 的 `unideskCapabilities` 必须包含 `network.egress-proxy`,labels 必须上报 `providerGatewayEgressProxy*` 状态。不得再为某个用户服务单独注册伪 provider 来实现出网代理;否则节点列表会出现虚假 provider,且代理、统计、升级路径会形成多套通道。代理健康检查使用 `GET /__unidesk/egress-proxy/health`,返回 `connected`、`providerId`、`activeTunnels` 和监听端口;业务服务自己的 `/health` 应把该结果作为排障证据透出。 -egress proxy 的长期边界是“统一 provider 通道,不引入第二控制面”。backend-core 只接受在线 provider socket 上的 `egress_tcp_*` 消息,并在该 socket 关闭时销毁全部对应 TCP relay;provider-gateway 只维护本地 HTTP proxy 与 WebSocket 消息映射,不保存业务状态,不参与任务调度、统计或节点注册以外的控制面。执行容器、用户服务和 Pipeline runner 不允许直接连接 backend-core provider ingress,也不允许携带 provider token 自行注册;需要出网时只能连接同节点 provider-gateway 暴露在私有 Docker network 内的 proxy endpoint。 +egress proxy 的长期边界是“统一 provider 通道,不引入第二控制面”。backend-core 只接受在线 provider socket 上的 `egress_tcp_*` 消息,并在该 socket 关闭时销毁全部对应 TCP relay;provider-gateway 只维护本地 HTTP proxy 与 WebSocket 消息映射,不保存业务状态,不参与任务调度、统计或节点注册以外的控制面。执行容器、用户服务和 Pipeline runner 不允许直接连接 backend-core provider ingress,也不允许携带 provider token 自行注册;需要出网时只能连接同节点 provider-gateway 的私有 proxy endpoint。当前 v3s/k8s Code Queue 采用 `host.docker.internal:18789`,这是节点 loopback egress 入口,不是业务 HTTP 代理入口,也不能替代 Kubernetes API service proxy。 故障语义必须显式,不允许静默 fallback。provider-gateway 到 backend-core 的 WebSocket 未连接时,本地 proxy 必须返回 503;执行容器不能自动绕过到 D601 本地直连公网、外部公共代理或主 server 公网 HTTP 端口。`NO_PROXY` 只用于 PostgreSQL、OA Event Flow、ClaudeQQ、frontend/backend-core 内网代理、provider-gateway health 等明确内网链路,不能把 GitHub、模型 API、npm registry 等外部目标加入绕过列表。验收必须同时证明 provider-gateway labels、业务服务 `/health` 和执行容器内 `curl -I https://...` 都走同一 proxy path。 diff --git a/docs/reference/repo-tree.md b/docs/reference/repo-tree.md index f1c366b0..f17ef215 100644 --- a/docs/reference/repo-tree.md +++ b/docs/reference/repo-tree.md @@ -57,6 +57,9 @@ - src/findjob.tsx (FindJob user-service React page; do not fold back into `app.tsx`) - src/pipeline.tsx (Pipeline user-service React page and React Flow control graph; do not fold back into `app.tsx`) - src/met-nonlinear.tsx (MET Nonlinear D601 training orchestration React page; do not fold back into `app.tsx`) + - src/code-queue.tsx (Code Queue user-service React page; do not fold back into `app.tsx`) + - src/oa-event-flow.tsx (Unified OA event flow and Trace/STEP stats React page; do not fold back into `app.tsx`) + - src/v3sctl.tsx (V3S Control Plane React page backed only by `v3sctl-adapter`; do not fold back into `app.tsx`) - public/ (HTML/CSS static assets for the compact industrial console; no handwritten app JS) - provider-gateway/ (Compute node Provider Gateway container) - package.json @@ -67,5 +70,8 @@ - database/ (PostgreSQL initialization and configuration) - config/postgresql.conf - init/001_unidesk_init.sql - - microservices/ (Compatibility path reserved for future stateless user services) + - microservices/ (UniDesk-owned user services and compatibility examples) + - code-queue/ (Codex/OpenCode queue backend; v3s-managed when exposed through UniDesk) + - oa-event-flow/ (Unified OA event ledger, tag stream, and Trace/STEP stats center) + - v3sctl-adapter/ (D601 v3s control-plane adapter and managed service manifests) - example-service/ diff --git a/scripts/src/check.ts b/scripts/src/check.ts index c93fb2fa..5e83d89a 100644 --- a/scripts/src/check.ts +++ b/scripts/src/check.ts @@ -34,6 +34,7 @@ function unifiedLogRotationItem(): CheckItem { "src/components/frontend/src/index.ts", "src/components/provider-gateway/src/index.ts", "src/components/microservices/code-queue/src/index.ts", + "src/components/microservices/v3sctl-adapter/src/index.ts", "src/components/microservices/project-manager/src/index.ts", "src/components/microservices/baidu-netdisk/src/index.ts", "src/components/microservices/oa-event-flow/src/index.ts", @@ -66,6 +67,7 @@ export function runChecks(config: UniDeskConfig): { ok: boolean; items: CheckIte fileItem("src/components/frontend/src/index.ts"), fileItem("src/components/provider-gateway/src/index.ts"), fileItem("src/components/microservices/oa-event-flow/src/index.ts"), + fileItem("src/components/microservices/v3sctl-adapter/src/index.ts"), fileItem("scripts/src/e2e.ts"), unifiedLogRotationItem(), commandItem("bun:version", ["bun", "--version"]), diff --git a/scripts/src/config.ts b/scripts/src/config.ts index 648c64d3..a733e8f4 100644 --- a/scripts/src/config.ts +++ b/scripts/src/config.ts @@ -66,6 +66,14 @@ export interface UniDeskMicroserviceConfig { healthPath: string; timeoutMs: number; }; + deployment: { + mode: "unidesk-direct" | "v3sctl-managed"; + adapterServiceId?: string; + v3sServiceId?: string; + namespace?: string; + expectedNodeIds?: string[]; + activeNodeId?: string; + }; development: { providerId: string; sshPassthrough: boolean; @@ -114,12 +122,25 @@ function booleanField(obj: Record, key: string, path: string): return value; } +function optionalStringField(obj: Record, key: string, path: string): string | undefined { + const value = obj[key]; + if (value === undefined) return undefined; + if (typeof value !== "string" || value.length === 0) throw new Error(`${path}.${key} must be a non-empty string`); + return value; +} + function optionalArray(value: unknown, name: string): Record[] { if (value === undefined) return []; if (!Array.isArray(value)) throw new Error(`${name} must be an array`); return value.map((item, index) => asRecord(item, `${name}[${index}]`)); } +function optionalStringArrayField(obj: Record, key: string, path: string): string[] | undefined { + const value = obj[key]; + if (value === undefined) return undefined; + return stringArrayField(obj, key, path); +} + function stringArrayField(obj: Record, key: string, path: string): string[] { const value = obj[key]; if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || item.length === 0)) { @@ -146,6 +167,11 @@ function microserviceConfig(item: Record, index: number): UniDe const backend = asRecord(item.backend, `${path}.backend`); const development = asRecord(item.development, `${path}.development`); const frontend = asRecord(item.frontend, `${path}.frontend`); + const deployment = item.deployment === undefined ? undefined : asRecord(item.deployment, `${path}.deployment`); + const deploymentMode = deployment === undefined ? "unidesk-direct" : stringField(deployment, "mode", `${path}.deployment`); + if (deploymentMode !== "unidesk-direct" && deploymentMode !== "v3sctl-managed") { + throw new Error(`${path}.deployment.mode must be unidesk-direct or v3sctl-managed`); + } return { id: stringField(item, "id", path), name: stringField(item, "name", path), @@ -171,6 +197,16 @@ function microserviceConfig(item: Record, index: number): UniDe healthPath: stringField(backend, "healthPath", `${path}.backend`), timeoutMs: numberField(backend, "timeoutMs", `${path}.backend`), }, + deployment: deployment === undefined + ? { mode: "unidesk-direct" } + : { + mode: deploymentMode, + adapterServiceId: optionalStringField(deployment, "adapterServiceId", `${path}.deployment`), + v3sServiceId: optionalStringField(deployment, "v3sServiceId", `${path}.deployment`), + namespace: optionalStringField(deployment, "namespace", `${path}.deployment`), + expectedNodeIds: optionalStringArrayField(deployment, "expectedNodeIds", `${path}.deployment`), + activeNodeId: optionalStringField(deployment, "activeNodeId", `${path}.deployment`), + }, development: { providerId: stringField(development, "providerId", `${path}.development`), sshPassthrough: booleanField(development, "sshPassthrough", `${path}.development`), diff --git a/scripts/src/docker.ts b/scripts/src/docker.ts index ad831aea..3455b985 100644 --- a/scripts/src/docker.ts +++ b/scripts/src/docker.ts @@ -306,7 +306,7 @@ function restrictedHostAccessScript(config: UniDeskConfig): string { ` || 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`, + `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", diff --git a/scripts/src/e2e.ts b/scripts/src/e2e.ts index 58759afe..6a0c6507 100644 --- a/scripts/src/e2e.ts +++ b/scripts/src/e2e.ts @@ -554,7 +554,7 @@ function providerGatewayPackageVersion(): string { function isCodeQueueTaskEnqueueRequest(url: string, method: string): boolean { try { const parsed = new URL(url); - return method === "POST" && parsed.pathname === "/api/code-queue-direct/api/tasks"; + return method === "POST" && parsed.pathname === "/api/microservices/code-queue/proxy/api/tasks"; } catch { return false; } @@ -568,7 +568,7 @@ async function runCodeQueueEnqueueAwaitSmoke(page: Page): Promise { "This task is created by the frontend E2E smoke test to verify that the enqueue submit path awaits the backend response before unlocking the form.", ].join("\n"); let delayedPostCount = 0; - const routePattern = "**/api/code-queue-direct/api/tasks**"; + const routePattern = "**/api/microservices/code-queue/proxy/api/tasks**"; const routeHandler = async (route: any, request: any): Promise => { if (!isCodeQueueTaskEnqueueRequest(request.url(), request.method())) { await route.continue(); @@ -635,14 +635,14 @@ async function runCodeQueueEnqueueAwaitSmoke(page: Page): Promise { }; }, taskId); const storedTask = await page.evaluate(async (id) => { - const response = await fetch(`/api/code-queue-direct/api/tasks/${encodeURIComponent(String(id))}?meta=1`, { credentials: "same-origin" }); + const response = await fetch(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(String(id))}?meta=1`, { credentials: "same-origin" }); const text = await response.text(); let body: any = null; try { body = text ? JSON.parse(text) : null; } catch { body = { text }; } return { ok: response.ok, status: response.status, body }; }, taskId); const interrupt = await page.evaluate(async (id) => { - const response = await fetch(`/api/code-queue-direct/api/tasks/${encodeURIComponent(String(id))}/interrupt`, { + const response = await fetch(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(String(id))}/interrupt`, { method: "POST", credentials: "same-origin", headers: { "content-type": "application/json" }, @@ -1028,7 +1028,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2 const oaEventFlowStats = dockerCoreJson("/api/microservices/oa-event-flow/proxy/api/stats/trace?limit=10"); const codeQueueStatus = dockerCoreJson("/api/microservices/code-queue/status"); const codeQueueHealth = dockerCoreJson("/api/microservices/code-queue/health"); - const codeQueueTasks = dockerCoreJson("/api/microservices/code-queue/proxy/api/tasks?limit=5"); + const codeQueueTasks = dockerCoreJson("/api/microservices/code-queue/proxy/api/tasks/overview?limit=5&transcriptLimit=1&compact=1&afterSeq=0&preferId="); const filebrowserHealth = dockerCoreJson("/api/microservices/filebrowser/health"); const filebrowserWebui = dockerCoreJson("/api/microservices/filebrowser/proxy/"); const filebrowserD601Health = dockerCoreJson("/api/microservices/filebrowser-d601/health"); @@ -1071,7 +1071,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2 addSelectedCheck(checks, options, "provider:process-resource-status", mainProcesses.length > 0 && mainSystem?.current?.processSummary?.defaultSort === "memory_desc" && processMemoryDescending && mainProcesses.some((row) => Number.isFinite(row.pid) && Number.isFinite(row.rssBytes) && Number.isFinite(row.cpuPercent) && typeof row.command === "string"), { providerId: config.providerGateway.id, processSummary: mainSystem?.current?.processSummary, sample: mainProcesses.slice(0, 5) }); addSelectedCheck(checks, options, "provider:docker-status", (dockerStatus as { ok?: boolean }).ok === true && mainDocker?.dockerStatus !== undefined && ((mainDocker.dockerStatus.counts?.containers ?? 0) > 0 || (mainDocker.dockerStatus.containers?.length ?? 0) > 0), dockerStatusCheckDetail(dockerStatus, config.providerGateway.id)); addSelectedCheck(checks, options, "provider:gateway-restart-policy", providerGatewayRuntimeGuard.ok, providerGatewayRuntimeGuard); - const microserviceList = (microservices as { body?: { microservices?: Array<{ id?: string; providerId?: string; backend?: { public?: boolean }; runtime?: { providerStatus?: string; container?: { name?: string; state?: string } } }> } }).body?.microservices ?? []; + const microserviceList = (microservices as { body?: { microservices?: Array<{ id?: string; providerId?: string; backend?: { public?: boolean; proxyMode?: string }; deployment?: { mode?: string }; runtime?: { orchestrator?: string; providerStatus?: string; container?: { name?: string; state?: string } | null } }> } }).body?.microservices ?? []; const findjob = microserviceList.find((service) => service.id === "findjob"); const pipeline = microserviceList.find((service) => service.id === "pipeline"); const metNonlinear = microserviceList.find((service) => service.id === "met-nonlinear"); @@ -1132,7 +1132,15 @@ 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 === "D601" && 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.backend?.proxyMode === "v3sctl-adapter-http" + && codeQueue.deployment?.mode === "v3sctl-managed" + && codeQueue.runtime?.orchestrator === "v3sctl" + && codeQueue.runtime?.container === null, + { microservices }); addSelectedCheck(checks, options, "microservice:catalog-filebrowser", (microservices as { ok?: boolean }).ok === true && filebrowser?.providerId === "D518" && filebrowser.backend?.public === false @@ -1954,7 +1962,7 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2 codeQueueTaskCount = await page.locator('[data-testid^="codex-task-codex_"]').count(); if (wants("frontend:code-queue-initial-prompt-full-expand")) { codexInitialPromptFullMetrics = await page.evaluate(async () => { - const tasksResponse = await fetch("/api/microservices/code-queue/proxy/api/tasks?limit=300&lite=1&devReady=0", { credentials: "same-origin" }); + const tasksResponse = await fetch("/api/microservices/code-queue/proxy/api/tasks/overview?limit=120&transcriptLimit=0&compact=1&selected=0&includeActive=1&stats=0&afterSeq=0&preferId=", { credentials: "same-origin" }); const tasksPayload = await tasksResponse.json().catch(() => null); const tasks = Array.isArray(tasksPayload?.tasks) ? tasksPayload.tasks : []; const candidate = tasks.find((task: any) => Array.isArray(task?.referenceTaskIds) && task.referenceTaskIds.length > 0); @@ -1995,14 +2003,14 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2 } if (wants("frontend:code-queue-trace-full-load")) { codexTraceFullMetrics = await page.evaluate(async () => { - const tasksResponse = await fetch("/api/code-queue-direct/api/tasks?limit=300&lite=1&devReady=0", { credentials: "same-origin" }); + const tasksResponse = await fetch("/api/microservices/code-queue/proxy/api/tasks/overview?limit=120&transcriptLimit=0&compact=1&selected=0&includeActive=1&stats=0&afterSeq=0&preferId=", { credentials: "same-origin" }); const tasksPayload = await tasksResponse.json().catch(() => null); const tasks = Array.isArray(tasksPayload?.tasks) ? tasksPayload.tasks : []; const terminal = new Set(["succeeded", "failed", "canceled"]); for (const task of tasks) { const taskId = String(task?.id || ""); if (!taskId || !terminal.has(String(task?.status || "")) || Number(task?.outputCount || 0) < 20) continue; - const transcriptResponse = await fetch(`/api/code-queue-direct/api/tasks/${encodeURIComponent(taskId)}/transcript?afterSeq=0&limit=120&fullText=1`, { credentials: "same-origin" }); + const transcriptResponse = await fetch(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/transcript?afterSeq=0&limit=120&fullText=1`, { credentials: "same-origin" }); const transcriptPayload = await transcriptResponse.json().catch(() => null); const transcript = Array.isArray(transcriptPayload?.transcript) ? transcriptPayload.transcript : []; const toolCount = transcript.filter((line: any) => ["ran", "explored", "edited"].includes(String(line?.kind || ""))).length; @@ -2065,7 +2073,7 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2 const response = await fetch(new URL(path, urls.frontendUrl), { headers: authHeaders }); return response.json().catch(() => null); }; - const tasksPayload = await fetchJson("/api/code-queue-direct/api/tasks?limit=300&lite=1&devReady=0"); + const tasksPayload = await fetchJson("/api/microservices/code-queue/proxy/api/tasks/overview?limit=120&transcriptLimit=0&compact=1&selected=0&includeActive=1&stats=0&afterSeq=0&preferId="); const tasks = Array.isArray(tasksPayload?.tasks) ? tasksPayload.tasks : []; const prioritized = tasks .filter((task: any) => ["failed", "canceled", "running", "judging", "succeeded"].includes(String(task?.status || ""))) @@ -2073,7 +2081,7 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2 for (const task of prioritized) { const taskId = String(task?.id || ""); if (!taskId) continue; - const summaryPayload = await fetchJson(`/api/code-queue-direct/api/tasks/${encodeURIComponent(taskId)}/trace-summary`); + const summaryPayload = await fetchJson(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/trace-summary`); const summary = summaryPayload?.summary || null; const attempts = Array.isArray(summary?.attempts) ? summary.attempts : []; const errorAttempt = attempts.find((attempt: any) => Number(attempt?.errorCount ?? 0) > 0) || null; diff --git a/scripts/src/provider-attach.ts b/scripts/src/provider-attach.ts index 70f3c612..4fe235cb 100644 --- a/scripts/src/provider-attach.ts +++ b/scripts/src/provider-attach.ts @@ -113,6 +113,8 @@ function composeContent(options: ProviderAttachOptions): string { ' pid: "host"', " env_file:", ` - ${relativeEnv}`, + " ports:", + ' - "127.0.0.1:${PROVIDER_EGRESS_PROXY_HOST_PORT:-18789}:${PROVIDER_EGRESS_PROXY_PORT:-18789}"', " volumes:", " - /var/run/docker.sock:/var/run/docker.sock", " - .:/workspace:ro", diff --git a/src/components/backend-core/src/index.ts b/src/components/backend-core/src/index.ts index 07989aca..97653d80 100644 --- a/src/components/backend-core/src/index.ts +++ b/src/components/backend-core/src/index.ts @@ -76,6 +76,14 @@ interface MicroserviceConfig { healthPath: string; timeoutMs: number; }; + deployment: { + mode: "unidesk-direct" | "v3sctl-managed"; + adapterServiceId?: string; + v3sServiceId?: string; + namespace?: string; + expectedNodeIds?: string[]; + activeNodeId?: string; + }; development: { providerId: string; sshPassthrough: boolean; @@ -306,6 +314,13 @@ function booleanFromRecord(value: Record, key: string, path: st return field; } +function optionalStringFromRecord(value: Record, key: string, path: string): string | undefined { + const field = value[key]; + if (field === undefined) return undefined; + if (typeof field !== "string" || field.length === 0) throw new Error(`${path}.${key} must be a non-empty string`); + return field; +} + function stringArrayFromRecord(value: Record, key: string, path: string): string[] { const field = value[key]; if (!Array.isArray(field) || field.some((item) => typeof item !== "string" || item.length === 0)) { @@ -314,6 +329,12 @@ function stringArrayFromRecord(value: Record, key: string, path return field as string[]; } +function optionalStringArrayFromRecord(value: Record, key: string, path: string): string[] | undefined { + const field = value[key]; + if (field === undefined) return undefined; + return stringArrayFromRecord(value, key, path); +} + function parseMicroserviceConfig(value: unknown, index: number): MicroserviceConfig { const path = `MICROSERVICES_JSON[${index}]`; const item = asRecord(value, path); @@ -321,6 +342,11 @@ function parseMicroserviceConfig(value: unknown, index: number): MicroserviceCon const backend = asRecord(item.backend, `${path}.backend`); const development = asRecord(item.development, `${path}.development`); const frontend = asRecord(item.frontend, `${path}.frontend`); + const deployment = item.deployment === undefined ? undefined : asRecord(item.deployment, `${path}.deployment`); + const deploymentMode = deployment === undefined ? "unidesk-direct" : stringFromRecord(deployment, "mode", `${path}.deployment`); + if (deploymentMode !== "unidesk-direct" && deploymentMode !== "v3sctl-managed") { + throw new Error(`${path}.deployment.mode must be unidesk-direct or v3sctl-managed`); + } return { id: stringFromRecord(item, "id", path), name: stringFromRecord(item, "name", path), @@ -346,6 +372,16 @@ function parseMicroserviceConfig(value: unknown, index: number): MicroserviceCon healthPath: stringFromRecord(backend, "healthPath", `${path}.backend`), timeoutMs: numberFromRecord(backend, "timeoutMs", `${path}.backend`), }, + deployment: deployment === undefined + ? { mode: "unidesk-direct" } + : { + mode: deploymentMode, + adapterServiceId: optionalStringFromRecord(deployment, "adapterServiceId", `${path}.deployment`), + v3sServiceId: optionalStringFromRecord(deployment, "v3sServiceId", `${path}.deployment`), + namespace: optionalStringFromRecord(deployment, "namespace", `${path}.deployment`), + expectedNodeIds: optionalStringArrayFromRecord(deployment, "expectedNodeIds", `${path}.deployment`), + activeNodeId: optionalStringFromRecord(deployment, "activeNodeId", `${path}.deployment`), + }, development: { providerId: stringFromRecord(development, "providerId", `${path}.development`), sshPassthrough: booleanFromRecord(development, "sshPassthrough", `${path}.development`), @@ -1672,10 +1708,12 @@ async function getMicroservices(): Promise { return config.microservices.map((service) => { const node = nodes.find((item) => item.providerId === service.providerId) ?? null; const docker = dockerStatuses.find((item) => item.providerId === service.providerId) ?? null; - const container = findContainer(docker?.dockerStatus ?? null, service.repository.containerName); + const v3sManaged = isV3sctlManagedMicroservice(service); + const container = v3sManaged ? null : findContainer(docker?.dockerStatus ?? null, service.repository.containerName); return { ...service, runtime: { + orchestrator: v3sManaged ? "v3sctl" : "unidesk-direct", providerStatus: node?.status ?? "missing", providerName: node?.name ?? service.providerId, providerLastHeartbeat: node?.lastHeartbeat ?? null, @@ -2996,6 +3034,10 @@ function canDirectProxyMicroservice(service: MicroserviceConfig): boolean { return service.providerId === "main-server"; } +function isV3sctlManagedMicroservice(service: MicroserviceConfig): boolean { + return service.deployment.mode === "v3sctl-managed" || service.backend.proxyMode === "v3sctl-adapter-http"; +} + async function directMicroserviceResponse( service: MicroserviceConfig, method: string, @@ -3055,6 +3097,28 @@ async function directMicroserviceResponse( } } +async function v3sctlAdapterMicroserviceResponse( + service: MicroserviceConfig, + method: string, + targetPath: string, + proxyOptions: { query: string; jsonArrayLimits: Record }, + requestHeaders: Record, + bodyText: string, + abortSignal?: AbortSignal, +): Promise { + const adapterServiceId = service.deployment.adapterServiceId ?? "v3sctl-adapter"; + const adapter = microserviceById(adapterServiceId); + if (adapter === null) { + return jsonResponse({ ok: false, error: `v3sctl adapter microservice not found: ${adapterServiceId}`, serviceId: service.id }, 502); + } + if (adapter.id === service.id || isV3sctlManagedMicroservice(adapter)) { + return jsonResponse({ ok: false, error: "v3sctl adapter must be a UniDesk-direct microservice", serviceId: service.id, adapterServiceId }, 500); + } + const v3sServiceId = service.deployment.v3sServiceId ?? service.id; + const adapterTargetPath = `/api/services/${encodeURIComponent(v3sServiceId)}/proxy${targetPath}`; + return fetchMicroserviceUpstreamResponse(adapter, method, adapterTargetPath, proxyOptions, requestHeaders, bodyText, abortSignal); +} + async function fetchMicroserviceUpstreamResponse( service: MicroserviceConfig, method: string, @@ -3064,6 +3128,9 @@ async function fetchMicroserviceUpstreamResponse( bodyText: string, abortSignal?: AbortSignal, ): Promise { + if (isV3sctlManagedMicroservice(service)) { + return v3sctlAdapterMicroserviceResponse(service, method, targetPath, proxyOptions, requestHeaders, bodyText, abortSignal); + } if (canDirectProxyMicroservice(service)) { return directMicroserviceResponse(service, method, targetPath, proxyOptions, requestHeaders, bodyText, abortSignal); } diff --git a/src/components/frontend/public/app.js b/src/components/frontend/public/app.js index 074b53f9..d1b9e2cc 100644 --- a/src/components/frontend/public/app.js +++ b/src/components/frontend/public/app.js @@ -1,41 +1,41 @@ -(()=>{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{var TK=Object.create;var{getPrototypeOf:EK,defineProperty:Z7,getOwnPropertyNames:ZK}=Object;var OK=Object.prototype.hasOwnProperty;function HK(u){return this[u]}var BK,VK,Pu=(u,l,f)=>{var r=u!=null&&typeof u==="object";if(r){var n=l?BK??=new WeakMap:VK??=new WeakMap,i=n.get(u);if(i)return i}f=u!=null?TK(EK(u)):{};let y=l||!u||!u.__esModule?Z7(f,"default",{value:u,enumerable:!0}):f;for(let t of ZK(u))if(!OK.call(y,t))Z7(y,t,{get:HK.bind(u,t),enumerable:!0});if(r)n.set(u,y);return y};var ir=(u,l)=>()=>(l||u((l={exports:{}}).exports,l),l.exports);var ll=((u)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(u,{get:(l,f)=>(typeof require<"u"?require:l)[f]}):u)(function(u){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+u+'" is not supported')});var C7=ir((ou)=>{var Xy=Symbol.for("react.element"),DK=Symbol.for("react.portal"),XK=Symbol.for("react.fragment"),SK=Symbol.for("react.strict_mode"),YK=Symbol.for("react.profiler"),pK=Symbol.for("react.provider"),mK=Symbol.for("react.context"),PK=Symbol.for("react.forward_ref"),CK=Symbol.for("react.suspense"),MK=Symbol.for("react.memo"),RK=Symbol.for("react.lazy"),O7=Symbol.iterator;function xK(u){if(u===null||typeof u!=="object")return null;return u=O7&&u[O7]||u["@@iterator"],typeof u==="function"?u:null}var V7={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},D7=Object.assign,X7={};function l1(u,l,f){this.props=u,this.context=l,this.refs=X7,this.updater=f||V7}l1.prototype.isReactComponent={};l1.prototype.setState=function(u,l){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,l,"setState")};l1.prototype.forceUpdate=function(u){this.updater.enqueueForceUpdate(this,u,"forceUpdate")};function S7(){}S7.prototype=l1.prototype;function d6(u,l,f){this.props=u,this.context=l,this.refs=X7,this.updater=f||V7}var e6=d6.prototype=new S7;e6.constructor=d6;D7(e6,l1.prototype);e6.isPureReactComponent=!0;var H7=Array.isArray,Y7=Object.prototype.hasOwnProperty,u8={current:null},p7={key:!0,ref:!0,__self:!0,__source:!0};function m7(u,l,f){var r,n={},i=null,y=null;if(l!=null)for(r in l.ref!==void 0&&(y=l.ref),l.key!==void 0&&(i=""+l.key),l)Y7.call(l,r)&&!p7.hasOwnProperty(r)&&(n[r]=l[r]);var t=arguments.length-2;if(t===1)n.children=f;else if(1{M7.exports=C7()});var a7=ir((Nl)=>{function i8(u,l){var f=u.length;u.push(l);u:for(;0>>1,n=u[r];if(0>>1;rA$(t,f))_A$(c,t)?(u[r]=c,u[_]=f,r=_):(u[r]=t,u[y]=f,r=y);else if(_A$(c,f))u[r]=c,u[_]=f,r=_;else break u}}return l}function A$(u,l){var f=u.sortIndex-l.sortIndex;return f!==0?f:u.id-l.id}if(typeof performance==="object"&&typeof performance.now==="function")y8=performance,Nl.unstable_now=function(){return y8.now()};else j$=Date,t8=j$.now(),Nl.unstable_now=function(){return j$.now()-t8};var y8,j$,t8,er=[],d0=[],aK=1,wr=null,Nf=3,Q$=!1,li=!1,Yy=!1,v7=typeof setTimeout==="function"?setTimeout:null,k7=typeof clearTimeout==="function"?clearTimeout:null,b7=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function _8(u){for(var l=Sr(d0);l!==null;){if(l.callback===null)J$(d0);else if(l.startTime<=u)J$(d0),l.sortIndex=l.expirationTime,i8(er,l);else break;l=Sr(d0)}}function c8(u){if(Yy=!1,_8(u),!li)if(Sr(er)!==null)li=!0,j8(A8);else{var l=Sr(d0);l!==null&&F8(c8,l.startTime-u)}}function A8(u,l){li=!1,Yy&&(Yy=!1,k7(py),py=-1),Q$=!0;var f=Nf;try{_8(l);for(wr=Sr(er);wr!==null&&(!(wr.expirationTime>l)||u&&!s7());){var r=wr.callback;if(typeof r==="function"){wr.callback=null,Nf=wr.priorityLevel;var n=r(wr.expirationTime<=l);l=Nl.unstable_now(),typeof n==="function"?wr.callback=n:wr===Sr(er)&&J$(er),_8(l)}else J$(er);wr=Sr(er)}if(wr!==null)var i=!0;else{var y=Sr(d0);y!==null&&F8(c8,y.startTime-l),i=!1}return i}finally{wr=null,Nf=f,Q$=!1}}var N$=!1,F$=null,py=-1,I7=5,g7=-1;function s7(){return Nl.unstable_now()-g7u||125r?(u.sortIndex=f,i8(d0,u),Sr(er)===null&&u===Sr(d0)&&(Yy?(k7(py),py=-1):Yy=!0,F8(c8,f-r))):(u.sortIndex=n,i8(er,u),li||Q$||(li=!0,j8(A8))),u};Nl.unstable_shouldYield=s7;Nl.unstable_wrapCallback=function(u){var l=Nf;return function(){var f=Nf;Nf=l;try{return u.apply(this,arguments)}finally{Nf=f}}}});var d7=ir((qm,o7)=>{o7.exports=a7()});var uJ=ir((Ar)=>{var oK=Jl(),$r=d7();function Ju(u){for(var l="https://reactjs.org/docs/error-decoder.html?invariant="+u,f=1;f"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Y8=Object.prototype.hasOwnProperty,dK=/^[: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]*$/,e7={},uj={};function eK(u){if(Y8.call(uj,u))return!0;if(Y8.call(e7,u))return!1;if(dK.test(u))return uj[u]=!0;return e7[u]=!0,!1}function uG(u,l,f,r){if(f!==null&&f.type===0)return!1;switch(typeof l){case"function":case"symbol":return!0;case"boolean":if(r)return!1;if(f!==null)return!f.acceptsBooleans;return u=u.toLowerCase().slice(0,5),u!=="data-"&&u!=="aria-";default:return!1}}function lG(u,l,f,r){if(l===null||typeof l>"u"||uG(u,l,f,r))return!0;if(r)return!1;if(f!==null)switch(f.type){case 3:return!l;case 4:return l===!1;case 5:return isNaN(l);case 6:return isNaN(l)||1>l}return!1}function Df(u,l,f,r,n,i,y){this.acceptsBooleans=l===2||l===3||l===4,this.attributeName=r,this.attributeNamespace=n,this.mustUseProperty=f,this.propertyName=u,this.type=l,this.sanitizeURL=i,this.removeEmptyString=y}var cf={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(u){cf[u]=new Df(u,0,!1,u,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(u){var l=u[0];cf[l]=new Df(l,1,!1,u[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(u){cf[u]=new Df(u,2,!1,u.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(u){cf[u]=new Df(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){cf[u]=new Df(u,3,!1,u.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(u){cf[u]=new Df(u,3,!0,u,null,!1,!1)});["capture","download"].forEach(function(u){cf[u]=new Df(u,4,!1,u,null,!1,!1)});["cols","rows","size","span"].forEach(function(u){cf[u]=new Df(u,6,!1,u,null,!1,!1)});["rowSpan","start"].forEach(function(u){cf[u]=new Df(u,5,!1,u.toLowerCase(),null,!1,!1)});var H4=/[\-:]([a-z])/g;function B4(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 l=u.replace(H4,B4);cf[l]=new Df(l,1,!1,u,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(u){var l=u.replace(H4,B4);cf[l]=new Df(l,1,!1,u,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(u){var l=u.replace(H4,B4);cf[l]=new Df(l,1,!1,u,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(u){cf[u]=new Df(u,1,!1,u.toLowerCase(),null,!1,!1)});cf.xlinkHref=new Df("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(u){cf[u]=new Df(u,1,!1,u.toLowerCase(),null,!0,!0)});function V4(u,l,f,r){var n=cf.hasOwnProperty(l)?cf[l]: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{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_++,0t||n[y]!==i[t]){var _=` +`+n[y].replace(" at new "," at ");return u.displayName&&_.includes("")&&(_=_.replace("",u.displayName)),_}while(1<=y&&0<=t);break}}}finally{J8=!1,Error.prepareStackTrace=f}return(u=u?u.displayName||u.name:"")?by(u):""}function fG(u){switch(u.tag){case 5:return by(u.type);case 16:return by("Lazy");case 13:return by("Suspense");case 19:return by("SuspenseList");case 0:case 2:case 15:return u=Q8(u.type,!1),u;case 11:return u=Q8(u.type.render,!1),u;case 1:return u=Q8(u.type,!0),u;default:return""}}function C8(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 i1:return"Fragment";case n1:return"Portal";case p8:return"Profiler";case D4:return"StrictMode";case m8:return"Suspense";case P8:return"SuspenseList"}if(typeof u==="object")switch(u.$$typeof){case iF:return(u.displayName||"Context")+".Consumer";case nF:return(u._context.displayName||"Context")+".Provider";case X4:var l=u.render;return u=u.displayName,u||(u=l.displayName||l.name||"",u=u!==""?"ForwardRef("+u+")":"ForwardRef"),u;case S4:return l=u.displayName||null,l!==null?l:C8(u.type)||"Memo";case un:l=u._payload,u=u._init;try{return C8(u(l))}catch(f){}}return null}function rG(u){var l=u.type;switch(u.tag){case 24:return"Cache";case 9:return(l.displayName||"Context")+".Consumer";case 10:return(l._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return u=l.render,u=u.displayName||u.name||"",l.displayName||(u!==""?"ForwardRef("+u+")":"ForwardRef");case 7:return"Fragment";case 5:return l;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return C8(l);case 8:return l===D4?"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 l==="function")return l.displayName||l.name||null;if(typeof l==="string")return l}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 tF(u){var l=u.type;return(u=u.nodeName)&&u.toLowerCase()==="input"&&(l==="checkbox"||l==="radio")}function nG(u){var l=tF(u)?"checked":"value",f=Object.getOwnPropertyDescriptor(u.constructor.prototype,l),r=""+u[l];if(!u.hasOwnProperty(l)&&typeof f<"u"&&typeof f.get==="function"&&typeof f.set==="function"){var{get:n,set:i}=f;return Object.defineProperty(u,l,{configurable:!0,get:function(){return n.call(this)},set:function(y){r=""+y,i.call(this,y)}}),Object.defineProperty(u,l,{enumerable:f.enumerable}),{getValue:function(){return r},setValue:function(y){r=""+y},stopTracking:function(){u._valueTracker=null,delete u[l]}}}}function W$(u){u._valueTracker||(u._valueTracker=nG(u))}function _F(u){if(!u)return!1;var l=u._valueTracker;if(!l)return!0;var f=l.getValue(),r="";return u&&(r=tF(u)?u.checked?"true":"false":u.value),u=r,u!==f?(l.setValue(u),!0):!1}function b$(u){if(u=u||(typeof document<"u"?document:void 0),typeof u>"u")return null;try{return u.activeElement||u.body}catch(l){return u.body}}function M8(u,l){var f=l.checked;return Bl({},l,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:f!=null?f:u._wrapperState.initialChecked})}function fj(u,l){var f=l.defaultValue==null?"":l.defaultValue,r=l.checked!=null?l.checked:l.defaultChecked;f=Jn(l.value!=null?l.value:f),u._wrapperState={initialChecked:r,initialValue:f,controlled:l.type==="checkbox"||l.type==="radio"?l.checked!=null:l.value!=null}}function $F(u,l){l=l.checked,l!=null&&V4(u,"checked",l,!1)}function R8(u,l){$F(u,l);var f=Jn(l.value),r=l.type;if(f!=null)if(r==="number"){if(f===0&&u.value===""||u.value!=f)u.value=""+f}else u.value!==""+f&&(u.value=""+f);else if(r==="submit"||r==="reset"){u.removeAttribute("value");return}l.hasOwnProperty("value")?x8(u,l.type,f):l.hasOwnProperty("defaultValue")&&x8(u,l.type,Jn(l.defaultValue)),l.checked==null&&l.defaultChecked!=null&&(u.defaultChecked=!!l.defaultChecked)}function rj(u,l,f){if(l.hasOwnProperty("value")||l.hasOwnProperty("defaultValue")){var r=l.type;if(!(r!=="submit"&&r!=="reset"||l.value!==void 0&&l.value!==null))return;l=""+u._wrapperState.initialValue,f||l===u.value||(u.value=l),u.defaultValue=l}f=u.name,f!==""&&(u.name=""),u.defaultChecked=!!u._wrapperState.initialChecked,f!==""&&(u.name=f)}function x8(u,l,f){if(l!=="number"||b$(u.ownerDocument)!==u)f==null?u.defaultValue=""+u._wrapperState.initialValue:u.defaultValue!==""+f&&(u.defaultValue=""+f)}var vy=Array.isArray;function Q1(u,l,f,r){if(u=u.options,l){l={};for(var n=0;n"+l.valueOf().toString()+"";for(l=w$.firstChild;u.firstChild;)u.removeChild(u.firstChild);for(;l.firstChild;)u.appendChild(l.firstChild)}});function _t(u,l){if(l){var f=u.firstChild;if(f&&f===u.lastChild&&f.nodeType===3){f.nodeValue=l;return}}u.textContent=l}var dy={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},iG=["Webkit","ms","Moz","O"];Object.keys(dy).forEach(function(u){iG.forEach(function(l){l=l+u.charAt(0).toUpperCase()+u.substring(1),dy[l]=dy[u]})});function FF(u,l,f){return l==null||typeof l==="boolean"||l===""?"":f||typeof l!=="number"||l===0||dy.hasOwnProperty(u)&&dy[u]?(""+l).trim():l+"px"}function UF(u,l){u=u.style;for(var f in l)if(l.hasOwnProperty(f)){var r=f.indexOf("--")===0,n=FF(f,l[f],r);f==="float"&&(f="cssFloat"),r?u.setProperty(f,n):u[f]=n}}var yG=Bl({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 v8(u,l){if(l){if(yG[u]&&(l.children!=null||l.dangerouslySetInnerHTML!=null))throw Error(Ju(137,u));if(l.dangerouslySetInnerHTML!=null){if(l.children!=null)throw Error(Ju(60));if(typeof l.dangerouslySetInnerHTML!=="object"||!("__html"in l.dangerouslySetInnerHTML))throw Error(Ju(61))}if(l.style!=null&&typeof l.style!=="object")throw Error(Ju(62))}}function k8(u,l){if(u.indexOf("-")===-1)return typeof l.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 I8=null;function Y4(u){return u=u.target||u.srcElement||window,u.correspondingUseElement&&(u=u.correspondingUseElement),u.nodeType===3?u.parentNode:u}var g8=null,N1=null,q1=null;function yj(u){if(u=Et(u)){if(typeof g8!=="function")throw Error(Ju(280));var l=u.stateNode;l&&(l=q3(l),g8(u.stateNode,u.type,l))}}function JF(u){N1?q1?q1.push(u):q1=[u]:N1=u}function QF(){if(N1){var u=N1,l=q1;if(q1=N1=null,yj(u),l)for(u=0;u>>=0,u===0?32:31-(NG(u)/qG|0)|0}var L$=64,K$=4194304;function ky(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 g$(u,l){var f=u.pendingLanes;if(f===0)return 0;var r=0,n=u.suspendedLanes,i=u.pingedLanes,y=f&268435455;if(y!==0){var t=y&~n;t!==0?r=ky(t):(i&=y,i!==0&&(r=ky(i)))}else y=f&~n,y!==0?r=ky(y):i!==0&&(r=ky(i));if(r===0)return 0;if(l!==0&&l!==r&&(l&n)===0&&(n=r&-r,i=l&-l,n>=i||n===16&&(i&4194240)!==0))return l;if((r&4)!==0&&(r|=f&16),l=u.entangledLanes,l!==0)for(u=u.entanglements,l&=r;0f;f++)l.push(u);return l}function zt(u,l,f){u.pendingLanes|=l,l!==536870912&&(u.suspendedLanes=0,u.pingedLanes=0),u=u.eventTimes,l=31-Cr(l),u[l]=f}function KG(u,l){var f=u.pendingLanes&~l;u.pendingLanes=l,u.suspendedLanes=0,u.pingedLanes=0,u.expiredLanes&=l,u.mutableReadLanes&=l,u.entangledLanes&=l,l=u.entanglements;var r=u.eventTimes;for(u=u.expirationTimes;0=ut),Jj=String.fromCharCode(32),Qj=!1;function pF(u,l){switch(u){case"keyup":return aG.indexOf(l.keyCode)!==-1;case"keydown":return l.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function mF(u){return u=u.detail,typeof u==="object"&&"data"in u?u.data:null}var y1=!1;function dG(u,l){switch(u){case"compositionend":return mF(l);case"keypress":if(l.which!==32)return null;return Qj=!0,Jj;case"textInput":return u=l.data,u===Jj&&Qj?null:u;default:return null}}function eG(u,l){if(y1)return u==="compositionend"||!h4&&pF(u,l)?(u=SF(),S$=M4=nn=null,y1=!1,u):null;switch(u){case"paste":return null;case"keypress":if(!(l.ctrlKey||l.altKey||l.metaKey)||l.ctrlKey&&l.altKey){if(l.char&&1=l)return{node:f,offset:l-u};u=r}u:{for(;f;){if(f.nextSibling){f=f.nextSibling;break u}f=f.parentNode}f=void 0}f=Wj(f)}}function RF(u,l){return u&&l?u===l?!0:u&&u.nodeType===3?!1:l&&l.nodeType===3?RF(u,l.parentNode):("contains"in u)?u.contains(l):u.compareDocumentPosition?!!(u.compareDocumentPosition(l)&16):!1:!1}function xF(){for(var u=window,l=b$();l instanceof u.HTMLIFrameElement;){try{var f=typeof l.contentWindow.location.href==="string"}catch(r){f=!1}if(f)u=l.contentWindow;else break;l=b$(u.document)}return l}function b4(u){var l=u&&u.nodeName&&u.nodeName.toLowerCase();return l&&(l==="input"&&(u.type==="text"||u.type==="search"||u.type==="tel"||u.type==="url"||u.type==="password")||l==="textarea"||u.contentEditable==="true")}function _z(u){var l=xF(),f=u.focusedElem,r=u.selectionRange;if(l!==f&&f&&f.ownerDocument&&RF(f.ownerDocument.documentElement,f)){if(r!==null&&b4(f)){if(l=r.start,u=r.end,u===void 0&&(u=l),"selectionStart"in f)f.selectionStart=l,f.selectionEnd=Math.min(u,f.value.length);else if(u=(l=f.ownerDocument||document)&&l.defaultView||window,u.getSelection){u=u.getSelection();var n=f.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=wj(f,i);var y=wj(f,r);n&&y&&(u.rangeCount!==1||u.anchorNode!==n.node||u.anchorOffset!==n.offset||u.focusNode!==y.node||u.focusOffset!==y.offset)&&(l=l.createRange(),l.setStart(n.node,n.offset),u.removeAllRanges(),i>r?(u.addRange(l),u.extend(y.node,y.offset)):(l.setEnd(y.node,y.offset),u.addRange(l)))}}l=[];for(u=f;u=u.parentNode;)u.nodeType===1&&l.push({element:u,left:u.scrollLeft,top:u.scrollTop});typeof f.focus==="function"&&f.focus();for(f=0;f=document.documentMode,t1=null,u4=null,ft=null,l4=!1;function Lj(u,l,f){var r=f.window===f?f.document:f.nodeType===9?f:f.ownerDocument;l4||t1==null||t1!==b$(r)||(r=t1,("selectionStart"in r)&&b4(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}),ft&&Ut(ft,r)||(ft=r,r=o$(u4,"onSelect"),0c1||(u.current=$4[c1],$4[c1]=null,c1--)}function ql(u,l){c1++,$4[c1]=u.current,u.current=l}var Qn={},Lf=qn(Qn),hf=qn(!1),ci=Qn;function G1(u,l){var f=u.type.contextTypes;if(!f)return Qn;var r=u.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===l)return r.__reactInternalMemoizedMaskedChildContext;var n={},i;for(i in f)n[i]=l[i];return r&&(u=u.stateNode,u.__reactInternalMemoizedUnmaskedChildContext=l,u.__reactInternalMemoizedMaskedChildContext=n),n}function bf(u){return u=u.childContextTypes,u!==null&&u!==void 0}function e$(){Kl(hf),Kl(Lf)}function Oj(u,l,f){if(Lf.current!==Qn)throw Error(Ju(168));ql(Lf,l),ql(hf,f)}function oF(u,l,f){var r=u.stateNode;if(l=l.childContextTypes,typeof r.getChildContext!=="function")return f;r=r.getChildContext();for(var n in r)if(!(n in l))throw Error(Ju(108,rG(u)||"Unknown",n));return Bl({},f,r)}function u3(u){return u=(u=u.stateNode)&&u.__reactInternalMemoizedMergedChildContext||Qn,ci=Lf.current,ql(Lf,u),ql(hf,hf.current),!0}function Hj(u,l,f){var r=u.stateNode;if(!r)throw Error(Ju(169));f?(u=oF(u,l,ci),r.__reactInternalMemoizedMergedChildContext=u,Kl(hf),Kl(Lf),ql(Lf,u)):Kl(hf),ql(hf,f)}var K0=null,W3=!1,E8=!1;function dF(u){K0===null?K0=[u]:K0.push(u)}function qz(u){W3=!0,dF(u)}function Wn(){if(!E8&&K0!==null){E8=!0;var u=0,l=$l;try{var f=K0;for($l=1;u>=y,n-=y,G0=1<<32-Cr(l)+n|f<E?(D=H,H=null):D=H.sibling;var h=F(U,H,q[E],W);if(h===null){H===null&&(H=D);break}u&&H&&h.alternate===null&&l(U,H),N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h,H=D}if(E===q.length)return f(U,H),Tl&&ri(U,E),z;if(H===null){for(;EE?(D=H,H=null):D=H.sibling;var V=F(U,H,h.value,W);if(V===null){H===null&&(H=D);break}u&&H&&V.alternate===null&&l(U,H),N=i(V,N,E),Z===null?z=V:Z.sibling=V,Z=V,H=D}if(h.done)return f(U,H),Tl&&ri(U,E),z;if(H===null){for(;!h.done;E++,h=q.next())h=j(U,h.value,W),h!==null&&(N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h);return Tl&&ri(U,E),z}for(H=r(U,H);!h.done;E++,h=q.next())h=J(H,U,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(S){return l(U,S)}),Tl&&ri(U,E),z}function L(U,N,q,W){if(typeof q==="object"&&q!==null&&q.type===i1&&q.key===null&&(q=q.props.children),typeof q==="object"&&q!==null){switch(q.$$typeof){case q$:u:{for(var z=q.key,Z=N;Z!==null;){if(Z.key===z){if(z=q.type,z===i1){if(Z.tag===7){f(U,Z.sibling),N=n(Z,q.props.children),N.return=U,U=N;break u}}else if(Z.elementType===z||typeof z==="object"&&z!==null&&z.$$typeof===un&&Dj(z)===Z.type){f(U,Z.sibling),N=n(Z,q.props),N.ref=Ry(U,Z,q),N.return=U,U=N;break u}f(U,Z);break}else l(U,Z);Z=Z.sibling}q.type===i1?(N=$i(q.props.children,U.mode,W,q.key),N.return=U,U=N):(W=h$(q.type,q.key,q.props,null,U.mode,W),W.ref=Ry(U,N,q),W.return=U,U=W)}return y(U);case n1: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){f(U,N.sibling),N=n(N,q.children||[]),N.return=U,U=N;break u}else{f(U,N);break}else l(U,N);N=N.sibling}N=S8(q,U.mode,W),N.return=U,U=N}return y(U);case un:return Z=q._init,L(U,N,Z(q._payload),W)}if(vy(q))return Q(U,N,q,W);if(my(q))return w(U,N,q,W);H$(U,q)}return typeof q==="string"&&q!==""||typeof q==="number"?(q=""+q,N!==null&&N.tag===6?(f(U,N.sibling),N=n(N,q),N.return=U,U=N):(f(U,N),N=X8(q,U.mode,W),N.return=U,U=N),y(U)):f(U,N)}return L}var T1=fU(!0),rU=fU(!1),r3=qn(null),n3=null,F1=null,g4=null;function s4(){g4=F1=n3=null}function a4(u){var l=r3.current;Kl(r3),u._currentValue=l}function j4(u,l,f){for(;u!==null;){var r=u.alternate;if((u.childLanes&l)!==l?(u.childLanes|=l,r!==null&&(r.childLanes|=l)):r!==null&&(r.childLanes&l)!==l&&(r.childLanes|=l),u===f)break;u=u.return}}function w1(u,l){n3=u,g4=F1=null,u=u.dependencies,u!==null&&u.firstContext!==null&&((u.lanes&l)!==0&&(xf=!0),u.firstContext=null)}function Tr(u){var l=u._currentValue;if(g4!==u)if(u={context:u,memoizedValue:l,next:null},F1===null){if(n3===null)throw Error(Ju(308));F1=u,n3.dependencies={lanes:0,firstContext:u}}else F1=F1.next=u;return l}var yi=null;function o4(u){yi===null?yi=[u]:yi.push(u)}function nU(u,l,f,r){var n=l.interleaved;return n===null?(f.next=f,o4(l)):(f.next=n.next,n.next=f),l.interleaved=f,O0(u,r)}function O0(u,l){u.lanes|=l;var f=u.alternate;f!==null&&(f.lanes|=l),f=u;for(u=u.return;u!==null;)u.childLanes|=l,f=u.alternate,f!==null&&(f.childLanes|=l),f=u,u=u.return;return f.tag===3?f.stateNode:null}var ln=!1;function d4(u){u.updateQueue={baseState:u.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function iU(u,l){u=u.updateQueue,l.updateQueue===u&&(l.updateQueue={baseState:u.baseState,firstBaseUpdate:u.firstBaseUpdate,lastBaseUpdate:u.lastBaseUpdate,shared:u.shared,effects:u.effects})}function T0(u,l){return{eventTime:u,lane:l,tag:0,payload:null,callback:null,next:null}}function An(u,l,f){var r=u.updateQueue;if(r===null)return null;if(r=r.shared,(rl&2)!==0){var n=r.pending;return n===null?l.next=l:(l.next=n.next,n.next=l),r.pending=l,O0(u,f)}return n=r.interleaved,n===null?(l.next=l,o4(r)):(l.next=n.next,n.next=l),r.interleaved=l,O0(u,f)}function m$(u,l,f){if(l=l.updateQueue,l!==null&&(l=l.shared,(f&4194240)!==0)){var r=l.lanes;r&=u.pendingLanes,f|=r,l.lanes=f,m4(u,f)}}function Xj(u,l){var{updateQueue:f,alternate:r}=u;if(r!==null&&(r=r.updateQueue,f===r)){var n=null,i=null;if(f=f.firstBaseUpdate,f!==null){do{var y={eventTime:f.eventTime,lane:f.lane,tag:f.tag,payload:f.payload,callback:f.callback,next:null};i===null?n=i=y:i=i.next=y,f=f.next}while(f!==null);i===null?n=i=l:i=i.next=l}else n=i=l;f={baseState:r.baseState,firstBaseUpdate:n,lastBaseUpdate:i,shared:r.shared,effects:r.effects},u.updateQueue=f;return}u=f.lastBaseUpdate,u===null?f.firstBaseUpdate=l:u.next=l,f.lastBaseUpdate=l}function i3(u,l,f,r){var n=u.updateQueue;ln=!1;var{firstBaseUpdate:i,lastBaseUpdate:y}=n,t=n.shared.pending;if(t!==null){n.shared.pending=null;var _=t,c=_.next;_.next=null,y===null?i=c:y.next=c,y=_;var A=u.alternate;A!==null&&(A=A.updateQueue,t=A.lastBaseUpdate,t!==y&&(t===null?A.firstBaseUpdate=c:t.next=c,A.lastBaseUpdate=_))}if(i!==null){var j=n.baseState;y=0,A=c=_=null,t=i;do{var{lane:F,eventTime:J}=t;if((r&F)===F){A!==null&&(A=A.next={eventTime:J,lane:0,tag:t.tag,payload:t.payload,callback:t.callback,next:null});u:{var Q=u,w=t;switch(F=l,J=f,w.tag){case 1:if(Q=w.payload,typeof Q==="function"){j=Q.call(J,j,F);break u}j=Q;break u;case 3:Q.flags=Q.flags&-65537|128;case 0:if(Q=w.payload,F=typeof Q==="function"?Q.call(J,j,F):Q,F===null||F===void 0)break u;j=Bl({},j,F);break u;case 2:ln=!0}}t.callback!==null&&t.lane!==0&&(u.flags|=64,F=n.effects,F===null?n.effects=[t]:F.push(t))}else J={eventTime:J,lane:F,tag:t.tag,payload:t.payload,callback:t.callback,next:null},A===null?(c=A=J,_=j):A=A.next=J,y|=F;if(t=t.next,t===null)if(t=n.shared.pending,t===null)break;else F=t,t=F.next,F.next=null,n.lastBaseUpdate=F,n.shared.pending=null}while(1);if(A===null&&(_=j),n.baseState=_,n.firstBaseUpdate=c,n.lastBaseUpdate=A,l=n.shared.interleaved,l!==null){n=l;do y|=n.lane,n=n.next;while(n!==l)}else i===null&&(n.shared.lanes=0);Fi|=y,u.lanes=y,u.memoizedState=j}}function Sj(u,l,f){if(u=l.effects,l.effects=null,u!==null)for(l=0;lf?f:4,u(!0);var r=O8.transition;O8.transition={};try{u(!1),l()}finally{$l=f,O8.transition=r}}function KU(){return Er().memoizedState}function Kz(u,l,f){var r=Fn(u);if(f={lane:r,action:f,hasEagerState:!1,eagerState:null,next:null},GU(u))zU(l,f);else if(f=nU(u,l,f,r),f!==null){var n=Vf();Mr(f,u,r,n),TU(f,l,r)}}function Gz(u,l,f){var r=Fn(u),n={lane:r,action:f,hasEagerState:!1,eagerState:null,next:null};if(GU(u))zU(l,n);else{var i=u.alternate;if(u.lanes===0&&(i===null||i.lanes===0)&&(i=l.lastRenderedReducer,i!==null))try{var y=l.lastRenderedState,t=i(y,f);if(n.hasEagerState=!0,n.eagerState=t,Rr(t,y)){var _=l.interleaved;_===null?(n.next=n,o4(l)):(n.next=_.next,_.next=n),l.interleaved=n;return}}catch(c){}finally{}f=nU(u,l,n,r),f!==null&&(n=Vf(),Mr(f,u,r,n),TU(f,l,r))}}function GU(u){var l=u.alternate;return u===Hl||l!==null&&l===Hl}function zU(u,l){rt=t3=!0;var f=u.pending;f===null?l.next=l:(l.next=f.next,f.next=l),u.pending=l}function TU(u,l,f){if((f&4194240)!==0){var r=l.lanes;r&=u.pendingLanes,f|=r,l.lanes=f,m4(u,f)}}var _3={readContext:Tr,useCallback:qf,useContext:qf,useEffect:qf,useImperativeHandle:qf,useInsertionEffect:qf,useLayoutEffect:qf,useMemo:qf,useReducer:qf,useRef:qf,useState:qf,useDebugValue:qf,useDeferredValue:qf,useTransition:qf,useMutableSource:qf,useSyncExternalStore:qf,useId:qf,unstable_isNewReconciler:!1},zz={readContext:Tr,useCallback:function(u,l){return l0().memoizedState=[u,l===void 0?null:l],u},useContext:Tr,useEffect:pj,useImperativeHandle:function(u,l,f){return f=f!==null&&f!==void 0?f.concat([u]):null,C$(4194308,4,NU.bind(null,l,u),f)},useLayoutEffect:function(u,l){return C$(4194308,4,u,l)},useInsertionEffect:function(u,l){return C$(4,2,u,l)},useMemo:function(u,l){var f=l0();return l=l===void 0?null:l,u=u(),f.memoizedState=[u,l],u},useReducer:function(u,l,f){var r=l0();return l=f!==void 0?f(l):l,r.memoizedState=r.baseState=l,u={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:u,lastRenderedState:l},r.queue=u,u=u.dispatch=Kz.bind(null,Hl,u),[r.memoizedState,u]},useRef:function(u){var l=l0();return u={current:u},l.memoizedState=u},useState:Yj,useDebugValue:yA,useDeferredValue:function(u){return l0().memoizedState=u},useTransition:function(){var u=Yj(!1),l=u[0];return u=Lz.bind(null,u[1]),l0().memoizedState=u,[l,u]},useMutableSource:function(){},useSyncExternalStore:function(u,l,f){var r=Hl,n=l0();if(Tl){if(f===void 0)throw Error(Ju(407));f=f()}else{if(f=l(),uf===null)throw Error(Ju(349));(ji&30)!==0||$U(r,l,f)}n.memoizedState=f;var i={value:f,getSnapshot:l};return n.queue=i,pj(AU.bind(null,r,i,u),[u]),r.flags|=2048,Kt(9,cU.bind(null,r,i,f,l),void 0,null),f},useId:function(){var u=l0(),l=uf.identifierPrefix;if(Tl){var f=z0,r=G0;f=(r&~(1<<32-Cr(r)-1)).toString(32)+f,l=":"+l+"R"+f,f=wt++,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[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,` +`+i.stack}return{value:u,source:l,stack:n,digest:null}}function V8(u,l,f){return{value:u,source:null,stack:f!=null?f:null,digest:l!=null?l:null}}function J4(u,l){try{console.error(l.value)}catch(f){setTimeout(function(){throw f})}}var Zz=typeof WeakMap==="function"?WeakMap:Map;function ZU(u,l,f){f=T0(-1,f),f.tag=3,f.payload={element:null};var r=l.value;return f.callback=function(){c3||(c3=!0,T4=r),J4(u,l)},f}function OU(u,l,f){f=T0(-1,f),f.tag=3;var r=u.type.getDerivedStateFromError;if(typeof r==="function"){var n=l.value;f.payload=function(){return r(n)},f.callback=function(){J4(u,l)}}var i=u.stateNode;return i!==null&&typeof i.componentDidCatch==="function"&&(f.callback=function(){J4(u,l),typeof r!=="function"&&(jn===null?jn=new Set([this]):jn.add(this));var y=l.stack;this.componentDidCatch(l.value,{componentStack:y!==null?y:""})}),f}function Cj(u,l,f){var r=u.pingCache;if(r===null){r=u.pingCache=new Zz;var n=new Set;r.set(l,n)}else n=r.get(l),n===void 0&&(n=new Set,r.set(l,n));n.has(f)||(n.add(f),u=Rz.bind(null,u,l,f),l.then(u,u))}function Mj(u){do{var l;if(l=u.tag===13)l=u.memoizedState,l=l!==null?l.dehydrated!==null?!0:!1:!0;if(l)return u;u=u.return}while(u!==null);return null}function Rj(u,l,f,r,n){if((u.mode&1)===0)return u===l?u.flags|=65536:(u.flags|=128,f.flags|=131072,f.flags&=-52805,f.tag===1&&(f.alternate===null?f.tag=17:(l=T0(-1,1),l.tag=2,An(f,l,1))),f.lanes|=1),u;return u.flags|=65536,u.lanes=n,u}var Oz=B0.ReactCurrentOwner,xf=!1;function Bf(u,l,f,r){l.child=u===null?rU(l,null,f,r):T1(l,u.child,f,r)}function xj(u,l,f,r,n){f=f.render;var i=l.ref;if(w1(l,n),r=rA(u,l,f,r,i,n),f=nA(),u!==null&&!xf)return l.updateQueue=u.updateQueue,l.flags&=-2053,u.lanes&=~n,H0(u,l,n);return Tl&&f&&v4(l),l.flags|=1,Bf(u,l,r,n),l.child}function hj(u,l,f,r,n){if(u===null){var i=f.type;if(typeof i==="function"&&!UA(i)&&i.defaultProps===void 0&&f.compare===null&&f.defaultProps===void 0)return l.tag=15,l.type=i,HU(u,l,i,r,n);return u=h$(f.type,null,r,l,l.mode,n),u.ref=l.ref,u.return=l,l.child=u}if(i=u.child,(u.lanes&n)===0){var y=i.memoizedProps;if(f=f.compare,f=f!==null?f:Ut,f(y,r)&&u.ref===l.ref)return H0(u,l,n)}return l.flags|=1,u=Un(i,r),u.ref=l.ref,u.return=l,l.child=u}function HU(u,l,f,r,n){if(u!==null){var i=u.memoizedProps;if(Ut(i,r)&&u.ref===l.ref)if(xf=!1,l.pendingProps=r=i,(u.lanes&n)!==0)(u.flags&131072)!==0&&(xf=!0);else return l.lanes=u.lanes,H0(u,l,n)}return Q4(u,l,f,r,n)}function BU(u,l,f){var r=l.pendingProps,n=r.children,i=u!==null?u.memoizedState:null;if(r.mode==="hidden")if((l.mode&1)===0)l.memoizedState={baseLanes:0,cachePool:null,transitions:null},ql(J1,yr),yr|=f;else{if((f&1073741824)===0)return u=i!==null?i.baseLanes|f:f,l.lanes=l.childLanes=1073741824,l.memoizedState={baseLanes:u,cachePool:null,transitions:null},l.updateQueue=null,ql(J1,yr),yr|=u,null;l.memoizedState={baseLanes:0,cachePool:null,transitions:null},r=i!==null?i.baseLanes:f,ql(J1,yr),yr|=r}else i!==null?(r=i.baseLanes|f,l.memoizedState=null):r=f,ql(J1,yr),yr|=r;return Bf(u,l,n,f),l.child}function VU(u,l){var f=l.ref;if(u===null&&f!==null||u!==null&&u.ref!==f)l.flags|=512,l.flags|=2097152}function Q4(u,l,f,r,n){var i=bf(f)?ci:Lf.current;if(i=G1(l,i),w1(l,n),f=rA(u,l,f,r,i,n),r=nA(),u!==null&&!xf)return l.updateQueue=u.updateQueue,l.flags&=-2053,u.lanes&=~n,H0(u,l,n);return Tl&&r&&v4(l),l.flags|=1,Bf(u,l,f,n),l.child}function bj(u,l,f,r,n){if(bf(f)){var i=!0;u3(l)}else i=!1;if(w1(l,n),l.stateNode===null)M$(u,l),EU(l,f,r),U4(l,f,r,n),r=!0;else if(u===null){var{stateNode:y,memoizedProps:t}=l;y.props=t;var _=y.context,c=f.contextType;typeof c==="object"&&c!==null?c=Tr(c):(c=bf(f)?ci:Lf.current,c=G1(l,c));var A=f.getDerivedStateFromProps,j=typeof A==="function"||typeof y.getSnapshotBeforeUpdate==="function";j||typeof y.UNSAFE_componentWillReceiveProps!=="function"&&typeof y.componentWillReceiveProps!=="function"||(t!==r||_!==c)&&Pj(l,y,r,c),ln=!1;var F=l.memoizedState;y.state=F,i3(l,r,y,n),_=l.memoizedState,t!==r||F!==_||hf.current||ln?(typeof A==="function"&&(F4(l,f,A,r),_=l.memoizedState),(t=ln||mj(l,f,t,r,F,_,c))?(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"&&(l.flags|=4194308)):(typeof y.componentDidMount==="function"&&(l.flags|=4194308),l.memoizedProps=r,l.memoizedState=_),y.props=r,y.state=_,y.context=c,r=t):(typeof y.componentDidMount==="function"&&(l.flags|=4194308),r=!1)}else{y=l.stateNode,iU(u,l),t=l.memoizedProps,c=l.type===l.elementType?t:pr(l.type,t),y.props=c,j=l.pendingProps,F=y.context,_=f.contextType,typeof _==="object"&&_!==null?_=Tr(_):(_=bf(f)?ci:Lf.current,_=G1(l,_));var J=f.getDerivedStateFromProps;(A=typeof J==="function"||typeof y.getSnapshotBeforeUpdate==="function")||typeof y.UNSAFE_componentWillReceiveProps!=="function"&&typeof y.componentWillReceiveProps!=="function"||(t!==j||F!==_)&&Pj(l,y,r,_),ln=!1,F=l.memoizedState,y.state=F,i3(l,r,y,n);var Q=l.memoizedState;t!==j||F!==Q||hf.current||ln?(typeof J==="function"&&(F4(l,f,J,r),Q=l.memoizedState),(c=ln||mj(l,f,c,r,F,Q,_)||!1)?(A||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"&&(l.flags|=4),typeof y.getSnapshotBeforeUpdate==="function"&&(l.flags|=1024)):(typeof y.componentDidUpdate!=="function"||t===u.memoizedProps&&F===u.memoizedState||(l.flags|=4),typeof y.getSnapshotBeforeUpdate!=="function"||t===u.memoizedProps&&F===u.memoizedState||(l.flags|=1024),l.memoizedProps=r,l.memoizedState=Q),y.props=r,y.state=Q,y.context=_,r=c):(typeof y.componentDidUpdate!=="function"||t===u.memoizedProps&&F===u.memoizedState||(l.flags|=4),typeof y.getSnapshotBeforeUpdate!=="function"||t===u.memoizedProps&&F===u.memoizedState||(l.flags|=1024),r=!1)}return N4(u,l,f,r,i,n)}function N4(u,l,f,r,n,i){VU(u,l);var y=(l.flags&128)!==0;if(!r&&!y)return n&&Hj(l,f,!1),H0(u,l,i);r=l.stateNode,Oz.current=l;var t=y&&typeof f.getDerivedStateFromError!=="function"?null:r.render();return l.flags|=1,u!==null&&y?(l.child=T1(l,u.child,null,i),l.child=T1(l,null,t,i)):Bf(u,l,t,i),l.memoizedState=r.state,n&&Hj(l,f,!0),l.child}function DU(u){var l=u.stateNode;l.pendingContext?Oj(u,l.pendingContext,l.pendingContext!==l.context):l.context&&Oj(u,l.context,!1),e4(u,l.containerInfo)}function vj(u,l,f,r,n){return z1(),I4(n),l.flags|=256,Bf(u,l,f,r),l.child}var q4={dehydrated:null,treeContext:null,retryLane:0};function W4(u){return{baseLanes:u,cachePool:null,transitions:null}}function XU(u,l,f){var r=l.pendingProps,n=Ol.current,i=!1,y=(l.flags&128)!==0,t;if((t=y)||(t=u!==null&&u.memoizedState===null?!1:(n&2)!==0),t)i=!0,l.flags&=-129;else if(u===null||u.memoizedState!==null)n|=1;if(ql(Ol,n&1),u===null){if(A4(l),u=l.memoizedState,u!==null&&(u=u.dehydrated,u!==null))return(l.mode&1)===0?l.lanes=1:u.data==="$!"?l.lanes=8:l.lanes=1073741824,null;return y=r.children,u=r.fallback,i?(r=l.mode,i=l.child,y={mode:"hidden",children:y},(r&1)===0&&i!==null?(i.childLanes=0,i.pendingProps=y):i=z3(y,r,0,null),u=$i(u,r,f,null),i.return=l,u.return=l,i.sibling=u,l.child=i,l.child.memoizedState=W4(f),l.memoizedState=q4,u):tA(l,y)}if(n=u.memoizedState,n!==null&&(t=n.dehydrated,t!==null))return Hz(u,l,y,r,t,n,f);if(i){i=r.fallback,y=l.mode,n=u.child,t=n.sibling;var _={mode:"hidden",children:r.children};return(y&1)===0&&l.child!==n?(r=l.child,r.childLanes=0,r.pendingProps=_,l.deletions=null):(r=Un(n,_),r.subtreeFlags=n.subtreeFlags&14680064),t!==null?i=Un(t,i):(i=$i(i,y,f,null),i.flags|=2),i.return=l,r.return=l,r.sibling=i,l.child=r,r=i,i=l.child,y=u.child.memoizedState,y=y===null?W4(f):{baseLanes:y.baseLanes|f,cachePool:null,transitions:y.transitions},i.memoizedState=y,i.childLanes=u.childLanes&~f,l.memoizedState=q4,r}return i=u.child,u=i.sibling,r=Un(i,{mode:"visible",children:r.children}),(l.mode&1)===0&&(r.lanes=f),r.return=l,r.sibling=null,u!==null&&(f=l.deletions,f===null?(l.deletions=[u],l.flags|=16):f.push(u)),l.child=r,l.memoizedState=null,r}function tA(u,l){return l=z3({mode:"visible",children:l},u.mode,0,null),l.return=u,u.child=l}function B$(u,l,f,r){return r!==null&&I4(r),T1(l,u.child,null,f),u=tA(l,l.pendingProps.children),u.flags|=2,l.memoizedState=null,u}function Hz(u,l,f,r,n,i,y){if(f){if(l.flags&256)return l.flags&=-257,r=V8(Error(Ju(422))),B$(u,l,y,r);if(l.memoizedState!==null)return l.child=u.child,l.flags|=128,null;return i=r.fallback,n=l.mode,r=z3({mode:"visible",children:r.children},n,0,null),i=$i(i,n,y,null),i.flags|=2,r.return=l,i.return=l,r.sibling=i,l.child=r,(l.mode&1)!==0&&T1(l,u.child,null,y),l.child.memoizedState=W4(y),l.memoizedState=q4,i}if((l.mode&1)===0)return B$(u,l,y,null);if(n.data==="$!"){if(r=n.nextSibling&&n.nextSibling.dataset,r)var t=r.dgst;return r=t,i=Error(Ju(419)),r=V8(i,r,void 0),B$(u,l,y,r)}if(t=(y&u.childLanes)!==0,xf||t){if(r=uf,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,O0(u,n),Mr(r,u,n,-1))}return FA(),r=V8(Error(Ju(421))),B$(u,l,y,r)}if(n.data==="$?")return l.flags|=128,l.child=u.child,l=xz.bind(null,u),n._reactRetry=l,null;return u=i.treeContext,tr=cn(n.nextSibling),_r=l,Tl=!0,Pr=null,u!==null&&(Lr[Kr++]=G0,Lr[Kr++]=z0,Lr[Kr++]=Ai,G0=u.id,z0=u.overflow,Ai=l),l=tA(l,r.children),l.flags|=4096,l}function kj(u,l,f){u.lanes|=l;var r=u.alternate;r!==null&&(r.lanes|=l),j4(u.return,l,f)}function D8(u,l,f,r,n){var i=u.memoizedState;i===null?u.memoizedState={isBackwards:l,rendering:null,renderingStartTime:0,last:r,tail:f,tailMode:n}:(i.isBackwards=l,i.rendering=null,i.renderingStartTime=0,i.last=r,i.tail=f,i.tailMode=n)}function SU(u,l,f){var r=l.pendingProps,n=r.revealOrder,i=r.tail;if(Bf(u,l,r.children,f),r=Ol.current,(r&2)!==0)r=r&1|2,l.flags|=128;else{if(u!==null&&(u.flags&128)!==0)u:for(u=l.child;u!==null;){if(u.tag===13)u.memoizedState!==null&&kj(u,f,l);else if(u.tag===19)kj(u,f,l);else if(u.child!==null){u.child.return=u,u=u.child;continue}if(u===l)break u;for(;u.sibling===null;){if(u.return===null||u.return===l)break u;u=u.return}u.sibling.return=u.return,u=u.sibling}r&=1}if(ql(Ol,r),(l.mode&1)===0)l.memoizedState=null;else switch(n){case"forwards":f=l.child;for(n=null;f!==null;)u=f.alternate,u!==null&&y3(u)===null&&(n=f),f=f.sibling;f=n,f===null?(n=l.child,l.child=null):(n=f.sibling,f.sibling=null),D8(l,!1,n,f,i);break;case"backwards":f=null,n=l.child;for(l.child=null;n!==null;){if(u=n.alternate,u!==null&&y3(u)===null){l.child=n;break}u=n.sibling,n.sibling=f,f=n,n=u}D8(l,!0,f,null,i);break;case"together":D8(l,!1,null,null,void 0);break;default:l.memoizedState=null}return l.child}function M$(u,l){(l.mode&1)===0&&u!==null&&(u.alternate=null,l.alternate=null,l.flags|=2)}function H0(u,l,f){if(u!==null&&(l.dependencies=u.dependencies),Fi|=l.lanes,(f&l.childLanes)===0)return null;if(u!==null&&l.child!==u.child)throw Error(Ju(153));if(l.child!==null){u=l.child,f=Un(u,u.pendingProps),l.child=f;for(f.return=l;u.sibling!==null;)u=u.sibling,f=f.sibling=Un(u,u.pendingProps),f.return=l;f.sibling=null}return l.child}function Bz(u,l,f){switch(l.tag){case 3:DU(l),z1();break;case 5:yU(l);break;case 1:bf(l.type)&&u3(l);break;case 4:e4(l,l.stateNode.containerInfo);break;case 10:var r=l.type._context,n=l.memoizedProps.value;ql(r3,r._currentValue),r._currentValue=n;break;case 13:if(r=l.memoizedState,r!==null){if(r.dehydrated!==null)return ql(Ol,Ol.current&1),l.flags|=128,null;if((f&l.child.childLanes)!==0)return XU(u,l,f);return ql(Ol,Ol.current&1),u=H0(u,l,f),u!==null?u.sibling:null}ql(Ol,Ol.current&1);break;case 19:if(r=(f&l.childLanes)!==0,(u.flags&128)!==0){if(r)return SU(u,l,f);l.flags|=128}if(n=l.memoizedState,n!==null&&(n.rendering=null,n.tail=null,n.lastEffect=null),ql(Ol,Ol.current),r)break;else return null;case 22:case 23:return l.lanes=0,BU(u,l,f)}return H0(u,l,f)}var YU,w4,pU,mU;YU=function(u,l){for(var f=l.child;f!==null;){if(f.tag===5||f.tag===6)u.appendChild(f.stateNode);else if(f.tag!==4&&f.child!==null){f.child.return=f,f=f.child;continue}if(f===l)break;for(;f.sibling===null;){if(f.return===null||f.return===l)return;f=f.return}f.sibling.return=f.return,f=f.sibling}};w4=function(){};pU=function(u,l,f,r){var n=u.memoizedProps;if(n!==r){u=l.stateNode,ti(n0.current);var i=null;switch(f){case"input":n=M8(u,n),r=M8(u,r),i=[];break;case"select":n=Bl({},n,{value:void 0}),r=Bl({},r,{value:void 0}),i=[];break;case"textarea":n=h8(u,n),r=h8(u,r),i=[];break;default:typeof n.onClick!=="function"&&typeof r.onClick==="function"&&(u.onclick=d$)}v8(f,r);var y;f=null;for(c in n)if(!r.hasOwnProperty(c)&&n.hasOwnProperty(c)&&n[c]!=null)if(c==="style"){var t=n[c];for(y in t)t.hasOwnProperty(y)&&(f||(f={}),f[y]="")}else c!=="dangerouslySetInnerHTML"&&c!=="children"&&c!=="suppressContentEditableWarning"&&c!=="suppressHydrationWarning"&&c!=="autoFocus"&&(tt.hasOwnProperty(c)?i||(i=[]):(i=i||[]).push(c,null));for(c in r){var _=r[c];if(t=n!=null?n[c]:void 0,r.hasOwnProperty(c)&&_!==t&&(_!=null||t!=null))if(c==="style")if(t){for(y in t)!t.hasOwnProperty(y)||_&&_.hasOwnProperty(y)||(f||(f={}),f[y]="");for(y in _)_.hasOwnProperty(y)&&t[y]!==_[y]&&(f||(f={}),f[y]=_[y])}else f||(i||(i=[]),i.push(c,f)),f=_;else c==="dangerouslySetInnerHTML"?(_=_?_.__html:void 0,t=t?t.__html:void 0,_!=null&&t!==_&&(i=i||[]).push(c,_)):c==="children"?typeof _!=="string"&&typeof _!=="number"||(i=i||[]).push(c,""+_):c!=="suppressContentEditableWarning"&&c!=="suppressHydrationWarning"&&(tt.hasOwnProperty(c)?(_!=null&&c==="onScroll"&&Ll("scroll",u),i||t===_||(i=[])):(i=i||[]).push(c,_))}f&&(i=i||[]).push("style",f);var c=i;if(l.updateQueue=c)l.flags|=4}};mU=function(u,l,f,r){f!==r&&(l.flags|=4)};function xy(u,l){if(!Tl)switch(u.tailMode){case"hidden":l=u.tail;for(var f=null;l!==null;)l.alternate!==null&&(f=l),l=l.sibling;f===null?u.tail=null:f.sibling=null;break;case"collapsed":f=u.tail;for(var r=null;f!==null;)f.alternate!==null&&(r=f),f=f.sibling;r===null?l||u.tail===null?u.tail=null:u.tail.sibling=null:r.sibling=null}}function Wf(u){var l=u.alternate!==null&&u.alternate.child===u.child,f=0,r=0;if(l)for(var n=u.child;n!==null;)f|=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;)f|=n.lanes|n.childLanes,r|=n.subtreeFlags,r|=n.flags,n.return=u,n=n.sibling;return u.subtreeFlags|=r,u.childLanes=f,l}function Vz(u,l,f){var r=l.pendingProps;switch(k4(l),l.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Wf(l),null;case 1:return bf(l.type)&&e$(),Wf(l),null;case 3:if(r=l.stateNode,E1(),Kl(hf),Kl(Lf),lA(),r.pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),u===null||u.child===null)O$(l)?l.flags|=4:u===null||u.memoizedState.isDehydrated&&(l.flags&256)===0||(l.flags|=1024,Pr!==null&&(O4(Pr),Pr=null));return w4(u,l),Wf(l),null;case 5:uA(l);var n=ti(Wt.current);if(f=l.type,u!==null&&l.stateNode!=null)pU(u,l,f,r,n),u.ref!==l.ref&&(l.flags|=512,l.flags|=2097152);else{if(!r){if(l.stateNode===null)throw Error(Ju(166));return Wf(l),null}if(u=ti(n0.current),O$(l)){r=l.stateNode,f=l.type;var i=l.memoizedProps;switch(r[f0]=l,r[Nt]=i,u=(l.mode&1)!==0,f){case"dialog":Ll("cancel",r),Ll("close",r);break;case"iframe":case"object":case"embed":Ll("load",r);break;case"video":case"audio":for(n=0;n",u=u.removeChild(u.firstChild)):typeof r.is==="string"?u=y.createElement(f,{is:r.is}):(u=y.createElement(f),f==="select"&&(y=u,r.multiple?y.multiple=!0:r.size&&(y.size=r.size))):u=y.createElementNS(u,f),u[f0]=l,u[Nt]=r,YU(u,l,!1,!1),l.stateNode=u;u:{switch(y=k8(f,r),f){case"dialog":Ll("cancel",u),Ll("close",u),n=r;break;case"iframe":case"object":case"embed":Ll("load",u),n=r;break;case"video":case"audio":for(n=0;nO1&&(l.flags|=128,r=!0,xy(i,!1),l.lanes=4194304)}else{if(!r)if(u=y3(y),u!==null){if(l.flags|=128,r=!0,f=u.updateQueue,f!==null&&(l.updateQueue=f,l.flags|=4),xy(i,!0),i.tail===null&&i.tailMode==="hidden"&&!y.alternate&&!Tl)return Wf(l),null}else 2*ml()-i.renderingStartTime>O1&&f!==1073741824&&(l.flags|=128,r=!0,xy(i,!1),l.lanes=4194304);i.isBackwards?(y.sibling=l.child,l.child=y):(f=i.last,f!==null?f.sibling=y:l.child=y,i.last=y)}if(i.tail!==null)return l=i.tail,i.rendering=l,i.tail=l.sibling,i.renderingStartTime=ml(),l.sibling=null,f=Ol.current,ql(Ol,r?f&1|2:f&1),l;return Wf(l),null;case 22:case 23:return jA(),r=l.memoizedState!==null,u!==null&&u.memoizedState!==null!==r&&(l.flags|=8192),r&&(l.mode&1)!==0?(yr&1073741824)!==0&&(Wf(l),l.subtreeFlags&6&&(l.flags|=8192)):Wf(l),null;case 24:return null;case 25:return null}throw Error(Ju(156,l.tag))}function Dz(u,l){switch(k4(l),l.tag){case 1:return bf(l.type)&&e$(),u=l.flags,u&65536?(l.flags=u&-65537|128,l):null;case 3:return E1(),Kl(hf),Kl(Lf),lA(),u=l.flags,(u&65536)!==0&&(u&128)===0?(l.flags=u&-65537|128,l):null;case 5:return uA(l),null;case 13:if(Kl(Ol),u=l.memoizedState,u!==null&&u.dehydrated!==null){if(l.alternate===null)throw Error(Ju(340));z1()}return u=l.flags,u&65536?(l.flags=u&-65537|128,l):null;case 19:return Kl(Ol),null;case 4:return E1(),null;case 10:return a4(l.type._context),null;case 22:case 23:return jA(),null;case 24:return null;default:return null}}var V$=!1,wf=!1,Xz=typeof WeakSet==="function"?WeakSet:Set,Zu=null;function U1(u,l){var f=u.ref;if(f!==null)if(typeof f==="function")try{f(null)}catch(r){Dl(u,l,r)}else f.current=null}function L4(u,l,f){try{f()}catch(r){Dl(u,l,r)}}var Ij=!1;function Sz(u,l){if(n4=s$,u=xF(),b4(u)){if("selectionStart"in u)var f={start:u.selectionStart,end:u.selectionEnd};else u:{f=(f=u.ownerDocument)&&f.defaultView||window;var r=f.getSelection&&f.getSelection();if(r&&r.rangeCount!==0){f=r.anchorNode;var{anchorOffset:n,focusNode:i}=r;r=r.focusOffset;try{f.nodeType,i.nodeType}catch(W){f=null;break u}var y=0,t=-1,_=-1,c=0,A=0,j=u,F=null;l:for(;;){for(var J;;){if(j!==f||n!==0&&j.nodeType!==3||(t=y+n),j!==i||r!==0&&j.nodeType!==3||(_=y+r),j.nodeType===3&&(y+=j.nodeValue.length),(J=j.firstChild)===null)break;F=j,j=J}for(;;){if(j===u)break l;if(F===f&&++c===n&&(t=y),F===i&&++A===r&&(_=y),(J=j.nextSibling)!==null)break;j=F,F=j.parentNode}j=J}f=t===-1||_===-1?null:{start:t,end:_}}else f=null}f=f||{start:0,end:0}}else f=null;i4={focusedElem:u,selectionRange:f},s$=!1;for(Zu=l;Zu!==null;)if(l=Zu,u=l.child,(l.subtreeFlags&1028)!==0&&u!==null)u.return=l,Zu=u;else for(;Zu!==null;){l=Zu;try{var Q=l.alternate;if((l.flags&1024)!==0)switch(l.tag){case 0:case 11:case 15:break;case 1:if(Q!==null){var{memoizedProps:w,memoizedState:L}=Q,U=l.stateNode,N=U.getSnapshotBeforeUpdate(l.elementType===l.type?w:pr(l.type,w),L);U.__reactInternalSnapshotBeforeUpdate=N}break;case 3:var q=l.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(Ju(163))}}catch(W){Dl(l,l.return,W)}if(u=l.sibling,u!==null){u.return=l.return,Zu=u;break}Zu=l.return}return Q=Ij,Ij=!1,Q}function nt(u,l,f){var r=l.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&&L4(l,f,i)}n=n.next}while(n!==r)}}function K3(u,l){if(l=l.updateQueue,l=l!==null?l.lastEffect:null,l!==null){var f=l=l.next;do{if((f.tag&u)===u){var r=f.create;f.destroy=r()}f=f.next}while(f!==l)}}function K4(u){var l=u.ref;if(l!==null){var f=u.stateNode;switch(u.tag){case 5:u=f;break;default:u=f}typeof l==="function"?l(u):l.current=u}}function PU(u){var l=u.alternate;l!==null&&(u.alternate=null,PU(l)),u.child=null,u.deletions=null,u.sibling=null,u.tag===5&&(l=u.stateNode,l!==null&&(delete l[f0],delete l[Nt],delete l[_4],delete l[Qz],delete l[Nz])),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 CU(u){return u.tag===5||u.tag===3||u.tag===4}function gj(u){u:for(;;){for(;u.sibling===null;){if(u.return===null||CU(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 G4(u,l,f){var r=u.tag;if(r===5||r===6)u=u.stateNode,l?f.nodeType===8?f.parentNode.insertBefore(u,l):f.insertBefore(u,l):(f.nodeType===8?(l=f.parentNode,l.insertBefore(u,f)):(l=f,l.appendChild(u)),f=f._reactRootContainer,f!==null&&f!==void 0||l.onclick!==null||(l.onclick=d$));else if(r!==4&&(u=u.child,u!==null))for(G4(u,l,f),u=u.sibling;u!==null;)G4(u,l,f),u=u.sibling}function z4(u,l,f){var r=u.tag;if(r===5||r===6)u=u.stateNode,l?f.insertBefore(u,l):f.appendChild(u);else if(r!==4&&(u=u.child,u!==null))for(z4(u,l,f),u=u.sibling;u!==null;)z4(u,l,f),u=u.sibling}var _f=null,mr=!1;function e0(u,l,f){for(f=f.child;f!==null;)MU(u,l,f),f=f.sibling}function MU(u,l,f){if(r0&&typeof r0.onCommitFiberUnmount==="function")try{r0.onCommitFiberUnmount(U3,f)}catch(t){}switch(f.tag){case 5:wf||U1(f,l);case 6:var r=_f,n=mr;_f=null,e0(u,l,f),_f=r,mr=n,_f!==null&&(mr?(u=_f,f=f.stateNode,u.nodeType===8?u.parentNode.removeChild(f):u.removeChild(f)):_f.removeChild(f.stateNode));break;case 18:_f!==null&&(mr?(u=_f,f=f.stateNode,u.nodeType===8?T8(u.parentNode,f):u.nodeType===1&&T8(u,f),jt(u)):T8(_f,f.stateNode));break;case 4:r=_f,n=mr,_f=f.stateNode.containerInfo,mr=!0,e0(u,l,f),_f=r,mr=n;break;case 0:case 11:case 14:case 15:if(!wf&&(r=f.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?L4(f,l,y):(i&4)!==0&&L4(f,l,y)),n=n.next}while(n!==r)}e0(u,l,f);break;case 1:if(!wf&&(U1(f,l),r=f.stateNode,typeof r.componentWillUnmount==="function"))try{r.props=f.memoizedProps,r.state=f.memoizedState,r.componentWillUnmount()}catch(t){Dl(f,l,t)}e0(u,l,f);break;case 21:e0(u,l,f);break;case 22:f.mode&1?(wf=(r=wf)||f.memoizedState!==null,e0(u,l,f),wf=r):e0(u,l,f);break;default:e0(u,l,f)}}function sj(u){var l=u.updateQueue;if(l!==null){u.updateQueue=null;var f=u.stateNode;f===null&&(f=u.stateNode=new Xz),l.forEach(function(r){var n=hz.bind(null,u,r);f.has(r)||(f.add(r),r.then(n,n))})}}function Yr(u,l){var f=l.deletions;if(f!==null)for(var r=0;rn&&(n=y),r&=~i}if(r=n,r=ml()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3000>r?3000:4320>r?4320:1960*pz(r/1960))-r,10u?16:u,yn===null)var r=!1;else{if(u=yn,yn=null,A3=0,(rl&6)!==0)throw Error(Ju(331));var n=rl;rl|=4;for(Zu=u.current;Zu!==null;){var i=Zu,y=i.child;if((Zu.flags&16)!==0){var t=i.deletions;if(t!==null){for(var _=0;_ml()-cA?_i(u,0):$A|=f),vf(u,l)}function gU(u,l){l===0&&((u.mode&1)===0?l=1:(l=K$,K$<<=1,(K$&130023424)===0&&(K$=4194304)));var f=Vf();u=O0(u,l),u!==null&&(zt(u,l,f),vf(u,f))}function xz(u){var l=u.memoizedState,f=0;l!==null&&(f=l.retryLane),gU(u,f)}function hz(u,l){var f=0;switch(u.tag){case 13:var{stateNode:r,memoizedState:n}=u;n!==null&&(f=n.retryLane);break;case 19:r=u.stateNode;break;default:throw Error(Ju(314))}r!==null&&r.delete(l),gU(u,f)}var sU;sU=function(u,l,f){if(u!==null)if(u.memoizedProps!==l.pendingProps||hf.current)xf=!0;else{if((u.lanes&f)===0&&(l.flags&128)===0)return xf=!1,Bz(u,l,f);xf=(u.flags&131072)!==0?!0:!1}else xf=!1,Tl&&(l.flags&1048576)!==0&&eF(l,f3,l.index);switch(l.lanes=0,l.tag){case 2:var r=l.type;M$(u,l),u=l.pendingProps;var n=G1(l,Lf.current);w1(l,f),n=rA(null,l,r,u,n,f);var i=nA();return l.flags|=1,typeof n==="object"&&n!==null&&typeof n.render==="function"&&n.$$typeof===void 0?(l.tag=1,l.memoizedState=null,l.updateQueue=null,bf(r)?(i=!0,u3(l)):i=!1,l.memoizedState=n.state!==null&&n.state!==void 0?n.state:null,d4(l),n.updater=L3,l.stateNode=n,n._reactInternals=l,U4(l,r,u,f),l=N4(null,l,r,!0,i,f)):(l.tag=0,Tl&&i&&v4(l),Bf(null,l,n,f),l=l.child),l;case 16:r=l.elementType;u:{switch(M$(u,l),u=l.pendingProps,n=r._init,r=n(r._payload),l.type=r,n=l.tag=vz(r),u=pr(r,u),n){case 0:l=Q4(null,l,r,u,f);break u;case 1:l=bj(null,l,r,u,f);break u;case 11:l=xj(null,l,r,u,f);break u;case 14:l=hj(null,l,r,pr(r.type,u),f);break u}throw Error(Ju(306,r,""))}return l;case 0:return r=l.type,n=l.pendingProps,n=l.elementType===r?n:pr(r,n),Q4(u,l,r,n,f);case 1:return r=l.type,n=l.pendingProps,n=l.elementType===r?n:pr(r,n),bj(u,l,r,n,f);case 3:u:{if(DU(l),u===null)throw Error(Ju(387));r=l.pendingProps,i=l.memoizedState,n=i.element,iU(u,l),i3(l,r,null,f);var y=l.memoizedState;if(r=y.element,i.isDehydrated)if(i={element:r,isDehydrated:!1,cache:y.cache,pendingSuspenseBoundaries:y.pendingSuspenseBoundaries,transitions:y.transitions},l.updateQueue.baseState=i,l.memoizedState=i,l.flags&256){n=Z1(Error(Ju(423)),l),l=vj(u,l,r,f,n);break u}else if(r!==n){n=Z1(Error(Ju(424)),l),l=vj(u,l,r,f,n);break u}else for(tr=cn(l.stateNode.containerInfo.firstChild),_r=l,Tl=!0,Pr=null,f=rU(l,null,r,f),l.child=f;f;)f.flags=f.flags&-3|4096,f=f.sibling;else{if(z1(),r===n){l=H0(u,l,f);break u}Bf(u,l,r,f)}l=l.child}return l;case 5:return yU(l),u===null&&A4(l),r=l.type,n=l.pendingProps,i=u!==null?u.memoizedProps:null,y=n.children,y4(r,n)?y=null:i!==null&&y4(r,i)&&(l.flags|=32),VU(u,l),Bf(u,l,y,f),l.child;case 6:return u===null&&A4(l),null;case 13:return XU(u,l,f);case 4:return e4(l,l.stateNode.containerInfo),r=l.pendingProps,u===null?l.child=T1(l,null,r,f):Bf(u,l,r,f),l.child;case 11:return r=l.type,n=l.pendingProps,n=l.elementType===r?n:pr(r,n),xj(u,l,r,n,f);case 7:return Bf(u,l,l.pendingProps,f),l.child;case 8:return Bf(u,l,l.pendingProps.children,f),l.child;case 12:return Bf(u,l,l.pendingProps.children,f),l.child;case 10:u:{if(r=l.type._context,n=l.pendingProps,i=l.memoizedProps,y=n.value,ql(r3,r._currentValue),r._currentValue=y,i!==null)if(Rr(i.value,y)){if(i.children===n.children&&!hf.current){l=H0(u,l,f);break u}}else for(i=l.child,i!==null&&(i.return=l);i!==null;){var t=i.dependencies;if(t!==null){y=i.child;for(var _=t.firstContext;_!==null;){if(_.context===r){if(i.tag===1){_=T0(-1,f&-f),_.tag=2;var c=i.updateQueue;if(c!==null){c=c.shared;var A=c.pending;A===null?_.next=_:(_.next=A.next,A.next=_),c.pending=_}}i.lanes|=f,_=i.alternate,_!==null&&(_.lanes|=f),j4(i.return,f,l),t.lanes|=f;break}_=_.next}}else if(i.tag===10)y=i.type===l.type?null:i.child;else if(i.tag===18){if(y=i.return,y===null)throw Error(Ju(341));y.lanes|=f,t=y.alternate,t!==null&&(t.lanes|=f),j4(y,f,l),y=i.sibling}else y=i.child;if(y!==null)y.return=i;else for(y=i;y!==null;){if(y===l){y=null;break}if(i=y.sibling,i!==null){i.return=y.return,y=i;break}y=y.return}i=y}Bf(u,l,n.children,f),l=l.child}return l;case 9:return n=l.type,r=l.pendingProps.children,w1(l,f),n=Tr(n),r=r(n),l.flags|=1,Bf(u,l,r,f),l.child;case 14:return r=l.type,n=pr(r,l.pendingProps),n=pr(r.type,n),hj(u,l,r,n,f);case 15:return HU(u,l,l.type,l.pendingProps,f);case 17:return r=l.type,n=l.pendingProps,n=l.elementType===r?n:pr(r,n),M$(u,l),l.tag=1,bf(r)?(u=!0,u3(l)):u=!1,w1(l,f),EU(l,r,n),U4(l,r,n,f),N4(null,l,r,!0,u,f);case 19:return SU(u,l,f);case 22:return BU(u,l,f)}throw Error(Ju(156,l.tag))};function aU(u,l){return GF(u,l)}function bz(u,l,f,r){this.tag=u,this.key=f,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=l,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 Gr(u,l,f,r){return new bz(u,l,f,r)}function UA(u){return u=u.prototype,!(!u||!u.isReactComponent)}function vz(u){if(typeof u==="function")return UA(u)?1:0;if(u!==void 0&&u!==null){if(u=u.$$typeof,u===X4)return 11;if(u===S4)return 14}return 2}function Un(u,l){var f=u.alternate;return f===null?(f=Gr(u.tag,l,u.key,u.mode),f.elementType=u.elementType,f.type=u.type,f.stateNode=u.stateNode,f.alternate=u,u.alternate=f):(f.pendingProps=l,f.type=u.type,f.flags=0,f.subtreeFlags=0,f.deletions=null),f.flags=u.flags&14680064,f.childLanes=u.childLanes,f.lanes=u.lanes,f.child=u.child,f.memoizedProps=u.memoizedProps,f.memoizedState=u.memoizedState,f.updateQueue=u.updateQueue,l=u.dependencies,f.dependencies=l===null?null:{lanes:l.lanes,firstContext:l.firstContext},f.sibling=u.sibling,f.index=u.index,f.ref=u.ref,f}function h$(u,l,f,r,n,i){var y=2;if(r=u,typeof u==="function")UA(u)&&(y=1);else if(typeof u==="string")y=5;else u:switch(u){case i1:return $i(f.children,n,i,l);case D4:y=8,n|=8;break;case p8:return u=Gr(12,f,l,n|2),u.elementType=p8,u.lanes=i,u;case m8:return u=Gr(13,f,l,n),u.elementType=m8,u.lanes=i,u;case P8:return u=Gr(19,f,l,n),u.elementType=P8,u.lanes=i,u;case yF:return z3(f,n,i,l);default:if(typeof u==="object"&&u!==null)switch(u.$$typeof){case nF:y=10;break u;case iF:y=9;break u;case X4:y=11;break u;case S4:y=14;break u;case un:y=16,r=null;break u}throw Error(Ju(130,u==null?u:typeof u,""))}return l=Gr(y,f,l,n),l.elementType=u,l.type=r,l.lanes=i,l}function $i(u,l,f,r){return u=Gr(7,u,r,l),u.lanes=f,u}function z3(u,l,f,r){return u=Gr(22,u,r,l),u.elementType=yF,u.lanes=f,u.stateNode={isHidden:!1},u}function X8(u,l,f){return u=Gr(6,u,null,l),u.lanes=f,u}function S8(u,l,f){return l=Gr(4,u.children!==null?u.children:[],u.key,l),l.lanes=f,l.stateNode={containerInfo:u.containerInfo,pendingChildren:null,implementation:u.implementation},l}function kz(u,l,f,r,n){this.tag=l,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=q8(0),this.expirationTimes=q8(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=q8(0),this.identifierPrefix=r,this.onRecoverableError=n,this.mutableSourceEagerHydrationData=null}function JA(u,l,f,r,n,i,y,t,_){return u=new kz(u,l,f,t,_),l===1?(l=1,i===!0&&(l|=8)):l=0,i=Gr(3,null,null,l),u.current=i,i.stateNode=u,i.memoizedState={element:r,isDehydrated:f,cache:null,transitions:null,pendingSuspenseBoundaries:null},d4(i),u}function Iz(u,l,f){var r=3{function lJ(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=="function")return;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(lJ)}catch(u){console.error(u)}}lJ(),fJ.exports=uJ()});var nJ=ir((wA)=>{var rJ=WA();wA.createRoot=rJ.createRoot,wA.hydrateRoot=rJ.hydrateRoot;var dz});var rN=ir((Ac)=>{var JO=Jl(),QO=Symbol.for("react.element"),NO=Symbol.for("react.fragment"),qO=Object.prototype.hasOwnProperty,WO=JO.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,wO={key:!0,ref:!0,__self:!0,__source:!0};function fN(u,l,f){var r,n={},i=null,y=null;f!==void 0&&(i=""+f),l.key!==void 0&&(i=""+l.key),l.ref!==void 0&&(y=l.ref);for(r in l)qO.call(l,r)&&!wO.hasOwnProperty(r)&&(n[r]=l[r]);if(u&&u.defaultProps)for(r in l=u.defaultProps,l)n[r]===void 0&&(n[r]=l[r]);return{$$typeof:QO,type:u,key:i,ref:y,props:n,_owner:WO.current}}Ac.Fragment=NO;Ac.jsx=fN;Ac.jsxs=fN});var iN=ir((KP,nN)=>{nN.exports=rN()});var pq=ir((Yq)=>{var cy=Jl();function mV(u,l){return u===l&&(u!==0||1/u===1/l)||u!==u&&l!==l}var PV=typeof Object.is==="function"?Object.is:mV,CV=cy.useState,MV=cy.useEffect,RV=cy.useLayoutEffect,xV=cy.useDebugValue;function hV(u,l){var f=l(),r=CV({inst:{value:f,getSnapshot:l}}),n=r[0].inst,i=r[1];return RV(function(){n.value=f,n.getSnapshot=l,A9(n)&&i({inst:n})},[u,f,l]),MV(function(){return A9(n)&&i({inst:n}),u(function(){A9(n)&&i({inst:n})})},[u]),xV(f),f}function A9(u){var l=u.getSnapshot;u=u.value;try{var f=l();return!PV(u,f)}catch(r){return!0}}function bV(u,l){return l()}var vV=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?bV:hV;Yq.useSyncExternalStore=cy.useSyncExternalStore!==void 0?cy.useSyncExternalStore:vV});var Pq=ir((Jb,mq)=>{mq.exports=pq()});var Mq=ir((Cq)=>{var n6=Jl(),kV=Pq();function IV(u,l){return u===l&&(u!==0||1/u===1/l)||u!==u&&l!==l}var gV=typeof Object.is==="function"?Object.is:IV,sV=kV.useSyncExternalStore,aV=n6.useRef,oV=n6.useEffect,dV=n6.useMemo,eV=n6.useDebugValue;Cq.useSyncExternalStoreWithSelector=function(u,l,f,r,n){var i=aV(null);if(i.current===null){var y={hasValue:!1,value:null};i.current=y}else y=i.current;i=dV(function(){function _(J){if(!c){if(c=!0,A=J,J=r(J),n!==void 0&&y.hasValue){var Q=y.value;if(n(Q,J))return j=Q}return j=J}if(Q=j,gV(A,J))return Q;var w=r(J);if(n!==void 0&&n(Q,w))return A=J,Q;return A=J,j=w}var c=!1,A,j,F=f===void 0?null:f;return[function(){return _(l())},F===null?void 0:function(){return _(F())}]},[l,f,r,n]);var t=sV(u,i[0],i[1]);return oV(function(){y.hasValue=!0,y.value=t},[t]),eV(t),t}});var xq=ir((Nb,Rq)=>{Rq.exports=Mq()});var gn=Pu(Jl(),1);var c$="北京时间";var IK={timeZone:"Asia/Shanghai",hour12:!1},gK={timeZone:"Asia/Shanghai",hour12:!1},sK=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 f8(u){if(u===null||u===void 0||u==="")return null;let l=u instanceof Date?u:new Date(u);return Number.isNaN(l.getTime())?null:l}function R7(u){let l=f8(u);if(!l)return null;return sK.formatToParts(l).reduce((f,r)=>{if(r.type!=="literal")f[r.type]=r.value;return f},{})}function qu(u){let l=f8(u);return l?l.toLocaleString("zh-CN",IK):"--"}function tl(u){let l=f8(u);return l?l.toLocaleTimeString("zh-CN",gK):"--"}function r8(u){let l=R7(u);if(!l)return"";let f=l.hour==="24"?"00":l.hour;return`${l.year}-${l.month}-${l.day}T${f}:${l.minute}`}function x7(u=new Date){let l=R7(u);if(!l)return"";return`${l.year}-${l.month}-${l.day}`}function h7(u){if(!u)return null;let l=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(u);if(!l)return null;let[,f,r,n,i,y,t="00"]=l,_=Date.UTC(Number(f),Number(r)-1,Number(n),Number(i)-8,Number(y),Number(t)),c=new Date(_),A=r8(c);return Number.isNaN(c.getTime())||A!==`${f}-${r}-${n}T${i}:${y}`?null:c.toISOString()}var JL=Pu(nJ(),1);var V3=Pu(Jl(),1);var iJ=Pu(Jl(),1),Ot=iJ.default.createElement;function ez({active:u=!0,label:l="正在加载"}){if(!u)return null;return Ot("span",{className:"loading-spinner-indicator",role:"status","aria-label":l,title:l,"data-testid":"loading-title-indicator"},Ot("span",{className:"loading-spinner-ring","aria-hidden":!0}))}function nl({title:u,children:l,loading:f,level:r=2,className:n="",label:i="正在加载"}){return Ot(r===3?"h3":"h2",{className:`loading-title ${f?"is-loading":""} ${n}`.trim()},Ot("span",{className:"loading-title-text"},l??u),Ot(ez,{active:Boolean(f),label:i}))}class V1 extends Error{unideskRequestError=!0;meta;constructor(u,l){super(u);this.name="UniDeskRequestError",this.meta=l}}function uT(u){return new Promise((l)=>setTimeout(l,u))}function Vt(u,l="操作失败"){return u instanceof Error?u.message:String(u||l)}function H3(u,l=500){if(u===null||u===void 0)return"";let f=typeof u==="string"?u:JSON.stringify(u),r=String(f||"").replace(/\s+/gu," ").trim();return r.length>l?`${r.slice(0,l)}...`:r}function lT(u){try{let l=typeof location<"u"&&location.origin?location.origin:"http://localhost";return new URL(u,l).toString()}catch{return u}}function yJ(u){return String(u.method||"GET").toUpperCase()}function fT(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 tJ(u){let l=new Headers(u.headers||{}),f=fT(u.body)?JSON.stringify(u.body):u.body;if(f&&!l.has("content-type")&&typeof f==="string")l.set("content-type","application/json");return{...u,credentials:u.credentials||"same-origin",body:f,headers:l}}function _J(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 rT(u,l){if(!u||typeof u!=="object"||Array.isArray(u))return!1;return l.some((f)=>f!==!1&&u[f]===!1)}function Ht(u,l,f,r,n={}){return{kind:u,method:f,url:lT(l),occurredAt:r.toISOString(),...n}}function Bt(u,l){if(!u)return"请求失败";return`HTTP ${u}${l?` ${l}`:""}`}function $J(u){try{return{body:u?JSON.parse(u):null,parseError:""}}catch(l){return{body:{text:u},parseError:Vt(l,"parse failed")}}}async function Tu(u,l={},f=0){let{failureFields:r=["ok"],strictJson:n=!1,retryInvalidJson:i=0,retryDelayMs:y=120,invalidJsonPrefix:t="服务返回了无效 JSON",invalidJsonPreview:_=!1,responsePreviewLength:c=500,...A}=l,j=yJ(A),F=new Date,J;try{J=await fetch(u,tJ(A))}catch(L){let U=Vt(L,"网络请求失败");throw new V1(U,Ht("network",u,j,F,{upstreamMessage:U}))}let Q=await J.text(),w=$J(Q);if(w.parseError){if(n&&j==="GET"&&f=300)?Bt(u.meta.status,u.meta.statusText):"应用请求失败",i=u.meta.status?Bt(u.meta.status):"",y=(_)=>!_||_===n||_===i,t=!y(u.message)?u.message:y(u.meta.upstreamMessage)?"":u.meta.upstreamMessage||"";return{title:n,message:t,status:u.meta.status,statusText:u.meta.statusText,method:u.meta.method,url:u.meta.url,occurredAt:nT(u.meta.occurredAt),responsePreview:u.meta.responsePreview,parseError:u.meta.parseError,structured:!0}}let r=Vt(u,l).split(/\r?\n/u);return{title:r[0]||l,message:r.slice(1).join(` +`),structured:r.length>1}}function iT(u,l="操作失败"){let f=LA(u,l),r=[f.title];if(f.message)r.push(`原因: ${f.message}`);if(f.method||f.url)r.push(`请求: ${[f.method,f.url].filter(Boolean).join(" ")}`);if(f.status)r.push(`状态: ${Bt(f.status,f.statusText)}`);if(f.occurredAt)r.push(`时间: ${f.occurredAt}`);if(f.parseError)r.push(`解析错误: ${f.parseError}`);if(f.responsePreview&&f.responsePreview!==f.message)r.push(`响应预览: ${f.responsePreview}`);return r.filter(Boolean).join(` +`)}function Ou(u,l="操作失败"){return AJ(u)?iT(u,l):Vt(u,l)}var jJ=Pu(Jl(),1);var wn=jJ.default.createElement;function Dt(u,l){return l?[wn("dt",{key:`${u}-label`},u),wn("dd",{key:u},l)]:null}function il({error:u,wide:l=!1,fallback:f="操作失败",className:r=""}){if(!u)return null;let n=LA(u,f),i=[Dt("请求",[n.method,n.url].filter(Boolean).join(" ")),Dt("状态",n.status?`HTTP ${n.status}${n.statusText?` ${n.statusText}`:""}`:""),Dt("时间",n.occurredAt),Dt("解析错误",n.parseError),Dt("响应预览",n.responsePreview)].filter(Boolean);return wn("div",{className:`form-error unidesk-error${l?" 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 i0=Pu(Jl(),1),FJ=i0.default.createContext(null);function UJ({children:u}){let[l,f]=i0.default.useState([]),[r,n]=i0.default.useState(Date.now()),i=i0.default.useCallback((j,F)=>{let Q={id:`notif_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:j,message:F,timestamp:Date.now()};f((w)=>{let L=[...w,Q];if(L.length>50)return L.slice(-50);return L})},[]),y=i0.default.useCallback((j)=>{f((F)=>F.filter((J)=>J.id!==j))},[]),t=i0.default.useCallback(()=>{f([]),n(Date.now())},[]),_=i0.default.useMemo(()=>{return l.filter((j)=>j.timestamp>r).length},[l,r]),c=_>0,A={notifications:l,addNotification:i,removeNotification:y,clearNotifications:t,unreadCount:_,hasUnread:c};return yT(FJ.Provider,{value:A},u)}var yT=i0.default.createElement;function Xf(){let u=i0.default.useContext(FJ);if(!u)throw Error("useNotification must be used within NotificationProvider");return u}var R=V3.default.createElement,{useEffect:B3}=V3.default,D1=V3.default.useState;function Kf(u,l={}){return Tu(u,{failureFields:["ok","success"],...l})}function Sf(u,l){return`${u}/microservices/baidu-netdisk/proxy${l}`}function tT(u){let l=Number(u);return Number.isFinite(l)?l.toLocaleString("zh-CN"):"--"}function Ln(u){let l=Number(u);if(!Number.isFinite(l)||l<=0)return"--";let f=["B","KB","MB","GB","TB"],r=l,n=0;while(r>=1024&&n{n?.stopPropagation?.(),f(u,l)}},"查看原始JSON")}function S1({title:u,text:l}){return R("div",{className:"empty-state"},R("strong",null,u),R("span",null,l))}function Y1({title:u,text:l,href:f,badge:r,testId:n}){return R("a",{className:"doc-link-card",href:f,target:"_blank",rel:"noreferrer","data-testid":n},R("span",null,r||"DOC"),R("strong",null,u),R("p",null,l),R("code",null,f))}function _T(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 cT(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function AT(u){return Array.isArray(u?.files)?u.files:[]}function jT(u){return Array.isArray(u?.jobs)?u.jobs:[]}function FT(u,l){if(!u||u===l)return l;let f=u.replace(/\/+$/u,""),r=f.slice(0,f.lastIndexOf("/"))||l;return r.lengthx.id==="baidu-netdisk")||null,[n,i]=D1({loading:!1,actionLoading:!1,error:"",message:"",health:null,account:null,files:null,transfers:null,logs:null,selfTest:null,refreshedAt:null}),[y,t]=D1("/"),[_,c]=D1(null),[A,j]=D1(""),[F,J]=D1({localPath:"sample.txt",remotePath:"/sample.txt"}),[Q,w]=D1({fsId:"",localPath:"downloads/"}),{addNotification:L}=Xf(),U=n.health?.baidu?.appRoot||n.account?.rootPath||"/";B3(()=>{J((x)=>{let lu=new Set(["/sample.txt","/apps/UniDeskBaiduNetdisk/sample.txt"]);if(x.remotePath&&!lu.has(x.remotePath))return x;let _u=KA(U,"sample.txt");return x.remotePath===_u?x:{...x,remotePath:_u}})},[U]);async function N(x=y){let _u=await Kf(Sf(f,`/api/files?dir=${encodeURIComponent(x||U)}&limit=100`));i(($u)=>({...$u,files:_u}))}async function q(){let x=await Kf(Sf(f,"/api/transfers?limit=80"));i((lu)=>({...lu,transfers:x}))}async function W(){if(!r)return;i((x)=>({...x,loading:!0,error:"",message:""}));try{let x=await Kf(`${f}/microservices/baidu-netdisk/health`),lu=x?.baidu?.appRoot||U,_u=null,$u=null;if(x?.auth?.loggedIn){_u=await Kf(Sf(f,"/api/account?refresh=1"));let Wu=y&&y.startsWith(lu)?y:lu;t(Wu),$u=await Kf(Sf(f,`/api/files?dir=${encodeURIComponent(Wu)}&limit=100`))}else t(lu);let ju=await Kf(Sf(f,"/api/transfers?limit=80")),zu=await Kf(Sf(f,"/logs?limit=60"));i((Wu)=>({...Wu,loading:!1,health:x,account:_u?.account||null,files:$u,transfers:ju,logs:zu,refreshedAt:new Date}))}catch(x){i((lu)=>({...lu,loading:!1,error:Ou(x,"百度网盘服务加载失败")}))}}async function z(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{let x=await Kf(Sf(f,"/api/auth/device/start"),{method:"POST",body:{}});c(x.session||null),i((lu)=>({...lu,actionLoading:!1,message:"设备码已生成,请扫码授权"}))}catch(x){i((lu)=>({...lu,actionLoading:!1,error:Ou(x,"创建设备码失败")}))}}async function Z(x=!1){if(!_?.id)return;if(x)i((lu)=>({...lu,actionLoading:!0,error:""}));try{let lu=await Kf(Sf(f,`/api/auth/device/status?sessionId=${encodeURIComponent(_.id)}`));if(c(lu.session||null),lu.session?.status==="succeeded")i((_u)=>({..._u,actionLoading:!1,message:"授权成功,正在刷新账号与文件列表"})),await W();else if(x)i((_u)=>({..._u,actionLoading:!1}))}catch(lu){i((_u)=>({..._u,actionLoading:!1,error:Ou(lu,"轮询登录状态失败")}))}}async function H(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{await Kf(Sf(f,"/api/auth/logout"),{method:"POST",body:{}}),c(null),i((x)=>({...x,actionLoading:!1,account:null,files:null,message:"本地 token 已清除"})),await W()}catch(x){i((lu)=>({...lu,actionLoading:!1,error:Ou(x,"退出登录失败")}))}}async function E(x){x.preventDefault();let lu=A.trim();if(!lu)return;i((_u)=>({..._u,actionLoading:!0,error:"",message:""}));try{await Kf(Sf(f,"/api/folders"),{method:"POST",body:{path:KA(y,lu)}}),j(""),i((_u)=>({..._u,actionLoading:!1,message:"文件夹已创建"})),await N(y)}catch(_u){i(($u)=>({...$u,actionLoading:!1,error:Ou(_u,"创建文件夹失败")}))}}async function D(x){if(!x)return;i((lu)=>({...lu,actionLoading:!0,error:"",message:""}));try{await Kf(Sf(f,"/api/files/manage"),{method:"POST",body:{opera:"delete",filelist:[{path:x}],async:1}}),i((lu)=>({...lu,actionLoading:!1,message:"删除任务已提交"})),await N(y)}catch(lu){i((_u)=>({..._u,actionLoading:!1,error:Ou(lu,"删除失败")}))}}async function h(x){x.preventDefault(),i((lu)=>({...lu,actionLoading:!0,error:"",message:""}));try{await Kf(Sf(f,"/api/transfers/upload-from-path"),{method:"POST",body:F}),i((lu)=>({...lu,actionLoading:!1,message:"上传任务已入队"})),await q()}catch(lu){i((_u)=>({..._u,actionLoading:!1,error:Ou(lu,"上传任务创建失败")}))}}async function V(x){x.preventDefault(),i((lu)=>({...lu,actionLoading:!0,error:"",message:""}));try{await Kf(Sf(f,"/api/transfers/download-to-path"),{method:"POST",body:Q}),i((lu)=>({...lu,actionLoading:!1,message:"下载任务已入队"})),await q()}catch(lu){i((_u)=>({..._u,actionLoading:!1,error:Ou(lu,"下载任务创建失败")}))}}async function S(x,lu){i((_u)=>({..._u,actionLoading:!0,error:"",message:""}));try{await Kf(Sf(f,`/api/transfers/${encodeURIComponent(x)}/${lu}`),{method:"POST",body:{}}),i((_u)=>({..._u,actionLoading:!1,message:lu==="cancel"?"已请求取消任务":"任务已重新入队"})),await q()}catch(_u){i(($u)=>({...$u,actionLoading:!1,error:Ou(_u,"任务操作失败")}))}}async function p(){i((x)=>({...x,actionLoading:!0,error:"",message:"正在运行上传/下载自测..."}));try{let x=await Kf(Sf(f,"/api/self-test"),{method:"POST",body:{}});i((lu)=>({...lu,actionLoading:!1,selfTest:x,message:`上传/下载自测通过:${x.remotePath||""}`})),await N(y),await q()}catch(x){i((lu)=>({...lu,actionLoading:!1,error:Ou(x,"上传/下载自测失败")}))}}if(B3(()=>{if(!r)return;W();return},[r?.id,r?.runtime?.providerStatus]),B3(()=>{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]),B3(()=>{if(!r)return;let x=window.setInterval(()=>void q(),5000);return()=>window.clearInterval(x)},[r?.id]),!r)return R(S1,{title:"Baidu Netdisk 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=baidu-netdisk"});let O=_T(r),m=cT(r),X=$T(r),v=n.health||{},T=n.account||v.auth?.account||null,Y=v.auth||{},k=AT(n.files),I=jT(n.transfers),b=T?.quota||{},o=Boolean(Y.loggedIn||T),g=Boolean(Y.configured);return R("div",{className:"baidu-netdisk-page","data-testid":"baidu-netdisk-page"},R(qi,{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(V0,{title:"Baidu Netdisk 用户服务",data:r,onOpen:l,testId:"raw-baidu-netdisk-service"}))},R("div",{className:"baidu-netdisk-hero"},R("div",null,R("div",{className:"node-version-line"},R(Ni,{status:O.providerStatus==="online"?"online":"warn"},O.providerStatus||"unknown"),R("span",null,r.providerId),R(Ni,{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(il,{error:n.error,wide:!0})),R("div",{className:"metric-grid"},R(X1,{label:"Health",value:v.ok?"OK":"--",hint:v.storage?.postgres||"postgres",tone:v.ok?"ok":"warn"}),R(X1,{label:"OAuth",value:g?"已配置":"待配置",hint:g?"client + secret + token key":"需要设置 UNIDESK_BAIDU_NETDISK_*",tone:g?"ok":"warn"}),R(X1,{label:"Login",value:o?"已登录":"未登录",hint:T?.username||"Device Code QR",tone:o?"ok":"warn"}),R(X1,{label:"Work Root",value:UT(U),hint:U}),R(X1,{label:"Quota",value:Ln(b.used),hint:b.total?`${b.usedPercent||0}% / ${Ln(b.total)}`:"授权后刷新"}),R(X1,{label:"Transfers",value:tT(I.length),hint:`running ${n.transfers?.counts?.running||0} / failed ${n.transfers?.counts?.failed||0}`})),R(qi,{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,U);t(x),N(x)},disabled:!o||y===U},"上级"),R("button",{type:"button",className:"ghost-btn",onClick:()=>N(y),disabled:!o},"刷新文件"),R(V0,{title:"Baidu Files",data:n.files,onOpen:l,testId:"raw-baidu-files"}))},R("form",{className:"baidu-pathbar",onSubmit:(x)=>{x.preventDefault(),N(y)}},R("input",{value:y,onChange:(x)=>t(x.target.value),disabled:!o}),R("button",{type:"submit",className:"ghost-btn",disabled:!o},"打开路径")),R("form",{className:"baidu-pathbar",onSubmit:E},R("input",{value:A,onChange:(x)=>j(x.target.value),placeholder:"新文件夹名称",disabled:!o}),R("button",{type:"submit",className:"primary-btn",disabled:!o||!A.trim()},"新建文件夹")),!o?R(S1,{title:"等待授权",text:"登录后通过 /api/files 读取工作目录文件列表"}):k.length===0?R(S1,{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(Ni,{status:x.isDir?"queued":"private"},x.isDir?"DIR":"FILE")),R("td",null,x.isDir?"--":Ln(x.size)),R("td",null,x.serverMtime?qu(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:()=>{t(x.path),N(x.path)}},"打开"):R("button",{type:"button",className:"ghost-btn",onClick:()=>w((lu)=>({...lu,fsId:x.fsId}))},"填入下载"),R("button",{type:"button",className:"ghost-btn",onClick:()=>D(x.path),disabled:n.actionLoading},"删除"))))))))),R("div",{className:"baidu-netdisk-grid"},R(qi,{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(Y1,{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(Y1,{title:"服务方案与 API",text:"说明 OAuth Device Code、根目录工作区、staging 上传下载任务和后端 API 设计。",href:"/docs/issue/baidu-netdisk-user-service.md",badge:"DESIGN"}),R(Y1,{title:"用户服务安全边界",text:"查看 UniDesk microservice 私有代理、允许路径、frontendOnly 和密钥边界规则。",href:"/docs/reference/microservices.md",badge:"REF"}),R(Y1,{title:"部署与重建流程",text:"查看 server rebuild、Compose 编排、健康检查和交付验证的长期规则。",href:"/docs/reference/deployment.md",badge:"DEPLOY"}),R(Y1,{title:"CLI 验证命令",text:"查看 microservice health/proxy、server rebuild、job status 等命令入口。",href:"/docs/reference/cli.md",badge:"CLI"}),R(Y1,{title:"百度设备码模式",text:"打开百度官方 OAuth Device Code 文档,对照扫码登录和轮询参数。",href:"https://pan.baidu.com/union/doc/fl1x114ti",badge:"OFFICIAL"}))),R(qi,{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(V0,{title:"Baidu Device Session",data:_||Y.latestSession,onOpen:l,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(S1,{title:g?"等待二维码":"OAuth 未配置",text:g?"点击生成二维码后使用百度网盘或百度 App 扫码":"设置 client id、secret 和 token key 后重建服务"})),R("div",{className:"claudeqq-login-copy"},R("div",{className:"node-version-line"},R(Ni,{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?qu(_.expiresAt):"--"),R("code",null,_?.error||"no token exposed"))))),R(qi,{title:"账号与容量",eyebrow:n.refreshedAt?`Updated ${tl(n.refreshedAt)}`:"Account",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(V0,{title:"Baidu Account",data:T,onOpen:l,testId:"raw-baidu-account"}))},T?R("div",{className:"baidu-account-card"},R("div",{className:"node-version-line"},R(Ni,{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||U};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(S1,{title:"尚未登录",text:"扫码授权后这里会显示账号、UID、会员状态和容量"})),R(qi,{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(V0,{title:"Baidu Transfers",data:n.transfers,onOpen:l,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)=>J((lu)=>({...lu,localPath:x.target.value})),placeholder:"sample.txt"})),R("label",null,"百度网盘目标路径",R("input",{value:F.remotePath,onChange:(x)=>J((lu)=>({...lu,remotePath:x.target.value})),placeholder:KA(U,"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)=>w((lu)=>({...lu,fsId:x.target.value})),placeholder:"从文件表填入"})),R("label",null,"保存到 staging 路径",R("input",{value:Q.localPath,onChange:(x)=>w((lu)=>({...lu,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(Ni,{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(V0,{title:"Baidu Self Test",data:n.selfTest,onOpen:l,testId:"raw-baidu-self-test"})):null,I.length===0?R(S1,{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(Ni,{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(JT,{percent:x.progressPercent}),R("span",{className:"muted"},`${Ln(x.bytesDone)} / ${Ln(x.sizeBytes)}`)),R("td",null,qu(x.updatedAt)),R("td",null,R("div",{className:"inline-actions"},["queued","running"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>S(x.id,"cancel")},"取消"):null,["failed","canceled"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>S(x.id,"retry")},"重试"):null,R(V0,{title:`Transfer ${x.id}`,data:x,onOpen:l}))))))))),R(qi,{title:"安全与日志",eyebrow:"redacted diagnostics",className:"baidu-wide-panel",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(V0,{title:"Baidu Health",data:v,onOpen:l,testId:"raw-baidu-health"}),R(V0,{title:"Baidu Logs",data:n.logs,onOpen:l,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 S3=Pu(Jl(),1);var a=S3.default.createElement,{useEffect:QT}=S3.default,D3=S3.default.useState,Wi={label:"主用户私聊账号",userId:645275593};function GA(u){let l=Number(u);return Number.isFinite(l)?l.toLocaleString("zh-CN"):"--"}async function Kn(u,l={}){return Tu(u,{failureFields:["ok","success"],...l})}async function NT(u){let l=await fetch(u,{credentials:"same-origin"}),f=await l.text();try{return f?JSON.parse(f):{ok:l.ok,status:l.status}}catch{return{ok:l.ok,status:l.status,text:f}}}function X3({status:u,children:l}){let f=String(u||"unknown").toLowerCase();return a("span",{className:`status-badge ${f}`},l||u||"unknown")}function p1({label:u,value:l,hint:f,tone:r}){return a("article",{className:`metric-card ${r||""}`},a("div",{className:"metric-label"},u),a("div",{className:"metric-value"},l),a("div",{className:"metric-hint"},f))}function m1({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){return a("section",{className:`panel ${n||""}`},a("div",{className:"panel-head"},a("div",null,l?a("p",{className:"panel-eyebrow"},l):null,a(nl,{title:u,loading:i})),f?a("div",{className:"panel-actions"},f):null),a("div",{className:"panel-body"},r))}function Xt({title:u,data:l,onOpen:f,testId:r}){return a("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),f(u,l)}},"查看原始JSON")}function St({title:u,text:l}){return a("div",{className:"empty-state"},a("strong",null,u),a("span",null,l))}function qT(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function WT(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function wT(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Gn(u,l){return`${u}/microservices/claudeqq/proxy${l}`}function LT(u){return Array.isArray(u?.events)?u.events.slice(0,80):[]}function KT(u){return Array.isArray(u?.subscriptions)?u.subscriptions.slice(0,50):[]}function GT(u){return Array.isArray(u?.messages)?u.messages.slice(0,30):[]}function QJ(u){let l=u?.text??u?.message??u?.raw?.raw_message;if(typeof l!=="string")return"--";return l.length>180?`${l.slice(0,177)}...`:l}function NJ(u){let l=u?.groupId??u?.group_id??(u?.message_type==="group"?u?.target_id:void 0),f=u?.userId??u?.user_id??(u?.message_type==="private"?u?.target_id:void 0);if(l)return`群 ${l}`;if(f)return`私聊 ${f}`;return"--"}function qJ({microservices:u,onRaw:l,apiBaseUrl:f="/api"}){let r=u.find((T)=>T.id==="claudeqq")||null,[n,i]=D3({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,t]=D3({targetType:"private",targetId:String(Wi.userId),message:""}),[_,c]=D3({name:"unidesk-callback",targetUrl:"",eventTypes:"message",secret:""}),[A,j]=D3(""),{addNotification:F}=Xf();async function J(){if(!r)return;i((T)=>({...T,loading:!0,error:""}));try{let[T,Y,k,I,b]=await Promise.all([NT(`${f}/microservices/claudeqq/health`),Kn(Gn(f,"/api/server/status")),Kn(Gn(f,"/api/events/recent?limit=60")),Kn(Gn(f,"/api/events/subscriptions")),Kn(Gn(f,"/api/messages/sent?limit=20"))]);if(i((o)=>({...o,loading:!1,error:"",health:T,status:Y,events:k,subscriptions:I,sent:b,refreshedAt:new Date})),!n.qrcodeFetched)Q(!1)}catch(T){i((Y)=>({...Y,loading:!1,error:Ou(T,"ClaudeQQ 加载失败")}))}}async function Q(T=!0){if(!r)return;i((Y)=>({...Y,qrLoading:!0,error:T?"":Y.error}));try{let Y=await Kn(Gn(f,"/api/napcat/login")),k=Y?.napcat?.qrcode||Y?.qrcode||null;i((I)=>({...I,qrLoading:!1,error:"",napcatLogin:Y,napcatQrcode:k,qrcodeFetched:!0,qrcodeRefreshedAt:new Date}))}catch(Y){i((k)=>({...k,qrLoading:!1,error:T||!k.napcatQrcode?Ou(Y,"NapCat 二维码加载失败"):k.error}))}}async function w(T){T.preventDefault(),j("");let Y=Number(y.targetId);if(!Number.isFinite(Y)||Y<=0||y.message.trim().length===0){i((k)=>({...k,error:"请填写 QQ 目标和消息内容"}));return}try{await Kn(Gn(f,"/api/push/text"),{method:"POST",body:JSON.stringify({userId:y.targetType==="private"?Y:void 0,groupId:y.targetType==="group"?Y:void 0,message:y.message})});let k="消息推送请求已提交";t((I)=>({...I,targetType:"private",targetId:String(Wi.userId),message:""})),j(k),F("success",k),await J()}catch(k){i((I)=>({...I,error:Ou(k,"发送失败")}))}}async function L(T){if(T.preventDefault(),j(""),_.targetUrl.trim().length===0){i((Y)=>({...Y,error:"请填写订阅回调 URL"}));return}try{await Kn(Gn(f,"/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 Y="事件订阅已创建";j(Y),F("success",Y),await J()}catch(Y){i((k)=>({...k,error:Ou(Y,"订阅失败")}))}}async function U(T){if(!T)return;j("");try{await Kn(Gn(f,`/api/events/subscriptions/${encodeURIComponent(T)}`),{method:"DELETE"});let Y="事件订阅已删除";j(Y),F("success",Y),await J()}catch(Y){i((k)=>({...k,error:Ou(Y,"删除订阅失败")}))}}if(QT(()=>{if(!r)return;J();return},[r?.id,r?.runtime?.providerStatus]),!r)return a(St,{title:"ClaudeQQ 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=claudeqq"});let N=qT(r),q=wT(r),W=WT(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||{},S=LT(n.events),p=KT(n.subscriptions),O=GT(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(m1,{title:"ClaudeQQ 工作台",eyebrow:"D601 QQ Event Gateway",loading:n.loading,actions:a("div",{className:"panel-actions"},a("button",{type:"button",className:"ghost-btn",onClick:J,disabled:n.loading,"data-testid":"claudeqq-refresh-button"},n.loading?"刷新中":"刷新"),a(Xt,{title:"ClaudeQQ 用户服务",data:r,onOpen:l,testId:"raw-claudeqq-service"}))},a("div",{className:"findjob-hero"},a("div",null,a("div",{className:"node-version-line"},a(X3,{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(il,{error:n.error,wide:!0})),a("div",{className:"metric-grid"},a(p1,{label:"Health",value:z.ok||z.status==="ok"?"OK":"--",hint:"D601 /health",tone:z.ok||z.status==="ok"?"ok":"warn"}),a(p1,{label:"NapCat HTTP",value:D.httpConnected||D.http?.connected?"OK":"离线",hint:`${D.httpHost||z.napcat?.httpHost||"--"}:${D.httpPort||z.napcat?.httpPort||"--"}`}),a(p1,{label:"NapCat WS",value:D.wsConnected||D.ws?.connected?"OK":"离线",hint:`${D.wsHost||z.napcat?.wsHost||"--"}:${D.wsPort||z.napcat?.wsPort||"--"}`}),a(p1,{label:"事件缓存",value:GA(n.events?.count??S.length),hint:"recent QQ events"}),a(p1,{label:"订阅",value:GA(n.subscriptions?.count??p.length),hint:"webhook subscribers"}),a(p1,{label:"已发送",value:GA(n.sent?.count??O.length),hint:"sent message log"})),a("div",{className:"findjob-grid"},a(m1,{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(Xt,{title:"NapCat Login",data:n.napcatLogin,onOpen:l,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(St,{title:"等待二维码",text:"NapCat 容器启动后会把登录二维码写入 cache/qrcode.png"})),a("div",{className:"claudeqq-login-copy"},a("div",{className:"node-version-line"},a(X3,{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?qu(V.modifiedAt):n.qrcodeRefreshedAt?qu(n.qrcodeRefreshedAt):"--"),a("code",null,V.file||"/napcat/cache/qrcode.png"))))),a(m1,{title:"消息推送",eyebrow:"Push API"},a("div",{className:"microservice-ref-card"},a("span",null,Wi.label),a("strong",null,String(Wi.userId)),a("code",null,"private userId / 默认推送测试目标")),a("form",{className:"stack-form",onSubmit:w,"data-testid":"claudeqq-push-form"},a("label",null,"目标类型",a("select",{value:y.targetType,onChange:(T)=>t((Y)=>({...Y,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)=>t((Y)=>({...Y,targetId:T.target.value})),placeholder:String(Wi.userId)})),a("label",null,"消息内容",a("textarea",{value:y.message,onChange:(T)=>t((Y)=>({...Y,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;当前人工推送测试默认使用 ${Wi.label} ${Wi.userId},不需要暴露 D601 后端端口。`)),a(m1,{title:"QQ 事件订阅",eyebrow:"Webhook Subscription",loading:n.loading},a("form",{className:"stack-form",onSubmit:L,"data-testid":"claudeqq-subscription-form"},a("label",null,"订阅名称",a("input",{value:_.name,onChange:(T)=>c((Y)=>({...Y,name:T.target.value}))})),a("label",null,"回调 URL",a("input",{value:_.targetUrl,onChange:(T)=>c((Y)=>({...Y,targetUrl:T.target.value})),placeholder:"http://host.docker.internal:18080/..."})),a("label",null,"事件类型",a("input",{value:_.eventTypes,onChange:(T)=>c((Y)=>({...Y,eventTypes:T.target.value})),placeholder:"message,notice"})),a("label",null,"签名密钥",a("input",{value:_.secret,onChange:(T)=>c((Y)=>({...Y,secret:T.target.value})),placeholder:"可选,生成 x-claudeqq-signature"})),a("button",{type:"submit",className:"primary-btn"},"创建订阅")),p.length===0?a(St,{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(X3,{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"} ${qu(T.lastDelivery.at)}`:"--"),a("td",null,a("button",{type:"button",className:"ghost-btn",onClick:()=>U(T.id)},"删除"))))))),a("div",{className:"panel-actions inline-actions"},a(Xt,{title:"ClaudeQQ Subscriptions",data:n.subscriptions,onOpen:l,testId:"raw-claudeqq-subscriptions"}))),a(m1,{title:"最近 QQ 事件",eyebrow:n.refreshedAt?`Updated ${tl(n.refreshedAt)}`:"Event Stream",loading:n.loading},S.length===0?a(St,{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,S.map((T)=>a("tr",{key:T.id},a("td",null,qu(T.receivedAt||T.timestamp)),a("td",null,a(X3,{status:T.postType||T.eventType},T.postType||T.eventType||"--")),a("td",null,NJ(T)),a("td",null,QJ(T)),a("td",null,a("code",null,T.messageId||T.id||"--"))))))),a("div",{className:"panel-actions inline-actions"},a(Xt,{title:"ClaudeQQ Events",data:n.events,onOpen:l,testId:"raw-claudeqq-events"}))),a(m1,{title:"已发送消息",eyebrow:`${O.length} Sent`,loading:n.loading},O.length===0?a(St,{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,Y)=>a("tr",{key:T.id||Y},a("td",null,qu(T.timestamp||T.sentAt||T.createdAt)),a("td",null,NJ(T)),a("td",null,QJ(T)),a("td",null,T.status||T.messageId||T.message_id||"--")))))),a("div",{className:"panel-actions inline-actions"},a(Xt,{title:"ClaudeQQ Sent Messages",data:n.sent,onOpen:l,testId:"raw-claudeqq-sent"})))))}var ht=Pu(Jl(),1);var LJ=Pu(Jl(),1),Ql=LJ.default.createElement;function KJ({markdown:u,className:l,testId:f}){let r=String(u??"").trimEnd(),n=["markdown-body",l].filter(Boolean).join(" ");return Ql("div",{className:n,"data-testid":f},GJ(r,"md"))}function GJ(u,l){let f=zT(u).split(` +`),r=[],n=0;while(n\s?/u.test(i)){let j=[];while(n\s?(.*)$/u);if(J!==null){j.push(J[1]),n+=1;continue}if(F.trim().length===0){j.push(""),n+=1;continue}break}r.push(Ql("blockquote",{key:`${l}-quote-${n}`},GJ(j.join(` +`),`${l}-quote-${n}`)));continue}if(TJ(f,n)){let j=n,F=Yt(f[n]??""),J=Yt(f[n+1]??"");n+=2;let Q=[];while(n0)Q.push(Yt(f[n]??"")),n+=1;r.push(HT(F,J,Q,`${l}-table-${j}`));continue}let _=p3(i);if(_!==null){let j=n,F=_.ordered,J=_.start,Q=[];while(nZT(L,`${l}-list-${j}-${U}`))));continue}let c=n,A=[];while(n0&&!ET(f,n))A.push(f[n].trim()),n+=1;if(A.length===0)A.push(i.trim()),n+=1;r.push(Ql("p",{key:`${l}-p-${c}`},y0(A.join(` +`),`${l}-p-${c}`)))}return r}function zT(u){return String(u||"").replace(/\r\n/gu,` `).replace(/\r/gu,` -`).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 VU(u){let f=String(u||"").replace(/\r\n/gu,` +`).trimEnd()}function zJ(u){let l=u.match(/^\s*(```+|~~~+)\s*([A-Za-z0-9_-]+)?\s*$/u);if(l===null)return null;let f=l[1];return{marker:f.startsWith("`")?"`":"~",length:f.length,language:l[2]||""}}function TT(u,l){let f=u.trim();return f.length>=l.length&&f.split("").every((r)=>r===l.marker)}function zA(u){return/^(?: {4}|\t)/u.test(u)}function WJ(u,l,f){let r=l.trim().length>0?`language-${VT(l)}`:void 0;return Ql("pre",{key:f,className:"markdown-code-block"},Ql("code",{className:r},u))}function ET(u,l){let f=u[l]??"";if(f.trim().length===0)return!0;return zJ(f)!==null||zA(f)||/^(#{1,6})\s+.+$/u.test(f)||/^\s*(?:---+|\*\*\*+|___+)\s*$/u.test(f)||/^\s*>\s?/u.test(f)||TJ(u,l)||p3(f)!==null}function p3(u){let l=u.match(/^\s{0,3}[-*+]\s+(.+)$/u);if(l!==null)return{ordered:!1,text:l[1]};let f=u.match(/^\s{0,3}(\d+)[.)]\s+(.+)$/u);if(f!==null)return{ordered:!0,start:Number(f[1]),text:f[2]};return null}function ZT(u,l){let f=u.match(/^\[([ xX])\]\s+(.+)$/u);if(f!==null){let r=f[1].toLowerCase()==="x";return Ql("li",{key:l,className:"task-list-item"},Ql("input",{type:"checkbox",checked:r,readOnly:!0,tabIndex:-1}),Ql("span",null,y0(f[2],`${l}-task`)))}return Ql("li",{key:l},y0(u,l))}function TJ(u,l){let f=u[l]??"",r=u[l+1]??"";if(!f.includes("|")||!r.includes("|"))return!1;let n=Yt(f),i=Yt(r);return n.length>1&&i.length===n.length&&i.every((y)=>/^:?-{3,}:?$/u.test(y.trim()))}function Yt(u){let l=u.trim();if(l.startsWith("|"))l=l.slice(1);if(l.endsWith("|"))l=l.slice(0,-1);return l.split("|").map((f)=>f.trim())}function OT(u){let l=u.trim();if(l.startsWith(":")&&l.endsWith(":"))return"center";if(l.endsWith(":"))return"right";if(l.startsWith(":"))return"left";return}function HT(u,l,f,r){let n=l.map(OT);return Ql("div",{key:r,className:"markdown-table-wrap"},Ql("table",null,Ql("thead",null,Ql("tr",null,u.map((i,y)=>Ql("th",{key:`${r}-h-${y}`,style:n[y]?{textAlign:n[y]}:void 0},y0(i,`${r}-h-${y}`))))),Ql("tbody",null,f.map((i,y)=>Ql("tr",{key:`${r}-r-${y}`},u.map((t,_)=>Ql("td",{key:`${r}-r-${y}-${_}`,style:n[_]?{textAlign:n[_]}:void 0},y0(i[_]||"",`${r}-r-${y}-${_}`))))))))}function y0(u,l,f={}){let r=[],n=/`([^`\n]+)`|\[([^\]\n]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)|(https?:\/\/[^\s<>)]+)|\*\*([^*\n]+)\*\*|__([^_\n]+)__|~~([^~\n]+)~~|\*([^*\n]+)\*|_([^_\n]+)_/gu,i=f.linkify!==!1,y=0,t=0;for(let _ of u.matchAll(n)){let c=_[0],A=_.index??0;Y3(r,u.slice(y,A),`${l}-text-${t}`),y=A+c.length;let j=`${l}-inline-${t}`;if(t+=1,_[1]!==void 0){r.push(Ql("code",{key:j},_[1]));continue}if(_[2]!==void 0&&_[3]!==void 0){if(!i){Y3(r,c,`${j}-literal`);continue}r.push(wJ(_[2],_[3],j));continue}if(_[4]!==void 0){if(!i){Y3(r,c,`${j}-literal`);continue}r.push(wJ(_[4],_[4],j));continue}let F=_[5]??_[6];if(F!==void 0){r.push(Ql("strong",{key:j},y0(F,`${j}-strong`)));continue}if(_[7]!==void 0){r.push(Ql("del",{key:j},y0(_[7],`${j}-del`)));continue}let J=_[8]??_[9];if(J!==void 0)r.push(Ql("em",{key:j},y0(J,`${j}-em`)))}return Y3(r,u.slice(y),`${l}-text-tail`),r}function Y3(u,l,f){if(l.length===0)return;l.split(` +`).forEach((n,i)=>{if(i>0)u.push(Ql("br",{key:`${f}-br-${i}`}));if(n.length>0)u.push(n)})}function wJ(u,l,f){let r=BT(l);if(r===null)return Ql("span",{key:f},u);let n=/^(?:https?:|mailto:)/iu.test(r);return Ql("a",{key:f,href:r,target:n?"_blank":void 0,rel:n?"noreferrer":void 0},y0(u,`${f}-label`,{linkify:!1}))}function BT(u){let l=String(u||"").trim();if(/^(?:https?:|mailto:)/iu.test(l))return l;if(l.startsWith("/")&&!l.startsWith("//"))return l;if(l.startsWith("#"))return l;return null}function VT(u){return String(u||"").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-").replace(/^-+|-+$/gu,"")||"text"}var BA=Pu(Jl(),1);var Su=BA.default.createElement,{useEffect:DT,useRef:EJ}=BA.default;function XT(u,l){return xJ(u.toTrace(l))}function ST(u){let l=Number(u);if(!Number.isFinite(l)||l<0)return"--";let f=Math.floor(l/1000),r=Math.floor(f/3600),n=Math.floor(f%3600/60),i=f%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 xr(u){let l=Number(u);return Number.isFinite(l)&&l>=0?l:null}function C1(u,l=180){let f=String(u||"").replace(/\s+/gu," ").trim();return f.length>l?`${f.slice(0,l-1)}…`:f}function YT(u){if(!u)return 0;return u.split(/\r?\n/u).length}function ZA(u){return{ran:"Ran",explored:"Explored",edited:"Edited",toolGroup:"Tool calls",plan:"Plan",message:"Message",system:"System",error:"Error"}[u]||"Message"}function OA(u){let l=Number(u||0);return Number.isFinite(l)&&l>0?`… +${Math.floor(l)} lines`:""}function pT(u){return(Array.isArray(u)?u:[]).reduce((l,f)=>Math.max(l,Number(f?.seq??0)),0)}function ZJ(u){return["explored","edited","ran"].includes(String(u?.kind||""))}function YJ(u){let l={read:0,edit:0,run:0};for(let f of u){let r=String(f?.kind||"");if(r==="explored")l.read+=1;else if(r==="edited")l.edit+=1;else if(r==="ran")l.run+=1}return l}function pJ(u){let l=YJ(u);return`${l.read} read, ${l.edit} edit, ${l.run} run`}function mJ(u){return u.replace(/^['"`([{<]+/u,"").replace(/['"`)\]}>.,;:]+$/u,"").replace(/:\d+(?::\d+)?$/u,"").trim()}function OJ(u){let f=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 f){let i=mJ(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 TA(u,l=4){if(u.length===0)return"--";let f=u.slice(0,l).join(", ");return u.length>l?`${f} +${u.length-l}`:f}function HJ(u){let l="";for(let f of u){if(f.length===0)continue;if(l.length>0&&!l.endsWith(` +`)&&!f.startsWith(` +`))l+=` +`;l+=f}return l}function PJ(u){let l=String(u||"").replace(/\r\n/gu,` `).replace(/\r/gu,` -`).trimEnd();return f.length>0?f.split(` -`):[]}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(` +`).trimEnd();return l.length>0?l.split(` +`):[]}function HA(u){let l=String(u.status||"").trim();if(l.length>0)return l;let f=String(u.bodyPreview||"");return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(f)?.[1]||"item/fileChange"}function mT(u){let l=String(u.bodyPreview||"");return/file changes status=([A-Za-z0-9_-]+)/u.exec(l)?.[1]}function PT(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function CJ(u){if(String(u.kind||"")!=="edited")return!1;let l=String(u.status||""),f=String(u.title||""),r=String(u.bodyPreview||""),n=String(u.commandPreview||"");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)||n.length>0&&P3(r).length>0}function P1(u){return mJ(String(u||"").replace(/^[ab]\//u,"").trim())}function VA(u){let l=/^([AMDRCU?]{1,2})\s+(.+)$/u.exec(u);if(!l)return null;let f=P1(l[2]||"");return f.length>0?{status:l[1]||"M",path:f}:null}function DA(u){let l=/^\*\*\*\s+(Add|Update|Delete)\s+File:\s+(.+)$/u.exec(u);if(l){let r=l[1]==="Add"?"A":l[1]==="Delete"?"D":"M",n=P1(l[2]||"");return n.length>0?{status:r,path:n}:null}let f=/^\*\*\*\s+Move to:\s+(.+)$/u.exec(u);if(f){let r=P1(f[1]||"");return r.length>0?{status:"R",path:r}:null}return null}function P3(u){let l=[],f=(n,i)=>{let y=P1(i);if(y.length===0||y==="/dev/null")return;let t=l.find((_)=>_.path===y);if(t){if(t.status==="M"&&n!=="M")t.status=n;return}l.push({status:n,path:y})},r="";for(let n of PJ(u)){let i=VA(n)||DA(n);if(i!==null){f(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]||"";f("M",j),r=P1(j);continue}let t=/^\+\+\+ b\/(.+)$/u.exec(n);if(t&&t[1]!=="/dev/null"){f("M",t[1]||""),r=P1(t[1]||"");continue}if(/^new file mode /u.exec(n)&&r)f("A",r);if(/^deleted file mode /u.exec(n)&&r)f("D",r);let A=/^rename to (.+)$/u.exec(n);if(A)f("R",A[1]||"")}return l}function CT(u){if(VA(u)!==null||DA(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 XA(u){return PJ(u).map((l)=>{let f=VA(l)||DA(l);if(f!==null)return{text:l,kind:"file",path:f.path,status:f.status};return{text:l,kind:CT(l)}})}function MT(u){return u.reduce((l,f)=>{if(f.kind==="add")l.added+=1;else if(f.kind==="del")l.removed+=1;return l},{added:0,removed:0})}function BJ(u,l){return`${l} ${u} line${u===1?"":"s"}`}function RT(u,l){let f=[];if(u>0)f.push(BJ(u,"Added"));if(l>0)f.push(BJ(l,"removed"));return f.join(", ")}function xT(u){for(let f=u.length-1;f>=0;f-=1){let r=String(u[f]?.status||"").trim();if(r.length>0)return r}let l=String(u[u.length-1]?.method||"").trim();if(l==="item/fileChange/outputDelta")return"updated";if(l==="item/started")return"started";if(l==="item/completed")return"completed";return l.replace(/^item\//u,"")||"changed"}function hT(u){return`${u} file${u===1?"":"s"}`}function MJ(u){let l=u.length>0?u:[],f=HJ(l.map((F)=>String(F.bodyPreview||""))),n=HJ(l.map((F)=>String(F.bodyPreview||"")).filter((F)=>F.trim().length>0&&!PT(F)))||f,i=P3(n||f),y=l.map((F)=>({method:HA(F),status:mT(F),at:F.at})),t=XA(n||f),_=MT(t),c=RT(_.added,_.removed),A=i.length>0?hT(i.length):"",j=c.length>0?`${c}${A?` in ${A}`:""}`:i.length>0?A:C1(n||f||"File changes",72);return{status:xT(y),summary:j,files:i,stages:y,lines:t,addedLines:_.added,removedLines:_.removed,rawText:f}}function bT(u){let l=u[0],f=u[u.length-1]||l,r=MJ(u);return{...l,seq:Number.isFinite(Number(f?.seq))?Number(f?.seq):Number(l?.seq??0),at:f?.at||l?.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 vT(u){let l=Array.isArray(u)?u:[],f=[],r=[],n=()=>{if(r.length===0)return;f.push(bT(r)),r=[]};for(let i of l){if(CJ(i)){if(HA(i)==="item/started"&&r.length>0)n();if(r.push(i),HA(i)==="item/completed")n();continue}n(),f.push(i)}return n(),f}function RJ(u){let l=[],f=[],r=[],n=(c,A)=>{for(let j of A)if(!c.includes(j))c.push(j)};for(let c of u){let A=String(c?.kind||""),j=[c?.commandPreview,c?.bodyPreview,c?.title].map((F)=>String(F||"")).join(` +`);if(A==="explored")n(l,OJ(j));else if(A==="edited")n(f,OJ(j));else if(A==="ran"){let F=String(c?.commandPreview||c?.title||"").trim();if(F.length>0&&!r.includes(F))r.push(C1(F,90))}}let i=u.map((c)=>Date.parse(String(c?.at||""))).filter((c)=>Number.isFinite(c)),y=i.length>=2?Math.max(0,Math.max(...i)-Math.min(...i)):0,t=u.reduce((c,A)=>c+(xr(A?.durationMs)??xr(A?.elapsedMs)??0),0),_=y>0?y:t;return{readFiles:l,editedFiles:f,runCommands:r,durationLabel:ST(_)}}function kT(u,l=3){let f=Array.isArray(u)?u:[],r=[],n=[],i=Math.max(0,l),y=new Set;for(let _=f.length-1;_>=0&&i>0;_-=1){let c=f[_];if(!ZJ(c))continue;y.add(c),i-=1}let t=()=>{if(n.length>=2){let _=YJ(n);r.push({seq:Number(n[0]?.seq??0),at:n[0]?.at||n.at(-1)?.at,kind:"toolGroup",title:pJ(n),status:`${n.length} calls`,items:n,counts:_,digest:RJ(n),rawSeqs:n.flatMap((c)=>Array.isArray(c?.rawSeqs)?c.rawSeqs:[c?.seq]).filter((c)=>c!==void 0)})}else r.push(...n);n=[]};for(let _ of f){if(ZJ(_)&&!y.has(_)){n.push(_);continue}t(),r.push(_)}return t(),r}function xJ(u){return(Array.isArray(u)?u:[]).map((l,f)=>({...l,seq:Number.isFinite(Number(l?.seq))?Number(l.seq):f+1,kind:String(l?.kind||"message"),at:l?.at===void 0?void 0:String(l.at),durationMs:xr(l?.durationMs)??void 0,title:l?.title===void 0?void 0:String(l.title),status:l?.status===void 0?void 0:String(l.status)}))}function pt(u){let l=xr(u?.state?.time?.start)??xr(u?.time?.start),f=xr(u?.state?.time?.end)??xr(u?.time?.end);return xr(u?.durationMs)??xr(u?.elapsedMs)??xr(u?.timing?.durationMs)??xr(u?.metadata?.durationMs)??(l!==null&&f!==null&&f>=l?f-l:null)??void 0}function mt(u,l){return u?.createdAt||u?.updatedAt||u?.completedAt||l||void 0}function EA(u,l){return u?.id||u?.messageId||l}function IT(u,l=1200){if(typeof u==="string")return u;if(u===void 0||u===null)return"";try{return C1(JSON.stringify(u),l)}catch{return C1(String(u),l)}}function hJ(u,l,f){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 l?.output==="string"&&l.output.length>0)return l.output;if(typeof f?.output==="string"&&f.output.length>0)return f.output;if(typeof u?.metadata?.output==="string"&&u.metadata.output.length>0)return u.metadata.output;return""}function m3(u,l){if(!u||typeof u!=="object"||Array.isArray(u))return"";for(let f of l){let r=u[f];if(typeof r==="string"&&r.length>0)return r;if(r!==void 0&&r!==null&&typeof r!=="object")return String(r)}return""}function VJ(u,l){if(!u||typeof u!=="object"||Array.isArray(u))return null;for(let f of l){let r=Number(u[f]);if(Number.isFinite(r))return r}return null}function bJ(u,l){let f=l?.input&&typeof l.input==="object"&&!Array.isArray(l.input)?l.input:u?.input&&typeof u.input==="object"&&!Array.isArray(u.input)?u.input:{},r=m3(f,["command","cmd","script"]);if(r.length>0)return r;if(typeof u?.command==="string"&&u.command.length>0)return u.command;if(typeof l?.command==="string"&&l.command.length>0)return l.command;let n=String(u?.tool||u?.title||"tool"),i=m3(f,["filePath","filepath","path"])||m3(u,["filePath","filepath","path"]),y=m3(f,["pattern","query"]),t=VJ(f,["offset"]),_=VJ(f,["limit"]),c=[n];if(y.length>0)c.push(y);if(i.length>0)c.push(i);if(t!==null)c.push(`offset=${t}`);if(_!==null)c.push(`limit=${_}`);return c.length>1?c.join(" "):n}function gT(u,l){let f=u?.part&&typeof u.part==="object"&&!Array.isArray(u.part)?u.part:{},r=String(u?.type||u?.event||u?.name||f?.type||"").toLowerCase(),n=String(f?.type||"").toLowerCase(),i=u?.at||u?.timestamp||f?.updatedAt||f?.createdAt,y=Number.isFinite(Number(u?.seq))?Number(u.seq):l;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 _=f?.state&&typeof f.state==="object"&&!Array.isArray(f.state)?f.state:{},c=bJ(f,_),A=hJ(_,f,u),j=vJ(c,String(f?.tool||f?.title||"")),F=j==="edited"?{status:String(_?.status||f?.status||u?.status||""),summary:C1(A||c,72),files:P3(A),stages:[],lines:XA(A),addedLines:0,removedLines:0,rawText:A}:void 0;return{seq:y,at:mt(f,i),kind:j,title:String(_?.title||f?.title||_?.metadata?.description||f?.tool||"OpenCode tool"),status:String(_?.status||f?.status||u?.status||""),commandPreview:c,bodyPreview:A,durationMs:pt(f),rawSeqs:[f?.id||f?.callID||u?.sessionID||y],editObservation:F}}let t=IT(f?.text??f?.content??f?.delta??u?.text??u?.content??u?.delta,3000).trim();if(t.length>0)return{seq:y,at:mt(f,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:t,durationMs:pt(f),rawSeqs:[f?.id||u?.sessionID||y]};return null}function vJ(u,l){let f=`${l} ${u}`.toLowerCase();if(/\b(read|grep|glob|list|ls|find|search|view|cat|sed|rg|head|tail|wc|file)\b/iu.test(f))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(f))return"edited";return"ran"}function sT(u){let l=[],f=1;for(let r of Array.isArray(u)?u:[]){if(r?.kind&&r?.title){let t=String(r?.status||"");if(t==="opencode/step-start"||t==="opencode/step-finish")continue;l.push({...r,seq:Number.isFinite(Number(r?.seq))?Number(r.seq):f++});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 t=gT(r,f);if(t!==null)l.push(t),f=Math.max(f+1,Number(t.seq)+1)}else if(r?.textPreview)l.push({seq:f++,at:n,kind:"message",title:`${i||"assistant"} message`,status:i,bodyPreview:String(r.textPreview),rawSeqs:[r?.messageId||f]});continue}for(let t of y){let _=String(t?.type||"").toLowerCase();if(_==="step-start"||_==="step-finish")continue;if(_==="text"||_==="reasoning"){let A=String(t?.textPreview||r?.textPreview||"").trim();if(A.length===0)continue;l.push({seq:f++,at:mt(t,n),kind:"message",title:_==="reasoning"?"Reasoning":i==="user"?"User message":i==="system"?"System message":"Assistant message",status:_==="reasoning"?"reasoning":i,bodyPreview:A,durationMs:pt(t),rawSeqs:[EA(t,f)]});continue}if(_==="tool"){let A=t?.state&&typeof t.state==="object"&&!Array.isArray(t.state)?t.state:{},j=bJ(t,A),F=hJ(A,t,{}),J=vJ(j,String(t?.tool||t?.title||"")),Q=J==="edited"?{status:String(A?.status||t?.status||""),summary:C1(F||j,72),files:P3(F),stages:[],lines:XA(F),addedLines:0,removedLines:0,rawText:F}:void 0;l.push({seq:f++,at:mt(t,n),kind:J,title:String(t?.title||t?.tool||"tool"),status:String(t?.status||""),commandPreview:j,bodyPreview:F,durationMs:pt(t),rawSeqs:[EA(t,f)],editObservation:Q});continue}let c=String(t?.textPreview||t?.title||_||"").trim();if(c)l.push({seq:f++,at:mt(t,n),kind:"system",title:_||"part",bodyPreview:c,status:String(t?.status||""),durationMs:pt(t),rawSeqs:[EA(t,f)]})}}return l}var kJ={source:"opencode",toTrace:sT};function aT(u){return String(u||"unknown").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-")||"unknown"}function DJ(u){let l=String(u||"M").toUpperCase();if(l.startsWith("A")||l==="??")return"added";if(l.startsWith("D"))return"deleted";if(l.startsWith("R"))return"renamed";return"modified"}function oT(u){if(u==="item/fileChange/outputDelta")return"delta";return u.replace(/^item\//u,"")}function dT(u,l){if(u.kind==="file"){let n=String(u.status||"M");return Su("div",{key:`${l}-${u.text}`,className:`codex-edit-diff-line file ${DJ(n)}`},Su("span",{className:`codex-edit-file-status ${DJ(n)}`},n),Su("code",null,u.path||u.text.replace(/^([AMDRCU?]{1,2})\s+/u,"")))}let f=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:`${l}-${u.text}`,className:`codex-edit-diff-line ${u.kind}`},Su("span",{className:"codex-edit-diff-sign"},f),Su("code",null,r||" "))}function eT(u,l){let f=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 ${aT(n.status||n.method)}`},Su("b",null,oT(n.method)),n.status?Su("em",null,n.status):null))):null,f.length>0?Su("div",{className:"codex-edit-diff",role:"list"},f.map(dT)):null,l?Su("div",{className:"codex-edit-omitted"},`${l} (查看原始JSON获取完整记录)`):null)}function XJ(u,l,f){let r=OA(f);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"},l,r?` +${r} (查看原始JSON获取完整记录)`:""))}function IJ(u,l=!1){let f=String(u.kind||"message"),r=["ran","explored","edited"].includes(f),n=OA(u.commandOmittedLines),i=OA(u.bodyOmittedLines),y=String(u.commandPreview||(r?u.title||"":"")),t=String(u.stdoutPreview||""),_=String(u.stderrPreview||""),c=t.length>0||_.length>0,A=Boolean(u.foldedReferencePrompt)&&String(u.fullPrompt||"").length>0,j=f==="edited"&&(u.editObservation!==void 0||CJ(u))?u.editObservation||MJ([u]):null;return Su("article",{key:`${u.seq}-${f}`,className:`codex-transcript-item ${f} ${l?"nested":""}`},Su("div",{className:"codex-transcript-main"},Su("div",{className:"codex-transcript-title"},Su("span",{className:"codex-output-channel"},ZA(f)),r&&j===null?null:Su("strong",null,j!==null?"File changes":String(u.title||ZA(f))),u.status?Su("code",null,String(j?.status||u.status)):null,Su("time",null,qu(u.at))),y&&j===null?Su("pre",{className:"codex-transcript-command"},y,n?` +${n}`:""):null,j!==null?eT(j,i):c?Su("div",{className:"codex-transcript-streams"},t.length>0?XJ("stdout",t,u.stdoutOmittedLines):null,_.length>0?XJ("stderr",_,u.stderrOmittedLines):null):u.bodyPreview?Su("pre",{className:"codex-transcript-body"},String(u.bodyPreview),i?` +${i} (查看原始JSON获取完整记录)`:""):null,A?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||YT(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 uE(u){let l=Array.isArray(u.items)?u.items:[],f=u.digest&&typeof u.digest==="object"?u.digest:RJ(l);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"},ZA("toolGroup")),Su("strong",null,String(u.title||pJ(l))),Su("code",null,String(u.status||`${l.length} calls`)),Su("time",null,qu(u.at)))),Su("div",{className:"codex-tool-group-digest"},Su("span",null,`read: ${TA(Array.isArray(f.readFiles)?f.readFiles:[])}`),Su("span",null,`edit: ${TA(Array.isArray(f.editedFiles)?f.editedFiles:[])}`),Su("span",null,`run: ${TA(Array.isArray(f.runCommands)?f.runCommands:[],2)}`),Su("span",null,`duration: ${f.durationLabel||"--"}`)),Su("div",{className:"codex-tool-group-items"},l.map((r)=>IJ(r,!0))))))}function lE(u){let l=[u.title,u.status,u.bodyPreview,u.commandPreview,u.stderrPreview,u.stdoutPreview].map((f)=>String(f||"")).join(` +`);return/\b(error|failed|failure|interrupt|interrupted|cancell?ed|watchdog|timeout|closed|refused|aborted|exception)\b/iu.test(l)}function gJ(u,l){if(l)return u;return u.flatMap((f)=>{if(String(f.kind||"")==="system"&&!lE(f))return[];if(String(f.kind||"")!=="toolGroup"||!Array.isArray(f.items))return[f];let r=gJ(f.items,l);return[{...f,items:r}]})}var fE=16;function SJ(u){return u.scrollHeight-u.scrollTop-u.clientHeight<=fE}function C3({items:u,input:l,port:f,autoScroll:r=!1,loading:n=!1,hasDetail:i=!0,emptyText:y="等待 Trace 输出...",loadingText:t="正在加载完整 Trace...",testId:_="trace-output",className:c="codex-transcript",keepRecentToolCalls:A=3,collapseTools:j=!0,showSystemEvents:F=!1}){let J=EJ(null),Q=EJ(!0),w=gJ(vT(f?XT(f,l):xJ(u)),Boolean(F)),L=j?kT(w,A):w,U=pT(w);DT(()=>{let W=J.current;if(!r||!W)return;if(!Q.current&&!SJ(W))return;W.scrollTop=W.scrollHeight,Q.current=!0},[r,w.length,U]);let q={className:c,ref:J,onScroll:(W)=>{let z=W.currentTarget;Q.current=SJ(z)},"data-testid":_};if(n&&!i)return Su("div",q,Su("div",{className:"codex-output-empty"},t));return Su("div",q,L.length===0?Su("div",{className:"codex-output-empty"},y):L.map((W)=>String(W.kind||"")==="toolGroup"?uE(W):IJ(W)))}var sJ=Pu(Jl(),1),wi=sJ.default.createElement;function M3(...u){return u.filter(Boolean).join(" ")}function aJ({title:u,children:l,actions:f,onClose:r,className:n,backdropClassName:i,bodyClassName:y,actionsClassName:t,titleId:_,testId:c,closeTestId:A,closeLabel:j="关闭",disableClose:F=!1,closeOnBackdrop:J=!0}){let Q={className:M3("raw-dialog","unidesk-dialog",n),role:"dialog","aria-modal":"true"};if(_)Q["aria-labelledby"]=_;else if(typeof u==="string")Q["aria-label"]=u;if(c)Q["data-testid"]=c;return wi("div",{className:M3("modal-backdrop","unidesk-dialog-backdrop",i),role:"presentation",onClick:(w)=>{if(J&&!F&&w.target===w.currentTarget)r()}},wi("section",Q,wi("div",{className:"raw-dialog-head unidesk-dialog-head"},wi("strong",_?{id:_}:null,u),wi("button",{type:"button",className:"ghost-btn",onClick:r,disabled:F,"data-testid":A},j)),wi("div",{className:M3("unidesk-dialog-body",y)},l),f?wi("div",{className:M3("unidesk-dialog-actions",t)},f):null))}var K=ht.default.createElement,{useEffect:Tn,useMemo:oJ,useRef:Xl}=ht.default,ku=ht.default.useState,rE=120,jQ=24,FQ=48,nE=1200;function SA(){return typeof document>"u"||document.visibilityState!=="hidden"}function Af(u,l="操作失败"){return Ou(u,l)}function br(u){let l=Number(u);if(!Number.isFinite(l)||l<0)return"--";let f=Math.floor(l/1000),r=Math.floor(f/3600),n=Math.floor(f%3600/60),i=f%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 l=u instanceof Date?u.getTime():new Date(u).getTime();return Number.isFinite(l)?l:null}function UQ(u,l=Date.now()){let f=Y0(u);if(f===null)return"--";let r=Math.max(0,Math.floor((l-f)/1000));if(r<1)return"刚刚";let n=Math.floor(r/86400),i=Math.floor(r%86400/3600),y=Math.floor(r%3600/60),t=r%60;if(n>0)return`${n}天${i>0?`${i}小时`:""}前`;if(i>0)return`${i}小时${y>0?`${y}分钟`:""}前`;if(y>0)return`${y}分钟${t}秒前`;return`${t}秒前`}function JQ(...u){let l="",f=-1/0;for(let r of u){let n=String(r||"");if(n.length===0)continue;let i=Y0(r);if(i!==null&&i>=f)l=n,f=i;else if(l.length===0)l=n}return l}function iE(u){let l=Number(u);if(!Number.isFinite(l)||l<0)return"--";if(l<1000)return`${Math.round(l)}ms`;return`${(l/1000).toFixed(l<1e4?2:1)}s`}function MA(u,l=180){let f=String(u||"").replace(/\s+/gu," ").trim();return f.length>l?`${f.slice(0,l-1)}…`:f}async function Rl(u,l={}){return Tu(u,{strictJson:!0,retryInvalidJson:1,invalidJsonPrefix:"Code Queue 返回了无效 JSON",invalidJsonPreview:!0,responsePreviewLength:nE,...l})}function zi({status:u,children:l,title:f}){let r=String(u||"unknown").toLowerCase();return K("span",{className:`status-badge ${r}`,title:f},l||u||"unknown")}function R1({title:u,eyebrow:l,summary:f,actions:r,children:n,className:i,loading:y}){return K("section",{className:`panel ${i||""}`},K("div",{className:"panel-head"},K("div",null,l?K("p",{className:"panel-eyebrow"},l):null,K(nl,{title:u,loading:y}),f?K("div",{className:"panel-summary"},f):null),r?K("div",{className:"panel-actions"},r):null),K("div",{className:"panel-body"},n))}function QQ({title:u,data:l,onOpen:f,testId:r}){return K("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>f(u,l)},"查看原始JSON")}function Ti({title:u,text:l}){return K("div",{className:"empty-state"},K("strong",null,u),K("span",null,l))}function yE(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function tE(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function xl(u,l){return`${u}/microservices/code-queue/proxy${l}`}function _E(u){return`${u}/microservices/oa-event-flow/proxy/api/events/stream?tags=${encodeURIComponent("service:code-queue")}`}function gA(){return{headers:{"cache-control":"no-cache","x-unidesk-no-cache":"1"}}}function jf(u){return Array.isArray(u?.tasks)?u.tasks:[]}function zn(u){return u?.pagination&&typeof u.pagination==="object"&&!Array.isArray(u.pagination)?u.pagination:{}}function dJ(u){let l=Date.parse(String(u?.updatedAt||u?.createdAt||""));return Number.isFinite(l)?l:0}function eJ(u){return Y0(u?.queueEnteredAt)??Y0(u?.createdAt)??Y0(u?.updatedAt)??0}function $E(u,l){let f=eJ(u)-eJ(l);if(f!==0)return f;let r=(Y0(u?.createdAt)??0)-(Y0(l?.createdAt)??0);if(r!==0)return r;return String(u?.id||"").localeCompare(String(l?.id||""))}function cE(u,l=""){let f=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length>0&&!f.has(i))f.set(i,n)}return Array.from(f.values()).sort((r,n)=>{let i=_Q(r)-_Q(n);if(i!==0)return i;let y=String(r?.id||"")===l?0:1,t=String(n?.id||"")===l?0:1;if(y!==t)return y-t;return dJ(n)-dJ(r)})}function M1(u,l=""){let f=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length===0)continue;f.set(i,{...f.get(i)||{},...n})}return cE([Array.from(f.values())],l)}function Ct(u){return Array.isArray(u?.activeTaskIds)?u.activeTaskIds.map((l)=>String(l||"")).filter(Boolean):[String(u?.activeTaskId||"")].filter(Boolean)}var Zn="__all__",AE="(max-width: 760px)",jE="(min-width: 761px)";function kf(u){return!u||u===Zn}function FE(){return typeof window<"u"&&window.matchMedia(AE).matches}function UE(u){return kf(u)?"":`&queueId=${encodeURIComponent(u)}`}function RA(u){return String(u||"").trim().replace(/\s+/gu," ").slice(0,200)}function JE(u){let l=RA(u);return l.length===0?"":`&search=${encodeURIComponent(l)}`}function sA(u,l=""){return`${UE(u)}${JE(l)}`}function R3(u,l){return Number(u?.counts?.[l]||0)}function uQ(u,l=""){let f=new Map;for(let n of Array.isArray(u?.queues)?u.queues:[]){let i=String(n?.id||"").trim();if(i.length>0)f.set(i,{...n,name:String(n?.name||i).trim()||i})}for(let n of[String(u?.defaultQueueId||"default"),l].map((i)=>i.trim()).filter(Boolean))if(!f.has(n))f.set(n,{id:n,name:n,total:0,counts:{},activeTaskId:null,runnableTaskId:null,processing:!1});return Array.from(f.values()).sort((n,i)=>{let y=String(n?.id||"")===String(u?.defaultQueueId||"default")?0:1,t=String(i?.id||"")===String(u?.defaultQueueId||"default")?0:1;if(y!==t)return y-t;return String(n?.id||"").localeCompare(String(i?.id||""))})}function NQ(u){let l=String(u?.id||"default"),f=String(u?.name||"").trim();return f.length>0?f:l}function xA(u){let l=String(u?.id||"default"),f=NQ(u);return f===l?l:`${f} (${l})`}function Mt(u){let l=R3(u,"running")+R3(u,"judging"),f=R3(u,"queued")+R3(u,"retry_wait"),r=Number(u?.total||0),n=[xA(u),`${r} tasks`];if(l>0)n.push(`${l} running`);if(f>0)n.push(`${f} queued`);return n.join(" · ")}function h1(u,l){if(kf(l))return null;return u.find((f)=>String(f?.id||"")===l)||null}function lQ(u,l,f,r){if(kf(f)){let i=Ct(u);return String(u?.activeTaskId||i[0]||r.find((y)=>yQ(y))?.id||"")}let n=h1(l,f);return String(n?.activeTaskId||r.find((i)=>yQ(i))?.id||"")}function QE(u,l,f){if(!kf(l)){let r=h1(u,l);return String(r?.runnableTaskId||f.find((n)=>String(n?.status||"")==="queued"||String(n?.status||"")==="retry_wait")?.id||"")}return String(f.find((r)=>String(r?.status||"")==="queued"||String(r?.status||"")==="retry_wait")?.id||"")}async function NE(u,l=Zn,f=""){return Rl(xl(u,`/api/tasks/overview?limit=${jQ}&transcriptLimit=1&compact=1&selected=0${sA(l,f)}`),gA())}async function qE(u,l,f=0,r=Zn,n=""){return Rl(xl(u,`/api/tasks/overview?limit=${jQ}&transcriptLimit=3&compact=1&afterSeq=${encodeURIComponent(String(Math.max(0,f)))}&preferId=${encodeURIComponent(l)}${sA(r,n)}`),gA())}async function fQ(u,l,f,r=FQ,n=""){return Rl(xl(u,`/api/tasks/overview?limit=${encodeURIComponent(String(r))}&transcriptLimit=1&compact=1&selected=0&includeActive=0&stats=0&beforeId=${encodeURIComponent(f)}${sA(l,n)}`),gA())}async function WE(u,l){return Rl(xl(u,`/api/tasks/${encodeURIComponent(l)}/trace-summary`))}async function wE(u,l,f,r=null){let n=r===null||r===void 0||String(r).length===0?"":`&attempt=${encodeURIComponent(String(r))}`;return Rl(xl(u,`/api/tasks/${encodeURIComponent(l)}/prompt?part=${encodeURIComponent(f)}${n}`))}async function LE(u,l,f=0,r=500,n=null){let i=n===null||n===void 0||String(n).length===0?"":`&attempt=${encodeURIComponent(String(n))}`;return Rl(xl(u,`/api/tasks/${encodeURIComponent(l)}/trace-steps?afterSeq=${encodeURIComponent(String(f))}&limit=${encodeURIComponent(String(r))}${i}`))}async function KE(u,l,f){return Rl(xl(u,`/api/tasks/${encodeURIComponent(l)}/trace-step?seq=${encodeURIComponent(String(f))}`))}async function GE(u,l){return Rl(xl(u,`/api/tasks/${encodeURIComponent(l)}/read`),{method:"POST",body:{}})}async function zE(u){return Rl(xl(u,"/api/tasks/read-all"),{method:"POST",body:{}})}function TE(u){return Array.isArray(u?.output)?u.output:[]}function EE(u){return Array.isArray(u?.attempts)?u.attempts:[]}function YA(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function ZE(u){return u.split(/^\s*---+\s*$/gmu).map((l)=>l.trim()).filter(Boolean)}function rQ(u){let l=Number(u);return Number.isFinite(l)?Math.max(1,Math.min(50,Math.floor(l))):1}function Li(u){let l=[];for(let f of u.split(/[\s,,;;]+/u)){let r=f.trim();if(/^codex_\d+_[A-Za-z0-9_-]+$/u.test(r)&&!l.includes(r))l.push(r)}return l}function OE(u,l){let f=Li(l);if(f.length===0)return u;return[`引用 Code Queue 任务 ${f.join(" ")}。后端会在入队时只注入这些任务的 initial prompt 和 final response 全文;中间执行过程不注入,如需补充核查可运行:${f.map((r)=>`bun scripts/cli.ts codex task ${r}`).join(";")}`,"","本次任务:",u].join(` +`)}function HE(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 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=` +本次任务:`,r=l.indexOf(f);if(r===-1)return u;return l.slice(r+f.length).trimStart()}function Gi(u){return u.length>0?u.split(/\r\n|\r|\n/u).length:0}function qQ(u){let l=String(u?.displayPrompt||"");if(l.length>0)return l;let f=String(u?.prompt||"");return BE(HE(f).userPrompt)}function jr(u){return u?._traceSummary&&typeof u._traceSummary==="object"&&!Array.isArray(u._traceSummary)?u._traceSummary:null}function I3(u){return u?._promptDetails&&typeof u._promptDetails==="object"&&!Array.isArray(u._promptDetails)?u._promptDetails:{}}function aA(u){let l=jr(u)?.prompt;return l&&typeof l==="object"&&!Array.isArray(l)?l:{}}function WQ(u){let l=jr(u)?.execution;return l&&typeof l==="object"&&!Array.isArray(l)?l:{}}function nQ(u){let l=Number(u);return Number.isFinite(l)&&l>=0?Math.floor(l):0}function S0(u){let l=Number(u);return Number.isFinite(l)&&l>=0?Math.floor(l):null}function wQ(u){let l=Wl(u?.traceStats);if(l&&(u?.statsSource==="oa-event-flow"||l.source==="oa-event-flow"))return l;let f=jr(u),r=Wl(f?.traceStats);if(r&&(f?.statsSource==="oa-event-flow"||r.source==="oa-event-flow"))return r;return null}function VE(u,l){let f=Wl(l?.traceStats)||Wl(l?.execution?.traceStats),r=String(l?.statsSource||l?.execution?.statsSource||"");if(f&&(r==="oa-event-flow"||f.source==="oa-event-flow"))return f;return null}function DE(u,l){return S0(wQ(u)?.[l])}function LQ(u){let l=DE(u,"stepCount");if(l!==null)return l;let f=jr(u);if(f!==null)return XE(f);return null}function XE(u){let l=Wl(u?.traceStats);if(!l||u?.statsSource!=="oa-event-flow"&&l.source!=="oa-event-flow")return null;return S0(l.stepCount)}function x3(u){if(!u||u?._traceSummaryLoaded!==!0)return!1;let l=jr(u),f=String(u?._traceSummaryUpdatedAt||l?.updatedAt||""),r=String(u?.updatedAt||"");if(r.length>0){let n=Y0(f),i=Y0(r);if(n!==null&&i!==null){if(n+10?f:qQ(u)}function KQ(u){let l=jr(u);return String(l?.finalResponse||u?.finalResponse||"").trimEnd()}function GQ(u){let f=jr(u)?.lastJudge||u?.lastJudge;return f&&typeof f==="object"&&!Array.isArray(f)?f:null}function Wl(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function SE(u){let l=Wl(u?.raw),f=Wl(u?.failureDetails)||Wl(l?.minimaxFailure);if(f===null)return"";let r=f.repairAttempt===void 0?"":`${f.repairAttempt}/${f.maxRepairAttempts??"?"}`;return[["provider",f.provider||"minimax"],["stage",f.stage],["model",f.model],["timedOut",f.timedOut],["durationMs",f.durationMs],["timeoutMs",f.timeoutMs],["promptChars",f.promptChars],["promptLines",f.promptLines],["payloadBytes",f.payloadBytes],["responseStatus",f.responseStatus],["repairAttempt",r],["errorName",f.errorName],["error",f.errorMessage],["responseContentPreview",f.responseContentPreview],["responseTextPreview",f.responseTextPreview]].filter(([,i])=>i!==void 0&&i!==null&&String(i).length>0).map(([i,y])=>`${i}: ${String(y)}`).join(` +`)}function zQ({judge:u,testId:l="codex-judge-failure-details"}){let f=SE(u);if(f.length===0)return null;return K("details",{className:"codex-judge-failure-details","data-testid":l},K("summary",null,"MiniMax failure details"),K("pre",null,f))}function YE(u){let l=jr(u)?.attempts;if(Array.isArray(l)&&l.length>0)return l;let f=WQ(u),r=KQ(u),n=GQ(u);if(Object.keys(f).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:f,finalResponse:r,finalResponseChars:r.length,judge:n}]}function pE(u,l){return Wl(l?.execution)||WQ(u)}function mE(u,l,f,r){let n=jr(u),i=Number(n?.currentAttempt||u?.currentAttempt||0),y=Number(f),t=Number.isFinite(y)&&y>0&&y===i,_=JQ(u?.updatedAt,n?.updatedAt);if(t&&!l?.finishedAt&&_.length>0)return _;return String(l?.updatedAt||l?.finishedAt||r.effectiveEndAt||(t?_:"")||_||u?.finishedAt||u?.startedAt||"")}function PE(u,l){let f=String(l?.finalResponse||l?.finalResponsePreview||"");if(Object.prototype.hasOwnProperty.call(l||{},"finalResponse")||Object.prototype.hasOwnProperty.call(l||{},"finalResponsePreview"))return f.trimEnd();return f.length>0?f.trimEnd():KQ(u)}function TQ(u,l){if(Object.prototype.hasOwnProperty.call(l||{},"judge"))return Wl(l?.judge);return GQ(u)}function CE(u,l,f){if(!lZ(u))return!1;if(oA(l,f))return!1;if(l?.finishedAt)return!1;if(["succeeded","failed","canceled"].includes(String(l?.terminalStatus||"")))return!1;let r=jr(u),n=Number(r?.currentAttempt||u?.currentAttempt||0),i=Number(f);if(Number.isFinite(i)&&i>0&&Number.isFinite(n)&&n>0)return i===n;return!0}function EQ(u){return`feedback:${String(u||"latest")}`}function ME(u,l,f){let r=String(l?.feedbackPrompt||"").trimEnd(),n=String(l?.feedbackPromptPreview||r||"").trimEnd(),i=Number(l?.feedbackPromptChars||r.length||n.length||0),y=Number(l?.feedbackPromptLines||Gi(r||n));if(r.length>0||n.length>0||i>0)return{text:r,preview:n,chars:i,lines:y,source:l?.feedbackPromptSource||"judge-feedback",forAttempt:l?.feedbackPromptForAttempt||Number(f||0)+1,truncated:Boolean(l?.feedbackPromptTruncated)};let t=TQ(u,l),_=String(t?.continuePrompt||"").trimEnd();if(t?.decision==="retry"&&_.length>0)return{text:"",preview:_,chars:_.length,lines:Gi(_),source:"judge-continue-prompt",forAttempt:Number(f||0)+1,truncated:!1};return null}function RE(u){let l=aA(u);return Boolean(l.hasReferenceInjection||Number(l.referencePromptChars||0)>0||u?.referenceInjection||u?.referenceInjectionSummary)}function ZQ(u,l=null){if(l!==null&&l!==void 0){let r=(Wl(u?._traceStepsByAttempt)||{})[String(l)];return Array.isArray(r)?r:[]}return Array.isArray(u?._traceSteps)?u._traceSteps:[]}function hA(u){let f=[u?.seq,...Array.isArray(u?.rawSeqs)?u.rawSeqs:[]].map((r)=>Number(r)).filter((r)=>Number.isFinite(r));return f.length>0?Math.max(...f):0}function xE(u){return(Array.isArray(u)?u:[]).reduce((l,f)=>Math.max(l,hA(f)),0)}function hE(u,l){let f=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(l)?l:[]]){let n=String(r?.seq??`${r?.title||"step"}:${r?.at||""}`);f.set(n,{...f.get(n)||{},...r})}return Array.from(f.values()).sort((r,n)=>hA(r)-hA(n))}function b1(u){return(Array.isArray(u?.summaryLines)?u.summaryLines:[]).map((l)=>String(l||""))}function bE(u){let l=String(u?.kind||"").trim().toLowerCase(),f=String(u?.status||"").trim().toLowerCase();return l==="error"||f==="error"}function g3(u){let l=String(u?.status||"").trim();if(l.length>0)return l;let f=b1(u).join(` +`);return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(f)?.[1]||""}function iQ(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function vE(u){let l=b1(u);for(let r=l.length-1;r>=0;r-=1){let n=/file changes status=([A-Za-z0-9_-]+)/u.exec(l[r]||"")?.[1];if(n)return n}let f=g3(u);if(f==="item/fileChange/outputDelta")return"updated";if(f==="item/started")return"started";if(f==="item/completed")return"completed";return f.replace(/^item\//u,"")||String(u?.status||"changed")}function kE(u){if(String(u?.kind||"")!=="edited")return!1;let l=String(u?.title||""),f=String(u?.status||""),r=b1(u).join(` +`);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)}function IE(u){if(u.length<=1)return u[0];let l=u.find((i)=>g3(i)==="item/fileChange/outputDelta")||u.find((i)=>b1(i).some((y)=>!iQ(y)))||u.at(-1)||u[0],f=u.flatMap((i)=>Array.isArray(i?.rawSeqs)?i.rawSeqs:[i?.seq]).filter((i)=>i!==void 0),r=u.flatMap(b1).filter((i)=>i.trim().length>0&&!iQ(i)),n=u[u.length-1]||l;return{...l,at:l?.at||n?.at,title:String(l?.title||"Edited files"),status:vE(n),summaryLines:r.length>0?r:b1(l),rawSeqs:f}}function gE(u){let l=Array.isArray(u)?u:[],f=[],r=[],n=()=>{if(r.length>0)f.push(IE(r));r=[]};for(let i of l){if(kE(i)){if(g3(i)==="item/started"&&r.length>0)n();if(r.push(i),g3(i)==="item/completed")n();continue}n(),f.push(i)}return n(),f}function sE(u){return{...u}}function bA(u,l=null){if(l!==null&&l!==void 0){let f=Wl(u?._traceStepsLoadedByAttempt)||{};return Boolean(f[String(l)])}return Boolean(u?._traceStepsLoaded)}function vA(u){return u?._traceStepDetails&&typeof u._traceStepDetails==="object"&&!Array.isArray(u._traceStepDetails)?u._traceStepDetails:{}}function aE(u,l){let f=Number(u?.index);return Number.isFinite(f)?f:l+1}function oA(u,l){return Boolean(u?.synthetic)||Number(l)<=0}function s3(u){let l=Number(u);return Number.isFinite(l)?String(l):void 0}function oE(u){let l=u?.timing&&typeof u.timing==="object"?u.timing:{},f=String(u?.status||"");if(["queued"].includes(f))return`等待 ${br(l.queueWaitMs??l.totalElapsedMs)}`;if(["running","judging","retry_wait"].includes(f))return`耗时 ${br(l.durationMs??l.totalElapsedMs)}`;return`耗时 ${br(l.durationMs??l.totalElapsedMs)}`}function Rt(u){return String(u?.queueId||"default")}function OQ(u){return Wl(u?.queuedReason)}function HQ(u){let l=String(u?.queuedReasonLabel||"").trim();if(l.length>0)return l.toUpperCase();let f=OQ(u),r=String(f?.label||"").trim();return r.length>0?r.toUpperCase():""}function dE(u){let l=String(u?.status||"unknown");if(l!=="queued")return l;let f=HQ(u);return f.length>0?`QUEUED(${f})`:"QUEUED"}function eE(u){if(String(u?.status||"")!=="queued")return;let l=OQ(u),f=String(l?.message||"").trim(),r=HQ(u);if(f.length>0&&r.length>0)return`${r}: ${f}`;if(f.length>0)return f;return r.length>0?r:void 0}function uZ(u){return{system:"SYS",user:"YOU",assistant:"GPT",reasoning:"THINK",command:"CMD",diff:"DIFF",tool:"TOOL",error:"ERR"}[u]||u.toUpperCase()}function yQ(u){return["running","judging","retry_wait"].includes(String(u?.status||""))}function lZ(u){return String(u?.status||"")==="running"}function hr(u){return["succeeded","failed","canceled"].includes(String(u?.status||""))}function BQ(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 X0(u){if(!hr(u))return!1;if(u?.terminalUnread===!0)return!0;if(u?.terminalUnread===!1)return!1;return!u?.readAt}function Ml(u){let l=Number(u||0);return Number.isFinite(l)?l:0}function fZ(u){return Ml(u.queued)+Ml(u.retry_wait)}function rZ(u){return Ml(u.running)+Ml(u.judging)}function nZ(u,l){return Wl(u?.statistics)||Wl(l?.statistics)||{}}function iZ(u){return Array.isArray(u?.daily)?u.daily:[]}function yZ(u){return Wl(u?.totals)||{}}function dA(u,l){let f=Number(u?.[l]??0);return Number.isFinite(f)&&f>0?f:0}function pA(u,l){return u.reduce((f,r)=>Math.max(f,dA(r,l)),0)}var Ki=700,tQ=220,En=30,x1=24,xt=184,kA=xt-x1;function VQ(u,l){if(l<=1)return Ki/2;return En+u*(Ki-En*2)/(l-1)}function DQ(u,l){let f=l>0?l:1;return xt-Math.min(1,u/f)*kA}function mA(u,l,f){let r=u.length>0?u:[{[l]:0}],n=r.length>1?r:[r[0],r[0]];return n.map((i,y)=>`${VQ(y,n.length).toFixed(2)},${DQ(dA(i,l),f).toFixed(2)}`).join(" ")}function D0(u){let l=String(u||"");return/^\d{4}-\d{2}-\d{2}$/u.test(l)?l.slice(5):l||"--"}function h3(u){if(!u)return"";return`${String(u.seriesKey||"")}:${String(u.row?.date||u.index||"")}`}function tZ(u,l,f,r){let n=dA(u,r.key);return{...r,row:u,index:l,value:n,valueLabel:r.format(n),x:VQ(l,f),y:DQ(n,r.max),seriesKey:r.key}}function _Q(u){if(X0(u))return 0;return{running:1,judging:2,retry_wait:3,queued:4,succeeded:8,failed:8,canceled:8}[String(u?.status||"")]??9}function Pt(u){if(!u)return!1;if(u?._traceSummaryLoaded===!0)return!1;return u?.summaryOnly===!0||u?._metaLoaded!==!0}function _Z(u){return Boolean(u?._metaLoaded)||u?.summaryOnly===!1}function $Z(u,l,f){let r=String(u?.[f]||""),n=String(l?.[f]||"");return r.length>n.length?r:n}function IA(u,l,f){let r=Array.isArray(u?.[f])?u[f]:[],n=Array.isArray(l?.[f])?l[f]:[];if(n.length===0&&r.length>0)return r;return r.length>n.length?r:n}function $Q(u,l){let f=l?.summaryOnly===!0&&_Z(u),r={...u,...l};if(!f)return r;for(let n of["prompt","basePrompt","displayPrompt","finalResponse"])r[n]=$Z(u,l,n);for(let n of["promptHistory","attempts","output","events"])r[n]=IA(u,l,n);if(u?.referenceInjection?.items&&!l?.referenceInjection?.items)r.referenceInjection=u.referenceInjection;if(u?.referenceInjectionSummary&&!l?.referenceInjectionSummary)r.referenceInjectionSummary=u.referenceInjectionSummary;r.summaryOnly=u?.summaryOnly===!1?!1:l.summaryOnly,r._metaLoaded=u?._metaLoaded,r._detailLoaded=u?._detailLoaded,r._transcriptComplete=u?._transcriptComplete,r._transcriptPreview=Object.prototype.hasOwnProperty.call(l,"_transcriptPreview")?l._transcriptPreview:u?._transcriptPreview;for(let n of["_traceSummary","_traceSummaryLoaded","_traceSteps","_traceStepsLoaded","_traceStepsByAttempt","_traceStepsLoadedByAttempt","_traceStepsNextAfterSeqByAttempt","_traceStepDetails","_promptDetails"])if(!Object.prototype.hasOwnProperty.call(l,n)&&Object.prototype.hasOwnProperty.call(u||{},n))r[n]=u[n];return r}function cZ(u){let l=u?.selected,f=l?.task&&typeof l.task==="object"?l.task:null;if(f!==null){let n=Boolean(l?.preview);return{...f,transcript:Array.isArray(l?.transcript)?l.transcript:[],_detailLoaded:Array.isArray(l?.transcript)&&l.transcript.length>0,_transcriptComplete:Boolean(!n&&!l?.hasMore&&hr(f)),_transcriptPreview:n,_summaryLoaded:!0}}let r=jf(u)[0];return r?{...r,_summaryLoaded:!0}:null}function PA(u,l){let f=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(l)?l:[]]){let n=`${Number(r?.seq??0)}:${String(r?.kind||"message")}`,i=f.get(n);if(!i){f.set(n,r);continue}let y={...i,...r};for(let[t,_]of[["bodyPreview","bodyOmittedLines"],["commandPreview","commandOmittedLines"]]){let c=String(i?.[t]||""),A=String(r?.[t]||"");if(c.length>A.length)y[t]=i[t],y[_]=i[_]}f.set(n,y)}return Array.from(f.values()).sort((r,n)=>Number(r?.seq??0)-Number(n?.seq??0))}function b3(u){return(Array.isArray(u)?u:[]).reduce((l,f)=>Math.max(l,Number(f?.seq??0)),0)}function cQ(u,l=8){let f=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(f.length===0)return 0;let r=f[Math.max(0,f.length-l)]??0;return Math.max(0,r-0.001)}function AZ(u,l){let f=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([...f,...r,l].map((n)=>String(n||"").trim()).filter(Boolean)))}function jZ(u,l){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"},l?{id:l,label:l,defaultWorkdir:eA(u,l),supportsWindowsNativeCodex:l!==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,l){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,l?{id:l,label:l,description:"",defaultWorkdir:"",requiresProvider:l==="windows-native",requiresWindowsCwd:l==="windows-native"}:null].filter(Boolean))if(!i.has(y.id))i.set(y.id,y);return Array.from(i.values())}function v3(u,l,f){if(l!=="windows-native")return eA(u,f);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||"")===f):null;return String(n?.windowsNativeDefaultWorkdir||r?.defaultWorkdir||u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart")}function eA(u,l){let f=String(l||"").trim(),r=u?.defaultWorkdirByProvider&&typeof u.defaultWorkdirByProvider==="object"?u.defaultWorkdirByProvider:{};if(typeof r[f]==="string"&&String(r[f]).trim().length>0)return String(r[f]).trim();let n=Array.isArray(u?.executionProviders)?u.executionProviders.find((y)=>String(y?.id||"")===f):null;if(typeof n?.defaultWorkdir==="string"&&n.defaultWorkdir.trim().length>0)return n.defaultWorkdir.trim();let i=String(u?.mainProviderId||u?.defaultProviderId||"D601");return f===i?String(u?.defaultWorkdir||"/workspace"):String(u?.remoteDefaultWorkdir||"/home/ubuntu")}function UZ(u){return LQ(u)}function JZ({task:u,selected:l,onSelect:f,onCopy:r,onReference:n,onMarkRead:i,copied:y,markingRead:t}){let _=u?.lastJudge||{},c=String(u?.id||""),A=X0(u),j=JQ(u?.updatedAt,jr(u)?.updatedAt),F=`最近更新: ${UQ(j)}`,J=UZ(u),Q=J===null?"--":String(J),w=J===null?"STEP 统计中心同步中":"STEP 来自 OA Event Flow 统计中心";return K("article",{role:"button",tabIndex:0,className:`codex-task-card ${l?"selected":""} ${A?"unread-terminal":""}`,onClick:f,onKeyDown:(L)=>{if(L.key==="Enter"||L.key===" ")L.preventDefault(),f()},"data-unread-terminal":A?"true":"false","data-testid":`codex-task-${u?.id||"unknown"}`},A?K("span",{className:"codex-unread-badge",title:"待读","aria-label":"待读","data-testid":`codex-unread-task-${c||"unknown"}`}):null,K("div",{className:"codex-task-card-head"},K("div",{className:"codex-task-status-line"},K(zi,{status:u?.status,title:eE(u)},dE(u))),K("span",{className:"mono-text"},`${u?.currentAttempt||0}/${u?.maxAttempts||0}`)),K("div",{className:"codex-task-id-row"},K("code",{title:c},c||"unknown"),K("div",{className:"codex-task-id-actions"},K("button",{type:"button",className:"codex-copy-id-btn",onClick:(L)=>{L.stopPropagation(),n(c)},"data-testid":`codex-reference-task-${c||"unknown"}`},"引用"),K("button",{type:"button",className:"codex-copy-id-btn",onClick:(L)=>{L.stopPropagation(),r(c)},"data-testid":`codex-copy-task-id-${c||"unknown"}`},y?"已复制":"复制ID"),A?K("button",{type:"button",className:"codex-copy-id-btn codex-mark-read-btn",disabled:Boolean(t),onClick:(L)=>{L.stopPropagation(),i(c)},"data-testid":`codex-mark-task-read-${c||"unknown"}`},t?"标记中":"标为已读"):null)),K("strong",null,MA(qQ(u),120)||"空任务"),K("div",{className:"codex-task-meta"},K("span",null,`queue=${Rt(u)}`),K("span",null,`provider=${u?.providerId||"D601"}`),K("span",null,`mode=${u?.executionMode||"default"}`),K("span",null,u?.model||"--"),K("span",null,oE(u))),K("div",{className:"codex-task-meta codex-task-update-meta"},K("span",{className:"codex-task-recent-update codex-task-step-count",title:w,"data-testid":`codex-task-step-count-${c||"unknown"}`},`STEP ${Q}`),K("span",{className:"codex-task-recent-update",title:j?`更新时间: ${qu(j)}`:F,"data-testid":`codex-task-recent-update-${c||"unknown"}`},F),K("span",null,qu(j||u?.updatedAt))),BQ(u)?K("div",{className:"codex-judge-line","data-testid":`codex-task-prompt-editable-${c||"unknown"}`},"queued prompt 可编辑"):null,_?.decision?K("div",{className:"codex-judge-line"},`judge=${_.decision} ${Math.round(Number(_.confidence||0)*100)}%`):null)}function CA({title:u,tasks:l,selectedId:f,onSelect:r,onCopy:n,onReference:i,onMarkRead:y,copiedTaskId:t,markingReadTaskId:_,emptyText:c}){let A=Array.isArray(l)?l:[];return K("section",{className:"codex-task-section"},K("div",{className:"codex-task-section-head"},K("span",null,u),K("code",null,String(A.length))),A.length===0?K("p",{className:"codex-task-section-empty"},c):K("div",{className:"codex-task-section-list"},A.map((j)=>K(JZ,{key:j.id,task:j,selected:f===j.id,onSelect:()=>r(j.id),onCopy:n,onReference:i,onMarkRead:y,copied:t===j.id,markingRead:_===j.id}))))}function QZ(){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 NZ({stats:u,queueName:l,onRaw:f}){let r=iZ(u),n=yZ(u),i=r.at(-1)||{},y=pA(r,"executedTasks"),t=pA(r,"retryAttempts"),_=pA(r,"avgDurationMs"),c=r.length>0,A=Wl(u?.range)||{},[j,F]=ku(null),[J,Q]=ku(null),w=[];if(y>0)w.push(`tasks ${y}`);if(t>0)w.push(`retry ${t}`);if(_>0)w.push(`avg ${br(_)}`);let L=[{key:"executedTasks",className:"tasks",label:"执行任务",max:y,format:(E)=>`${Ml(E)} tasks`},{key:"retryAttempts",className:"retry",label:"重试次数",max:t,format:(E)=>`${Ml(E)} retries`},{key:"avgDurationMs",className:"duration",label:"平均耗时",max:_,format:(E)=>br(E)}],U=j||J,N=h3(U),q=String(U?.row?.date||""),W=U?{left:`${Math.max(8,Math.min(92,Number(U.x)/Ki*100))}%`,top:`${Math.max(14,Math.min(86,Number(U.y)/tQ*100))}%`}:void 0;Tn(()=>{F(null),Q(null)},[l,A.startDate,A.endDate,r.length]);let z=(E)=>{F(E)},Z=(E)=>{let D=h3(E);Q((h)=>h3(h)===D?null:E),F(E)},H=L.flatMap((E)=>r.map((D,h)=>{let V=tZ(D,h,r.length,E),S=h3(V),p=N===S,O=String(D?.date||`day-${h}`),m=`${D0(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(R1,{title:"统计曲线",eyebrow:`Daily task stats / ${l}`,className:"codex-stats-panel",summary:K("span",null,`${D0(A.startDate)} -> ${D0(A.endDate)} · ${u?.timezone||"Asia/Shanghai"}`),actions:Wl(u)?K(QQ,{title:"Code Queue Stats",data:u,onOpen:f,testId:"raw-codex-stats"}):null},K("div",{className:"codex-stats-hero","data-testid":"codex-stats-panel"},K(QZ),K("div",null,K("strong",null,`${Ml(n.executedTasks)} tasks / ${Ml(n.retryAttempts)} retries`),K("span",null,`平均完成耗时 ${br(n.avgDurationMs??void 0)} · 终态 ${Ml(n.completedTasks)} 个`))),c?K("div",{className:"codex-stats-chart","data-testid":"codex-stats-chart",onMouseLeave:()=>F(null)},K("svg",{viewBox:`0 0 ${Ki} ${tQ}`,preserveAspectRatio:"none",role:"img","aria-label":"Code Queue daily task statistics"},K("line",{className:"axis",x1:En,x2:Ki-En,y1:xt,y2:xt}),K("line",{className:"grid",x1:En,x2:Ki-En,y1:x1+kA/2,y2:x1+kA/2}),K("line",{className:"grid",x1:En,x2:Ki-En,y1:x1,y2:x1}),K("polyline",{className:"stat-line tasks",points:mA(r,"executedTasks",y)}),K("polyline",{className:"stat-line retry",points:mA(r,"retryAttempts",t)}),K("polyline",{className:"stat-line duration",points:mA(r,"avgDurationMs",_)}),U?K("g",{className:"stat-cursor-layer","data-testid":"codex-stats-active-point"},K("line",{className:"stat-cursor",x1:U.x,x2:U.x,y1:x1,y2:xt}),K("circle",{className:`stat-point-active ${U.className}`,cx:U.x,cy:U.y,r:8})):null,K("g",{className:"stat-point-layer"},H)),U?K("div",{className:"codex-stats-tooltip active",style:W,"data-testid":"codex-stats-tooltip"},K("b",null,D0(U.row?.date)),K("span",null,`${U.label} · ${U.valueLabel}`),K("code",null,`${Ml(U.row?.executedTasks)} exec / ${Ml(U.row?.retryAttempts)} retry / ${br(U.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,D0(r[0]?.date)),K("span",null,w.join(" · ")||"暂无峰值"),K("span",null,D0(r.at(-1)?.date))),K("div",{className:`codex-stats-focus ${U?"active":""}`,"data-testid":"codex-stats-focus"},U?K(ht.default.Fragment,null,K("div",null,K("strong",null,D0(U.row?.date)),K("span",null,`${U.label} · ${U.valueLabel}`)),K("div",{className:"codex-stats-focus-metrics"},K("code",null,`${Ml(U.row?.executedTasks)} exec`),K("code",null,`${Ml(U.row?.retryAttempts)} retry`),K("code",null,br(U.row?.avgDurationMs??void 0)))):K("span",null,"将鼠标悬停到曲线数据点查看明细,点击数据点可固定。"))):K(Ti,{title:"暂无统计",text:"任务开始执行后会生成按天汇总的曲线。"}),K("div",{className:"codex-stats-summary-grid"},K("article",null,K("span",null,"今日执行"),K("strong",null,String(Ml(i.executedTasks))),K("code",null,D0(i.date))),K("article",null,K("span",null,"今日重试"),K("strong",null,String(Ml(i.retryAttempts))),K("code",null,`累计 ${Ml(n.retryAttempts)}`)),K("article",null,K("span",null,"平均耗时"),K("strong",null,br(n.avgDurationMs??void 0)),K("code",null,`${Ml(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,D0(E?.date)),K("b",null,`${Ml(E?.executedTasks)} exec`),K("b",null,`${Ml(E?.retryAttempts)} retry`),K("code",null,br(E?.avgDurationMs??void 0))))))}function qZ({task:u,queueRows:l,busy:f,onMove:r}){let n=String(u?.id||""),i=Rt(u),[y,t]=ku(i);Tn(()=>{t(i)},[n,i]);let _=!n||f||["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||f,onChange:(c)=>t(String(c.target.value||i)),"data-testid":"codex-task-queue-move-select"},l.map((c)=>K("option",{key:String(c?.id||""),value:String(c?.id||"")},Mt(c))))),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 AQ(u,l=4){let f=(Array.isArray(u)?u:[]).map((n)=>String(n||"").trim()).filter(Boolean);if(f.length===0)return"--";let r=f.slice(0,l).join(" / ");return f.length>l?`${r} +${f.length-l}`:r}function WZ({task:u,loading:l,onLoadPromptPart:f,testId:r="codex-initial-prompt-full",textTestId:n="codex-initial-prompt-full-text",baseTextTestId:i="codex-initial-prompt-base"}){let y=aA(u),t=I3(u),_=k3(u).trimEnd(),c=String(t.full?.text||""),A=RE(u),j=Number(y.promptChars||u?.promptChars||c.length),F=Number(y.basePromptLines||Gi(_)),J=Number(y.promptLines||Gi(c));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||Gi(_)} lines / ${_.length} chars`)),K("pre",{className:"codex-prompt-full","data-testid":i},_||"空 prompt"),A?K("details",{className:"codex-reference-injection codex-progressive-full-prompt","data-testid":r,onToggle:(Q)=>{if(Q.currentTarget?.open&&!c)f?.("full")}},K("summary",null,K("span",null,"引用注入已折叠,点击按需拉取最终进入 Code agent 的完整 prompt"),K("code",null,c?`${J||Gi(c)} lines / ${c.length} chars`:`${Number.isFinite(j)&&j>0?j:"--"} chars`)),K("pre",{className:"codex-prompt-full codex-prompt-final-full","data-testid":n},c||(l?"正在按需拉取完整 prompt...":"展开后将只请求 full prompt,不拉取完整 transcript。"))):null)}function XQ({task:u,attempt:l,attemptIndex:f,loading:r,onLoadSteps:n,onLoadStep:i,testId:y="codex-execution-summary"}){let t=gE(ZQ(u,f)),_=sE(pE(u,l)),c=l?VE(u,l):wQ(u),A=vA(u),j=bA(u,f),F=S0(c?.errorCount),J=S0(c?.stepCount??c?.llmStepCount),Q=S0(c?.readCount),w=S0(c?.editCount),L=S0(c?.runCount),U=S0(c?.stepCount??c?.llmStepCount),N=J===null?"--":String(J),q=U===null?"--":String(U),W=Array.isArray(_.editedFiles)?_.editedFiles:[],z=Array.isArray(_.commands)?_.commands:[],H=oA(l,f)?` · ${String(l?.label||"recovered thread execution")}`:f?` #${f}`:"",E=mE(u,l,f,_),D=`最近更新: ${UQ(E)}`,h=CE(u,l,f);return K("details",{className:`codex-progressive-card codex-execution-summary ${h?"running":""}`,"data-testid":y,"data-attempt-index":s3(f),"data-running":h?"true":"false",onToggle:(V)=>{if(V.currentTarget?.open&&!j)n?.(f)}},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?`最近更新: ${qu(E)}`:D},`${br(_.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 ${w===null?"--":w}`),K("span",{title:"来自 OA Event Flow 统计中心"},`run ${L===null?"--":L}`),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,`修改文件:${AQ(W,6)}`),K("span",null,`执行命令:${AQ(z,4)}`)),t.length===0?K("div",{className:"codex-output-empty"},r?"正在按需拉取步骤 summary...":"展开后将只请求执行步骤 summary,不拉取单步骤全量。"):K("div",{className:"codex-trace-step-list"},t.map((V)=>{let S=String(V?.seq??""),p=A[S],O=Array.isArray(V?.summaryLines)?V.summaryLines.slice(0,4):[],m=O.find((X)=>String(X||"").trim().length>0);return K("details",{key:S||`${V?.title}-${V?.at}`,className:`codex-trace-step ${String(V?.kind||"message")} ${bE(V)?"error":""}`,"data-testid":`codex-trace-step-${S||"unknown"}`,onToggle:(X)=>{if(X.currentTarget?.open&&!p)i?.(V?.seq)}},K("summary",null,K("span",{className:"codex-output-channel"},wZ(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,qu(V?.at))),K("div",{className:"codex-trace-step-summary"},O.length>0?O.map((X,v)=>K("pre",{key:`${S}-${v}`},String(X||""))):K("span",null,"无 summary")),p?.line?K(C3,{items:[p.line],autoScroll:!1,loading:!1,hasDetail:!0,emptyText:"无步骤详情",testId:`codex-trace-step-detail-${S||"unknown"}`,className:"codex-transcript codex-step-detail-transcript",collapseTools:!1}):K("div",{className:"codex-output-empty"},r?"正在按需拉取这个步骤的全量数据...":"展开后将只请求这个单步骤的全量数据。"))})))}function wZ(u){let l=String(u||"");if(l==="ran")return"Ran";if(l==="explored")return"Explored";if(l==="edited")return"Edited";if(l==="error")return"Error";if(l==="system")return"System";return"Message"}function SQ({task:u,attempt:l,attemptIndex:f,testId:r="codex-final-response"}){let n=PE(u,l);if(n.length===0)return null;let i=Number(l?.finalResponseChars||n.length),y=f?` #${f}`:"";return K("section",{className:"codex-progressive-card codex-final-response","data-testid":r,"data-attempt-index":s3(f)},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(KJ,{markdown:n,className:"codex-transcript-body codex-markdown",testId:`${r}-markdown`}))}function YQ({task:u,attempt:l,attemptIndex:f,testId:r="codex-progressive-judge"}){let n=TQ(u,l);if(!n?.decision)return null;let i=f?` #${f}`:"";return K("section",{className:"codex-progressive-card codex-progressive-judge","data-testid":r,"data-attempt-index":s3(f)},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(zi,{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(zQ,{judge:n,testId:`${r}-failure-details`}),n.continuePrompt?K("pre",{"data-testid":`${r}-continue-prompt`},String(n.continuePrompt||"")):null))}function LZ({task:u,attempt:l,attemptIndex:f,loading:r,onLoadPromptPart:n,testId:i="codex-judge-feedback-prompt"}){let y=ME(u,l,f);if(y===null)return null;let t=EQ(f),c=I3(u)[t],A=String(c?.text||"").trimEnd(),j=String(y.preview||y.text||"").trimEnd(),F=A||String(y.text||"").trimEnd(),J=Number(c?.chars||y.chars||F.length||j.length),Q=Number(c?.lines||y.lines||Gi(F||j)),w=c?.forAttempt||y.forAttempt||Number(f||0)+1;return K("details",{className:"codex-progressive-card codex-judge-feedback-prompt","data-testid":i,"data-attempt-index":s3(f),onToggle:(L)=>{if(L.currentTarget?.open&&!A)n?.("feedback",f)}},K("summary",null,K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Prompt"),K("strong",null,`judge feedback prompt #${f} -> #${w}`),K("code",null,`${Q||"--"} lines / ${Number.isFinite(J)?J: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 KZ({task:u,attempt:l,position:f,loading:r,onLoadPromptPart:n,onLoadSteps:i,onLoadStep:y}){let t=aE(l,f),_=f===0,c=oA(l,t),A=c?String(l?.label||"Recovered thread execution"):`Attempt ${t}`;return K("section",{className:"codex-attempt-cycle","data-testid":`codex-attempt-cycle-${t}`},K("div",{className:"codex-attempt-cycle-head"},K("span",{className:"codex-output-channel"},A),K("strong",null,String(l?.mode||(t<=1?"initial":"retry"))),l?.terminalStatus?K(zi,{status:l.terminalStatus},l.terminalStatus):null,K("code",null,`${qu(l?.startedAt)} -> ${qu(l?.finishedAt)}`)),K(XQ,{task:u,attempt:l,attemptIndex:t,loading:r,onLoadSteps:i,onLoadStep:y,testId:_?"codex-execution-summary":`codex-execution-summary-attempt-${t}`}),c?null:K(SQ,{task:u,attempt:l,attemptIndex:t,testId:_?"codex-final-response":`codex-final-response-attempt-${t}`}),c?null:K(YQ,{task:u,attempt:l,attemptIndex:t,testId:_?"codex-progressive-judge":`codex-progressive-judge-attempt-${t}`}),c?null:K(LZ,{task:u,attempt:l,attemptIndex:t,loading:r,onLoadPromptPart:n,testId:_?"codex-judge-feedback-prompt":`codex-judge-feedback-prompt-attempt-${t}`}))}function GZ({task:u,loading:l,onLoadPromptPart:f,onLoadSteps:r,onLoadStep:n}){if(!u)return K(Ti,{title:"未选择任务",text:"从左侧队列选择任务,或提交新 Codex 任务。"});let i=YE(u);return K("div",{className:"codex-transcript codex-progressive-trace","data-testid":"codex-output"},l&&!jr(u)?K("div",{className:"codex-output-empty"},"正在加载 Trace Summary..."):null,K(WZ,{task:u,loading:l,onLoadPromptPart:f}),i.length>0?i.map((y,t)=>K(KZ,{key:`${y?.index||t+1}-${y?.startedAt||t}`,task:u,attempt:y,position:t,loading:l,onLoadPromptPart:f,onLoadSteps:r,onLoadStep:n})):[K(XQ,{key:"execution",task:u,loading:l,onLoadSteps:r,onLoadStep:n}),K(SQ,{key:"final",task:u}),K(YQ,{key:"judge",task:u})])}function zZ({task:u}){let l=TE(u);if(!u||l.length===0)return K(Ti,{title:"暂无原始消息",text:"原始 Codex app-server 消息会保留在任务 JSON 中。"});return K("details",{className:"codex-raw-output"},K("summary",null,`原始 messages (${l.length})`),K("div",null,l.map((f)=>K("article",{key:`${f.seq}-${f.channel}`,className:`codex-output-line ${f.channel||"system"}`},K("div",{className:"codex-output-meta"},K("span",{className:"codex-output-channel"},uZ(String(f.channel||"system"))),K("span",null,qu(f.at)),f.method?K("code",null,f.method):null),K("pre",null,String(f.text||""))))))}function TZ({task:u}){let l=EE(u).slice().reverse();if(l.length===0)return K(Ti,{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,l.map((f)=>K("tr",{key:`${f.index}-${f.startedAt}`},K("td",null,f.index),K("td",null,f.mode),K("td",null,K(zi,{status:f.terminalStatus||"unknown"},f.terminalStatus||"unknown")),K("td",null,f.transportClosedBeforeTerminal?K(zi,{status:"failed"},"closed-before-terminal"):K(zi,{status:"succeeded"},"normal")),K("td",null,`code=${f.appServerExitCode??"--"} signal=${f.appServerSignal??"--"}`),K("td",null,qu(f.finishedAt)))))))}function pQ({microservices:u,onRaw:l,apiBaseUrl:f="/api",initialTasksData:r=null,standalone:n=!1}){let i=u.find((B)=>B.id==="code-queue")||null,y=cZ(r),t=String(y?.id||""),_=new Map;if(y!==null&&t.length>0)_.set(t,{task:y,maxSeq:b3(Array.isArray(y.transcript)?y.transcript:[]),complete:Boolean(y._transcriptComplete),completeUpdatedAt:y._transcriptComplete?String(y.updatedAt||""):""});let c=typeof performance>"u"?0:performance.now(),A=Xl(t),j=Xl(0),F=Xl(0),J=Xl(0),Q=Xl(!1),w=Xl(!1),L=Xl(!1),U=Xl(null),N=Xl(new Map),q=Xl(new Map),W=Xl(new Map),z=Xl(new Map),Z=Xl(new Set),H=Xl(null),E=Xl(null),D=Xl(!1),h=Xl(!1),V=Xl(Boolean(r)),S=Xl(new Map),p=Xl(new Set),O=Xl(_),m=Xl(r),[X,v]=ku(null),[T,Y]=ku(r),[k,I]=ku(t),[b,o]=ku(y),[g,x]=ku(!1),[lu,_u]=ku(""),[$u,ju]=ku(null),[zu,Wu]=ku(!1),[P,e]=ku(!1),uu=r?.queue||{},Ku=String(uu?.mainProviderId||uu?.defaultProviderId||"D601").trim()||"D601",[s,Nu]=ku(""),[Eu,Hu]=ku(""),[vu,ul]=ku("default"),[mu,Fl]=ku(Zn),[Uf,Ef]=ku(!1),[lf,ol]=ku(""),[Zf,mf]=ku(Ku),[Au,su]=ku("default"),[Jf,pu]=ku("gpt-5.5"),[ff,rf]=ku(v3(uu,"default",Ku)||"/workspace"),[ur,nf]=ku(99),[Of,N0]=ku(1),[lr,k0]=ku(!1),[Ul,bi]=ku(!1),[fu,Bu]=ku(""),[Yu,au]=ku(""),[_l,Pl]=ku(""),[yl,Qf]=ku(!0),[Xr,Ky]=ku(()=>typeof window>"u"?!0:window.matchMedia(jE).matches),[Zl,k_]=ku(!1),[m6,zl]=ku(""),[$7,vl]=ku(""),{addNotification:fr}=Xf(),[vi,Gy]=ku(""),[ki,I_]=ku(""),[zy,g_]=ku(!1),[Pf,ar]=ku(r?{phase:"complete",taskId:t,queueMs:0,detailMs:0,totalMs:c,chunks:y?1:0,transcriptRows:Array.isArray(y?.transcript)?y.transcript.length:0,partial:Boolean(r?.selected?.hasMore||Pt(y)),completedAt:new Date}:null),[s_,Ty]=ku(r?new Date:null),[Ey,a_]=ku(!1),or=oi(jf(T)),o_=or.filter(X0),pl=T?.queue||X?.body?.queue||X?.queue||{},P6=nZ(T,pl),d_=zn(T),qr=uQ(pl,vu),an=String(vu||"default").trim()||"default",on=qr.filter((B)=>String(B?.id||"")!==an),Ii=h1(qr,mu),dn=Number((kf(mu)?pl?.total:Ii?.total)??d_.total??or.length),Zy=Ct(pl),c7=kf(mu)?Zy:[String(h1(qr,mu)?.activeTaskId||"")].filter(Boolean),gi=lQ(pl,qr,mu,or),A7=kf(mu)?YA(pl):YA(Ii||{}),Oy=YA(pl),C6=fZ(Oy),e_=Math.max(rZ(Oy),Zy.length),M6=Ml((kf(mu)?pl?.unreadTerminal:Ii?.unreadTerminal)??o_.length),I0=T?o_.length:M6,g0=kf(mu)?"All queues":xA(Ii||{id:mu,name:mu}),en=RA(lu),Cf=en.length>0,Hy=Cf?oi(jf($u)):[],R6=zn($u),dr=Cf?Hy:or,j7=dr.filter(X0),SL=dr.filter((B)=>!hr(B)).sort($E),YL=dr.filter((B)=>hr(B)&&!X0(B)),F7=Cf?R6:d_,si=Cf?Number(R6.total??Hy.length):dn,U7=F7.hasMore===!0&&String(F7.nextBeforeId||"").length>0,x6=Cf?P:Ey,pL=i?yE(i):{},mL=i?tE(i):{},h6=oJ(()=>ZE(s),[s]),q0=oJ(()=>{let B=rQ(Of);return h6.flatMap((C)=>Array.from({length:B},()=>OE(C,Eu)))},[h6,Of,Eu]),By=q0.length,J7=By>1&&!lr,PL=Ul||Zl||By===0||J7,Q7=AZ(pl,Jf),u$=jZ(pl,Zf),N7=FZ(pl,Au),CL=v3(pl,Au,Zf),b6=b?.id&&b?.activeTurnId&&String(b?.status)==="running",ML=b?.id&&!["succeeded","failed","canceled"].includes(String(b?.status||"")),RL=b?.id&&["succeeded","failed","canceled"].includes(String(b?.status||"")),ai=b?.id&&BQ(b);function Wr(B){let C=typeof B==="function"?B(m.current):B;return m.current=C,Y(C),C}function xL(B,C,d=!0){let nu=Array.from(new Set(B.map((Fu)=>String(Fu||"")).filter(Boolean)));for(let Fu of nu)if(S.current.set(Fu,C),d)p.current.add(Fu);return nu}function q7(B){for(let C of B.map((d)=>String(d||"")).filter(Boolean))S.current.delete(C),p.current.delete(C)}function l$(B){let C=String(B?.id||""),d=C?S.current.get(C):void 0;if(!d)return B;if(String(B?.status||"").length>0&&!hr(B))return S.current.delete(C),p.current.delete(C),B;return{...B,readAt:B?.readAt||d,terminalUnread:!1}}function v6(B){let C=String(B?.id||"");return C.length>0&&p.current.has(C)&&hr(B)}function oi(B,C=!0){let d=[];for(let nu of Array.isArray(B)?B:[]){let Fu=l$(nu);if(C&&v6(Fu))continue;d.push(Fu)}return d}function hL(B,C=!0){if(!B||!Array.isArray(B?.tasks))return B;let d=oi(jf(B),C),nu=zn(B);return{...B,tasks:d,pagination:B.pagination?{...nu,returned:d.length}:B.pagination}}function bL(B){let C=String(B||pl?.mainProviderId||"D601").trim()||"D601";mf(C),rf(v3(pl,Au,C))}function vL(B){let C=String(B||"default").trim()||"default",d=Zf;if(C==="windows-native"){if(!u$.find((Fu)=>Fu.id===Zf)?.supportsWindowsNativeCodex)d=String(u$.find((Fu)=>Fu.supportsWindowsNativeCodex)?.id||Zf||"D601"),mf(d)}su(C),rf(v3(pl,C,d))}function f$(B,C,d=null,nu=null){let Fu=new Set(xL(B,C));if(Fu.size===0&&nu===null&&d===null)return;Wr((Gu)=>{if(!Gu)return Gu;let wu=jf(Gu).flatMap((Ru)=>{let hu=String(Ru?.id||"");if(!Fu.has(hu)){let Al=l$(Ru);return v6(Al)?[]:[Al]}let Cu=nu&&String(nu?.id||"")===hu?nu:{},xu={...Ru,...Cu,readAt:C,terminalUnread:!1};return v6(xu)?[]:[xu]});return{...Gu,queue:d||Gu.queue,tasks:Fu.size>0?M1([wu],gi):wu}});for(let Gu of Fu){let wu=O.current.get(Gu);if(wu?.task){let Ru=nu&&String(nu?.id||"")===Gu?nu:{},hu={...wu.task,...Ru,readAt:C,terminalUnread:!1};if(O.current.set(Gu,{...wu,task:hu}),A.current===Gu)o(hu)}}}Tn(()=>{k0(!1)},[s,Of,Eu]),Tn(()=>{let B=RA(lu);F.current+=1;let C=F.current;if(!i||B.length===0){ju(null),Wu(!1),e(!1),L.current=!1;return}Wu(!0),ju(null);let d=window.setTimeout(()=>{(async()=>{try{let nu=await NE(f,mu,B);if(C!==F.current)return;ju(hL(nu))}catch(nu){if(C===F.current)ju(null),zl(Af(nu,"搜索 Codex tasks 失败"))}finally{if(C===F.current)Wu(!1)}})()},240);return()=>window.clearTimeout(d)},[i?.id,f,mu,lu]),Tn(()=>{au(b?k3(b):""),Pl(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},[k]);function W0(B,C,d){let nu=O.current.get(B)||{},Fu=nu.task||{},Gu=Array.isArray(Fu.transcript)?Fu.transcript:[],wu=$Q(Fu,C),Ru=Object.prototype.hasOwnProperty.call(C,"transcript")?PA(Gu,Array.isArray(C.transcript)?C.transcript:[]):Gu,hu={...Fu,...wu,transcript:Ru,output:Array.isArray(wu.output)?IA(Fu,wu,"output"):Array.isArray(Fu.output)?Fu.output:[],events:Array.isArray(wu.events)?IA(Fu,wu,"events"):Array.isArray(Fu.events)?Fu.events:[]},Cu=l$(hu),xu=String(Cu?.updatedAt||""),Al=Boolean(C._transcriptComplete)&&hr(Cu),yf=Boolean(nu.complete)&&hr(Cu)&&String(nu.completeUpdatedAt||"")===xu,eu=Al||yf,dl={...nu,task:Cu,maxSeq:b3(Ru),complete:eu,completeUpdatedAt:eu?xu:""};if(O.current.set(B,dl),d===J.current&&A.current===B)o(Cu);return dl}async function di(B,C=!1,d,nu){if(!i||!B)return;let Gu=O.current.get(B)?.task;if(!C&&x3(Gu))return;let wu=B,Ru=N.current.get(wu);if(Ru){if(C||!x3(Gu))Ru.refreshAfter=!0;return Ru.promise}let hu=J.current,Cu=performance.now();if(A.current===B)x(!0);let xu={promise:Promise.resolve(),refreshAfter:!1},Al=(async()=>{try{let yf=await WE(f,B);if(hu!==J.current||A.current!==B)return;let eu=yf?.summary||{},dl=String(eu.updatedAt||"");W0(B,{id:B,status:eu.status,updatedAt:dl,startedAt:eu.startedAt,finishedAt:eu.finishedAt,currentAttempt:eu.currentAttempt,maxAttempts:eu.maxAttempts,finalResponse:eu.finalResponse,lastJudge:eu.lastJudge,lastError:eu.lastError,attempts:Array.isArray(eu.attempts)?eu.attempts:[],stepCount:eu.stepCount,llmStepCount:eu.llmStepCount,traceStats:eu.traceStats,statsSource:eu.statsSource,timing:eu.timing,_traceSummary:eu,_traceSummaryLoaded:!0,_traceSummaryUpdatedAt:dl,_detailLoaded:!0},hu),ar({phase:"complete",taskId:B,queueMs:nu??0,detailMs:performance.now()-Cu,totalMs:d===void 0?performance.now()-Cu:performance.now()-d,chunks:1,transcriptRows:Number(eu?.execution?.traceLineCount||eu?.execution?.stepCount||0),partial:!1,completedAt:new Date})}finally{let yf=Boolean(xu.refreshAfter&&A.current===B&&!x3(O.current.get(B)?.task));if(N.current.delete(wu),hu===J.current&&A.current===B)x(!1);if(yf)window.setTimeout(()=>{di(B,!0).catch((eu)=>zl(Af(eu,"自动刷新 Trace Summary 失败")))},0)}})();xu.promise=Al,N.current.set(wu,xu),await Al}async function kL(B,C=null){let d=A.current;if(!i||!d||!B)return;let nu=O.current.get(d)?.task,Fu=I3(nu),Gu=B==="feedback"||B==="judge-feedback"?EQ(C):B;if(Fu[Gu]?.text)return;let wu=`${d}:${Gu}`,Ru=q.current.get(wu);if(Ru)return Ru;let hu=J.current;if(A.current===d)x(!0);let Cu=(async()=>{try{let xu=await wE(f,d,B,C);if(hu!==J.current||A.current!==d)return;let Al=O.current.get(d)?.task,yf=I3(Al);W0(d,{...B==="full"?{prompt:String(xu?.text||""),promptChars:Number(xu?.chars||0)}:{},_promptDetails:{...yf,[Gu]:xu}},hu)}finally{if(q.current.delete(wu),hu===J.current&&A.current===d)x(!1)}})();q.current.set(wu,Cu),await Cu}async function k6(B=null,C={}){let d=A.current;if(!i||!d)return;let nu=O.current.get(d)?.task,Fu=B===null||B===void 0||String(B).length===0?"":String(B),Gu=bA(nu,Fu||null),wu=Boolean(C.force),Ru=Boolean(C.incremental);if(Gu&&!wu)return;let hu=ZQ(nu,Fu||null),Cu=Ru&&hu.length>0?xE(hu):0,xu=`${d}:${Fu||"all"}:${Cu}`,Al=W.current.get(xu);if(Al)return Al;let yf=J.current;if(A.current===d)x(!0);let eu=(async()=>{try{let dl=await LE(f,d,Cu,500,Fu||null);if(yf!==J.current||A.current!==d)return;let s0=Array.isArray(dl?.steps)?dl.steps:[],a0=Cu>0?hE(hu,s0):s0;if(Fu){let o0=O.current.get(d)?.task,ei=Wl(o0?._traceStepsByAttempt)||{},tf=Wl(o0?._traceStepsLoadedByAttempt)||{},w0=Wl(o0?._traceStepsNextAfterSeqByAttempt)||{};W0(d,{_traceStepsByAttempt:{...ei,[Fu]:a0},_traceStepsLoadedByAttempt:{...tf,[Fu]:!0},_traceStepsNextAfterSeqByAttempt:{...w0,[Fu]:dl?.nextAfterSeq}},yf)}else W0(d,{_traceSteps:a0,_traceStepsLoaded:!0,_traceStepsHasMore:Boolean(dl?.hasMore),_traceStepsNextAfterSeq:dl?.nextAfterSeq},yf)}finally{if(W.current.delete(xu),yf===J.current&&A.current===d)x(!1)}})();W.current.set(xu,eu),await eu}async function IL(B){let C=A.current,d=String(B??"");if(!i||!C||d.length===0)return;let nu=O.current.get(C)?.task;if(vA(nu)[d]?.line)return;let Gu=`${C}:${d}`,wu=z.current.get(Gu);if(wu)return wu;let Ru=J.current;if(A.current===C)x(!0);let hu=(async()=>{try{let Cu=await KE(f,C,B);if(Ru!==J.current||A.current!==C)return;let xu=O.current.get(C)?.task,Al=vA(xu);W0(C,{_traceStepDetails:{...Al,[d]:Cu}},Ru)}finally{if(z.current.delete(Gu),Ru===J.current&&A.current===C)x(!1)}})();z.current.set(Gu,hu),await hu}function gL(B){if(A.current!==B)return;let C=O.current.get(B)?.task;if(!C)return;if(bA(C,null))k6(null,{force:!0,incremental:!0}).catch((nu)=>zl(Af(nu,"增量刷新 Trace Steps 失败")));let d=Wl(C?._traceStepsLoadedByAttempt)||{};for(let nu of Object.keys(d).filter((Fu)=>d[Fu]))k6(nu,{force:!0,incremental:!0}).catch((Fu)=>zl(Af(Fu,"增量刷新 Attempt Trace Steps 失败")))}async function jm(B,C,d){if(!i||!B)return;let nu=performance.now(),Fu=J.current,Gu=O.current.get(B);if(Gu?.task){if(o(Gu.task),x(Pt(Gu.task)||!Gu.complete),!Pt(Gu.task)&&Gu.complete&&hr(Gu.task)&&String(Gu.completeUpdatedAt||"")===String(Gu.task?.updatedAt||"")){ar({phase:"complete",taskId:B,queueMs:d??0,detailMs:0,totalMs:C===void 0?0:performance.now()-C,chunks:0,transcriptRows:Array.isArray(Gu.task.transcript)?Gu.task.transcript.length:0,completedAt:new Date});return}}else x(!0);let wu=U.current;if(wu?.taskId===B&&wu.token===Fu)return wu.promise;let Ru=(async()=>{try{let hu=await Rl(xl(f,`/api/tasks/${encodeURIComponent(B)}?meta=1`));if(Fu!==J.current||A.current!==B)return;let Cu=O.current.get(B),xu=Array.isArray(Cu?.task?.transcript)?Cu.task.transcript:[],Al=hu?.task||{},yf=Boolean(Cu?.complete)&&String(Cu?.completeUpdatedAt||"")===String(Al?.updatedAt||"");W0(B,{...Al,summaryOnly:!1,_metaLoaded:!0,transcript:xu,_detailLoaded:xu.length>0,_transcriptComplete:yf},Fu);let eu=Pt(Cu?.task)||Boolean(Cu?.task?._transcriptPreview),dl=eu?0:xu.length>0?cQ(xu):0,s0=!eu&&Cu?.complete&&hr(Al)&&String(Cu?.completeUpdatedAt||"")===String(Al?.updatedAt||"")?b3(xu):dl,a0=!0,o0=0,ei=xu.length;while(a0){let tf=await Rl(xl(f,`/api/tasks/${encodeURIComponent(B)}/transcript?afterSeq=${encodeURIComponent(String(s0))}&limit=${rE}&fullText=1`));if(Fu!==J.current||A.current!==B)return;let w0=O.current.get(B),r$=Array.isArray(w0?.task?.transcript)?w0.task.transcript:[],kl=PA(r$,Array.isArray(tf?.transcript)?tf.transcript:[]);o0+=1,ei=kl.length;let n$=Boolean(!tf?.hasMore);if(W0(B,{status:tf?.status||Al.status,updatedAt:tf?.updatedAt||Al.updatedAt,transcript:kl,_detailLoaded:n$||kl.length>0,_transcriptComplete:n$,_transcriptPreview:eu&&!n$},Fu),a0=Boolean(tf?.hasMore),s0=Number(tf?.nextAfterSeq??b3(kl)),!a0)break;await new Promise((u1)=>window.setTimeout(u1,0))}ar({phase:"complete",taskId:B,queueMs:d??0,detailMs:performance.now()-nu,totalMs:C===void 0?performance.now()-nu:performance.now()-C,chunks:o0,transcriptRows:ei,completedAt:new Date})}finally{if(U.current?.taskId===B&&U.current?.token===Fu)U.current=null;if(Fu===J.current&&A.current===B)x(!1)}})();U.current={taskId:B,token:Fu,promise:Ru},await Ru}async function Mf(B=A.current,C=!0,d=mu){if(!i)return;if(!C&&h.current)return;let nu=performance.now();if(C)h.current=!0;if(C)ar({phase:"loading",taskId:String(B||A.current||""),startedAt:new Date});let Fu=j.current+1;j.current=Fu;let Gu=String(B||A.current||""),wu=Gu?O.current.get(Gu):null,Ru=Array.isArray(wu?.task?.transcript)?wu.task.transcript:[],hu=cQ(Ru),Cu=null;if(Cu=await qE(f,Gu,hu,d),Fu!==j.current){if(C)h.current=!1;return}let xu=performance.now()-nu;v(X||{});let Al=Cu?.queue||{},yf=String(Al?.activeTaskId||Ct(Al)[0]||""),eu=Cu;Wr((nr)=>{let Vy=jf(Cu),ui=jf(nr),Dy=ui.length>0?M1([ui,Vy],yf):M1([Vy],yf),i$=oi(Dy),KK=zn(Cu),y$=zn(nr),GK=ui.length>Vy.length&&(y$.hasMore===!1||String(y$.nextBeforeId||"").length>0),zK={...KK,...GK?{hasMore:y$.hasMore,nextBeforeId:y$.nextBeforeId}:{},returned:i$.length};return eu={...Cu,tasks:i$,pagination:zK},eu});let dl=jf(eu),s0=uQ(Al,vu),a0=lQ(Al,s0,d,dl),o0=QE(s0,d,dl),ei=Gu||A.current,tf=eu?.selected||null,w0=tf?.task||null,r$=Array.isArray(tf?.transcript)?tf.transcript:null,kl=ei||a0||o0||dl[0]?.id||"";if(A.current!==kl)J.current+=1;A.current=kl,I(kl);let u1=dl.find((nr)=>nr.id===kl);if(u1){let nr=O.current.get(kl);if(nr?.task)O.current.set(kl,{...nr,task:{...u1,...nr.task,status:u1.status,updatedAt:u1.updatedAt}})}if(w0?.id===kl&&r$!==null){let nr=O.current.get(kl),Vy=Array.isArray(nr?.task?.transcript)?nr.task.transcript:[],ui=PA(Vy,r$),Dy=Boolean(tf?.preview);if(W0(kl,{...w0,_summaryLoaded:!0,transcript:ui,_detailLoaded:!tf?.hasMore||ui.length>0,_transcriptComplete:!Dy&&!tf?.hasMore&&hr(w0),_transcriptPreview:Dy},J.current),x(!1),C)ar({phase:"complete",taskId:kl,queueMs:xu,detailMs:Math.max(0,performance.now()-nu-xu),totalMs:performance.now()-nu,chunks:1,transcriptRows:ui.length,partial:Boolean(Dy||tf?.hasMore||Pt(w0)),completedAt:new Date});if(Ty(new Date),C)h.current=!1;di(kl,!1,C?nu:void 0,C?xu:void 0).catch((i$)=>zl(Af(i$,"加载 Codex Trace Summary 失败")));return}if(C)ar({phase:"session",taskId:kl,queueMs:xu,totalMs:xu,startedAt:new Date(Date.now()-xu)});if(kl)di(kl,!0,C?nu:void 0,C?xu:void 0).catch((nr)=>zl(Af(nr,"加载 Codex Trace Summary 失败")));else if(J.current+=1,o(null),x(!1),C)ar({phase:"complete",taskId:"",queueMs:xu,detailMs:0,totalMs:performance.now()-nu,chunks:0,transcriptRows:0,completedAt:new Date});if(Ty(new Date),C)h.current=!1}async function W7(){if(Cf){if(!i||P||L.current)return;let C=String(R6.nextBeforeId||"");if(!C)return;L.current=!0,e(!0),zl("");try{let d=await fQ(f,mu,C,FQ,en),nu=jf(d),Fu=d?.queue||pl||{},Gu=String(Fu?.activeTaskId||Ct(Fu)[0]||gi||"");ju((wu)=>{let Ru=oi(M1([jf(wu),nu],Gu)),hu=zn(d);return{...wu||{},queue:Fu,tasks:Ru,pagination:{...hu,returned:Ru.length}}})}catch(d){zl(Af(d,"加载更多搜索结果失败"))}finally{L.current=!1,e(!1)}return}if(!i||Ey||w.current)return;let B=String(zn(T).nextBeforeId||"");if(!B)return;w.current=!0,a_(!0),zl("");try{let C=await fQ(f,mu,B),d=jf(C),nu=C?.queue||pl||{},Fu=String(nu?.activeTaskId||Ct(nu)[0]||gi||"");Wr((Gu)=>{let wu=oi(M1([jf(Gu),d],Fu)),Ru=zn(C);return{...Gu||{},queue:nu,statistics:C?.statistics||Gu?.statistics,tasks:wu,pagination:{...Ru,returned:wu.length}}})}catch(C){zl(Af(C,"加载更早 Codex tasks 失败"))}finally{w.current=!1,a_(!1)}}function sL(B){let C=B.currentTarget;if(!C||x6||!U7)return;if(C.scrollHeight-C.scrollTop-C.clientHeight<120)W7()}async function rr(B,C){k_(!0),zl("");try{await B()}catch(d){zl(Af(d,C))}finally{k_(!1)}}async function I6(B){if(!B)return;try{let C=!1;try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(B),C=!0}catch{C=!1}if(!C){let nu=document.createElement("textarea");nu.value=B,nu.style.position="fixed",nu.style.opacity="0",document.body.appendChild(nu),nu.select(),C=document.execCommand("copy"),document.body.removeChild(nu)}if(!C)throw Error("browser clipboard rejected the copy request");Gy(B);let d=`已复制任务 ID:${B}`;vl(d),fr("success",d),window.setTimeout(()=>Gy((nu)=>nu===B?"":nu),1600)}catch(C){zl(`复制任务 ID 失败:${Af(C)}`)}}function g6(B){if(!B)return;Hu(B);let C=`已引用任务 ID:${B};提交时后端会读取并注入该任务上下文`;vl(C),fr("success",C)}async function s6(B){if(!i||!B)return;let C=new Date().toISOString();j.current+=1,f$([B],C,null,{id:B,readAt:C,terminalUnread:!1}),I_(B);let d=!1;if(await rr(async()=>{let nu=await GE(f,B),Fu=nu?.task||{id:B,readAt:new Date().toISOString(),terminalUnread:!1},Gu=String(Fu?.readAt||new Date().toISOString());f$([B],Gu,nu?.queue||null,Fu),d=!0;let wu=`已将任务 ${B} 标为已读`;vl(wu),fr("success",wu)},"标记 Codex task 已读失败"),!d)q7([B]),Mf(A.current,!1).catch((nu)=>zl(Af(nu,"刷新 Codex tasks 失败")));I_((nu)=>nu===B?"":nu)}async function aL(){if(!i||zy)return;g_(!0);let B=new Date().toISOString(),C=Array.from(new Set([...jf(m.current).filter(X0).map((nu)=>String(nu?.id||"")).filter(Boolean),...Array.from(O.current.entries()).filter(([,nu])=>X0(nu?.task)).map(([nu])=>nu)]));if(j.current+=1,C.length>0)f$(C,B);let d=!1;if(await rr(async()=>{let nu=await zE(f),Fu=String(nu?.readAt||new Date().toISOString()),Gu=jf(m.current).filter(X0).map((xu)=>String(xu?.id||"")).filter(Boolean),wu=Array.from(O.current.entries()).filter(([,xu])=>X0(xu?.task)).map(([xu])=>xu),Ru=Array.from(new Set([...C,...Gu,...wu]));f$(Ru,Fu,nu?.queue||null);let hu=Number(nu?.count||Ru.length);d=!0;let Cu=`已将 ${hu} 个已结束未读任务标为已读`;vl(Cu),fr("success",Cu)},"全部标为已读失败"),!d&&C.length>0)q7(C),Mf(A.current,!1).catch((nu)=>zl(Af(nu,"刷新 Codex tasks 失败")));g_(!1)}function oL(B){let C=B||Zn;if(Fl(C),!kf(C))ul(C);if(Wr(null),!(kf(C)?A.current:""))A.current="",J.current+=1,I(""),o(null),x(!0)}async function dL(){let B=typeof window>"u"?"":window.prompt("输入新的 Codex queue ID(字母/数字/._-,最长 64)","new-lane"),C=String(B||"").trim();if(!C)return;await rr(async()=>{let d=await Rl(xl(f,"/api/queues"),{method:"POST",body:{queueId:C}}),nu=String(d?.queue?.id||C);ul(nu),Fl(nu),Wr(null),A.current="",J.current+=1,I(""),o(null);let Fu=`已创建并切换到 queue:${nu}`;vl(Fu),fr("success",Fu),await Mf("",!0,nu)},"创建 Codex queue 失败")}async function eL(){let B=String(vu||"default").trim()||"default",C=h1(qr,B)||{id:B,name:B},d=typeof window>"u"?null:window.prompt(`输入 queue 显示名称(ID 不变:${B};留空恢复为 ID)`,NQ(C));if(d===null)return;await rr(async()=>{let nu=await Rl(xl(f,`/api/queues/${encodeURIComponent(B)}`),{method:"PATCH",body:{name:String(d)}}),Fu=nu?.queue||{id:B,name:String(d||B)};if(nu?.summary)Wr((wu)=>wu?{...wu,queue:nu.summary}:wu);let Gu=`已更新 queue 名称:${xA(Fu)}`;vl(Gu),fr("success",Gu),await Mf(A.current,!0,mu)},"修改 Codex queue 名称失败")}function uK(){if(on.length===0){vl("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let B=on.some((C)=>String(C?.id||"")===lf)?lf:"";ol(B),Ef(!0)}async function lK(){let B=an;if(on.length===0){vl("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let d=String(lf||""||"").trim();if(!d){vl("请先选择要合并的源 queue。");return}if(d===B){zl("源 queue 和目标 queue 不能相同。");return}await rr(async()=>{let nu=await Rl(xl(f,`/api/queues/${encodeURIComponent(B)}/merge`),{method:"POST",body:{sourceQueueId:d}});if(nu?.summary)Wr((wu)=>wu?{...wu,queue:nu.summary}:wu);ul(B),Fl(B),Wr(null);let Fu=Number(nu?.mergedTaskCount||0),Gu=`已将 queue=${d} 合并到 ${B},移动 ${Fu} 个任务;源 queue 已自动删除。`;vl(Gu),fr("success",Gu),Ef(!1),ol(""),await Mf(A.current,!0,B)},"合并 Codex queue 失败")}async function fK(B){if(B.preventDefault(),Q.current){vl("任务正在提交中,请等待当前请求完成,已阻止重复提交。");return}if(q0.length>1&&!lr){zl(`检测到将创建 ${q0.length} 个任务;请先勾选“确认批量入队”,避免误传多个任务。`);return}Q.current=!0,bi(!0),vl("正在提交 Code Queue 任务,请等待后端确认,输入已临时锁定。"),await rr(async()=>{if(q0.length===0)throw Error("prompt 不能为空");let C=Li(Eu),d=vu.trim()||"default",nu=[...q0],Fu=(xu)=>({prompt:xu,queueId:d,providerId:Zf,executionMode:Au,model:Jf,cwd:ff,maxAttempts:Number(ur),...C.length>0?{referenceTaskIds:C}:{}}),Gu=nu.length===1?Fu(nu[0]):{tasks:nu.map(Fu)},wu=await Rl(xl(f,nu.length===1?"/api/tasks":"/api/tasks/batch"),{method:"POST",body:Gu}),Ru=wu?.tasks?.[0]?.id||"",hu=Array.isArray(wu?.tasks)?wu.tasks.map((xu)=>String(xu?.id||"")).filter(Boolean):[],Cu=`已创建 ${hu.length||nu.length} 个任务${hu.length>0?`:${hu.join(" / ")}`:""}`;if(vl(Cu),fr("success",Cu),Nu(""),Hu(""),k0(!1),A.current=Ru,mu!==d)Wr(null);ul(d),await Mf(Ru,!0,d)},"Codex 任务入队失败"),Q.current=!1,bi(!1)}async function rK(B){if(B.preventDefault(),!b?.id)return;await rr(async()=>{await Rl(xl(f,`/api/tasks/${encodeURIComponent(b.id)}/steer`),{method:"POST",body:{prompt:fu}}),Bu(""),await Mf(b.id)},"追加 prompt 失败")}async function nK(B){B.preventDefault();let C=String(b?.id||"");if(!C||!ai)return;await rr(async()=>{let d=Li(_l),nu=await Rl(xl(f,`/api/tasks/${encodeURIComponent(C)}/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(C,{...O.current.get(C)||{},task:Fu,complete:!1,completeUpdatedAt:""}),A.current=C,o(Fu),I(C),au(k3(Fu)),Pl(Array.isArray(Fu?.referenceTaskIds)?Fu.referenceTaskIds.join(" "):""),Wr((wu)=>{if(!wu)return wu;let Ru=jf(wu).map((hu)=>String(hu?.id||"")===C?{...hu,...Fu}:hu);return{...wu,queue:nu?.queue||wu.queue,tasks:M1([Ru],gi)}});let Gu=nu?.changed===!1?`任务 ${C} 的 prompt 未变化`:`已更新 queued 任务 ${C} 的用户 prompt`;vl(Gu),fr("success",Gu),await Mf(C,!0,mu)},"编辑 queued 任务 prompt 失败")}async function iK(){if(!b?.id)return;await rr(async()=>{await Rl(xl(f,`/api/tasks/${encodeURIComponent(b.id)}/interrupt`),{method:"POST",body:{}}),await Mf(b.id)},"打断 Codex session 失败")}async function yK(){if(!b?.id)return;await rr(async()=>{await Rl(xl(f,`/api/tasks/${encodeURIComponent(b.id)}/retry`),{method:"POST",body:{}}),await Mf(b.id)},"重新入队失败")}async function tK(B){let C=String(b?.id||""),d=String(B||"").trim();if(!C||!d)return;let nu=Rt(b);if(d===nu){vl(`任务 ${C} 已在 queue=${d}`);return}await rr(async()=>{let Gu=(await Rl(xl(f,`/api/tasks/${encodeURIComponent(C)}/move`),{method:"POST",body:{queueId:d}}))?.task||{...b,queueId:d};if(O.current.set(C,{...O.current.get(C)||{},task:Gu}),A.current=C,o(Gu),I(C),ul(d),!kf(mu))Wr(null),Fl(d);let wu=`已将任务 ${C} 从 ${nu} 移动到 ${d}`;vl(wu),fr("success",wu),await Mf(C,!0,kf(mu)?Zn:d)},"移动任务 queue 失败")}async function _K(){let B=A.current;if(!B)return;let C=performance.now();await rr(async()=>{ar({phase:"session",taskId:B,queueMs:0,totalMs:0,partial:!0,startedAt:new Date}),await di(B,!0,C,0)},"刷新 Trace Summary 失败")}function $K(B){A.current=B,J.current+=1,I(B);let C=O.current.get(B);if(C?.task)o(C.task),x(!1);else{x(!0);let d=or.find((nu)=>nu.id===B);if(d)o(d);else o(null)}Mf(B).catch((d)=>zl(Af(d,"切换 Codex session 失败")))}function a6(B){if($K(B),FE())Ky(!1)}function w7(B,C,d){if(!B||!Array.isArray(B?.tasks)||C.length===0||Object.keys(d).length===0)return B;let nu=!1,Fu=jf(B).map((Gu)=>{if(String(Gu?.id||"")!==C)return Gu;return nu=!0,l$($Q(Gu,d))});return nu?{...B,tasks:Fu}:B}function cK(B,C){Wr((d)=>w7(d,B,C)),ju((d)=>w7(d,B,C))}function AK(B,C,d){let nu=String(B?.type||"");if(nu==="queue-updated")return!0;if(nu==="trace-stats-updated"||nu==="trace-step-created")return!1;if(C.length===0)return!0;if(!d)return!0;if(B?.queueId&&String(B.queueId)!==Rt(d))return!0;if(B?.status&&String(B.status)!==String(d?.status||""))return!0;return String(B?.reason||"")!=="output"}function L7(){if(!i||!SA())return;if(H.current!==null)window.clearTimeout(H.current);H.current=window.setTimeout(()=>{H.current=null,Mf(A.current,!1).catch((B)=>zl(Af(B,"Code Queue 事件刷新失败")))},120)}function jK(B,C){if(!i||!SA()||A.current!==B)return;if(D.current=D.current||C,E.current!==null)return;E.current=window.setTimeout(()=>{E.current=null;let d=D.current;if(D.current=!1,di(B,!0).catch((nu)=>zl(Af(nu,"事件刷新 Trace Summary 失败"))),d)gL(B)},250)}function FK(B){let C=Wl(B?.payload)||B,d=Wl(C?.stats),nu=String(B?.type||C?.type||""),Fu=String(C?.subjectKind||d?.subjectKind||""),Gu=String(C?.scopeId||d?.scopeId||""),wu=String(C?.taskId||(Fu==="task"?C?.subjectId:"")||d?.taskId||B?.taskId||""),Ru=C?.attemptIndex??d?.attemptIndex,hu=Ru===null||Ru===void 0||Ru===""?null:S0(Ru),Cu=d||Wl(C?.traceStats),xu=Cu?.stepCount??Cu?.llmStepCount,Al=Cu?.outputMaxSeq;return{...C,type:nu,eventId:B?.eventId||C?.eventId,sequence:B?.sequence??C?.sequence,taskId:wu,subjectKind:Fu,scopeId:Gu,attemptIndex:hu,stepCount:xu,outputMaxSeq:Al,updatedAt:Cu?.updatedAt||C?.updatedAt||B?.createdAt,traceStats:Cu,statsSource:Cu?"oa-event-flow":C?.statsSource}}function UK(B){let C=FK(B),d=String(C?.taskId||""),nu=String(C?.scopeId||C?.traceStats?.scopeId||""),Fu=String(C?.subjectKind||C?.traceStats?.subjectKind||"")==="task-attempt"||Number(C?.attemptIndex)>0||/:attempt:\d+$/u.test(nu),Gu=nQ(C?.stepCount),wu={},Ru=d.length>0?jf(m.current).find((hu)=>String(hu?.id||"")===d):null;if(d.length>0){if(C?.status)wu.status=String(C.status);if(C?.updatedAt)wu.updatedAt=String(C.updatedAt);if(C?.queueId)wu.queueId=String(C.queueId);if(!Fu&&Number.isFinite(Number(C?.stepCount)))wu.stepCount=Gu,wu.llmStepCount=Gu;if(!Fu&&Number.isFinite(Number(C?.outputMaxSeq)))wu.outputMaxSeq=nQ(C.outputMaxSeq);if(!Fu&&Wl(C?.traceStats))wu.traceStats=C.traceStats,wu.statsSource="oa-event-flow";if(Object.keys(wu).length>0&&(O.current.has(d)||A.current===d))W0(d,wu,J.current);if(Object.keys(wu).length>0)cK(d,wu);if(A.current===d&&(C?.type==="trace-step-created"||C?.type==="task-updated"||C?.type==="trace-stats-updated")){let hu=LQ(Ru),Cu=C?.type==="trace-step-created"||C?.type==="trace-stats-updated"&&!Fu&&Number.isFinite(Number(C?.stepCount))&&(hu===null||Gu>hu);jK(d,Cu)}}if(AK(C,d,Ru))L7()}Tn(()=>{if(V.current){V.current=!1;return}rr(()=>Mf(A.current),"Code Queue 加载失败")},[i?.id,mu]),Tn(()=>{if(!i||typeof EventSource>"u")return;let B=new EventSource(_E(f),{withCredentials:!0}),C=(nu)=>{try{UK(JSON.parse(String(nu.data||"{}")))}catch(Fu){zl(Af(Fu,"解析 Code Queue 事件失败"))}},d=()=>{if(SA())L7()};return B.addEventListener("trace-step-created",C),B.addEventListener("task-updated",C),B.addEventListener("queue-updated",C),B.addEventListener("trace-stats-updated",C),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,f,mu]),Tn(()=>{if(!i||!b||g)return;let B=String(b.id||"");if(!B)return;let C=String(b.updatedAt||"");if(x3(b))return;let d=`${B}:${C||"unknown"}:${String(b?._traceSummaryUpdatedAt||"")}`;if(Z.current.has(d))return;Z.current.add(d),di(B,!0).catch((nu)=>zl(Af(nu,"自动加载 Trace Summary 失败")))},[i?.id,b?.id,b?.updatedAt,b?.traceStats?.statsRevision,b?._traceSummaryUpdatedAt,b?._traceSummaryLoaded,g]);let JK=dr.length===0?K(Ti,{title:Cf?zu?"搜索中":"没有匹配任务":"队列为空",text:Cf?zu?`正在搜索包含“${en}”的 task...`:`未找到包含“${en}”的 task;可换个关键词或切换 queue。`:"提交一个任务后,Codex 会串行执行并保存输出。"}):[j7.length>0?K(CA,{key:"unread",title:"已结束未读",tasks:j7,selectedId:k,emptyText:"暂无已结束未读任务。",onSelect:a6,onCopy:I6,onReference:g6,onMarkRead:s6,copiedTaskId:vi,markingReadTaskId:ki}):null,K(CA,{key:"active",title:"运行 / 排队",tasks:SL,selectedId:k,emptyText:"当前没有运行或排队任务。",onSelect:a6,onCopy:I6,onReference:g6,onMarkRead:s6,copiedTaskId:vi,markingReadTaskId:ki}),K(CA,{key:"history",title:"历史 session",tasks:YL,selectedId:k,emptyText:"最近没有完成、失败或取消的 session。",onSelect:a6,onCopy:I6,onReference:g6,onMarkRead:s6,copiedTaskId:vi,markingReadTaskId:ki}),K("div",{key:"pagination",className:"codex-task-pagination","data-testid":"codex-task-pagination"},K("span",null,Cf?`搜索“${en}” · 已显示 ${dr.length} / ${Number.isFinite(si)?si:dr.length}`:`已加载 ${dr.length} / ${Number.isFinite(si)?si:dr.length}`),U7?K("button",{type:"button",className:"ghost-btn",disabled:x6,onClick:()=>void W7(),"data-testid":"codex-load-more-tasks-button"},x6?"加载中":Cf?"加载更多结果":"加载更早任务"):K("code",null,Cf?"已到结果末尾":"已到队列末尾"))],K7=(B,C=!1)=>K("label",{className:`code-queue-switcher ${C?"compact":""}`},K("span",null,C?"Queue":"查看 queue"),K("select",{value:mu,onChange:(d)=>oL(String(d.target.value||Zn)),"data-testid":B},K("option",{value:Zn},`All queues · ${Number.isFinite(dn)?dn:or.length} tasks · ${Zy.length} running`),qr.map((d)=>K("option",{key:String(d?.id||""),value:String(d?.id||"")},Mt(d))))),QK=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:lu,placeholder:"关键词 / task ID / prompt",autoComplete:"off",onChange:(B)=>_u(String(B.target.value||"")),"data-testid":"codex-task-search-input"}),lu?K("button",{type:"button",className:"ghost-btn",onClick:()=>_u(""),"data-testid":"codex-task-search-clear"},"清除"):null),K("small",{"data-testid":"codex-task-search-summary"},Cf?zu?"搜索中...":`匹配 ${dr.length}/${Number.isFinite(si)?si:dr.length}`:"支持 task ID、prompt、状态、provider、模型和最近输出关键词")),NK=K("div",{className:"codex-trace-status","data-testid":"codex-trace-status-summary"},K("span",{className:"codex-trace-status-chip queued"},K("b",null,"排队"),String(C6)),K("span",{className:"codex-trace-status-chip running"},K("b",null,"运行"),String(e_)),K("span",{className:`codex-trace-status-chip unread ${I0>0?"warn":""}`},K("b",null,"结束未读"),String(I0)),K("span",{className:"codex-trace-status-chip service"},K("b",null,"服务"),`${pL.providerStatus||"unknown"} · ${i?.providerId||"D601"} · ${mL.public?"公网暴露":"仅 UniDesk frontend 代理访问"}`),K("span",{className:"codex-trace-status-chip"},K("b",null,"执行节点"),u$.map((B)=>B.id).join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"执行模式"),N7.map((B)=>B.id).join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"模型"),Q7.join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"加载"),Pf?.phase==="complete"?iE(Pf?.totalMs):String(Pf?.phase||"idle")),K("span",{className:"codex-trace-status-chip"},K("b",null,"刷新"),s_?tl(s_):"--")),qK=K(R1,{title:b?`Trace ${String(b.id).slice(0,22)}`:"Trace 输出",eyebrow:b?`${b.status} / view=${g0} / task queue=${Rt(b)} / provider=${b.providerId||"D601"} / mode=${b.executionMode||"default"} / ${b.model} / agent loop trace`:`Agent loop trace / view=${g0}`,summary:NK,loading:g||Ey||zu||P||Pf?.phase==="loading",actions:K("div",{className:"panel-actions"},K7("code-queue-filter-select"),K("button",{type:"button",className:"ghost-btn codex-mark-all-read-btn",disabled:I0===0||Zl||zy,onClick:()=>void aL(),"data-testid":"codex-mark-all-read-button"},zy?"标记中":`全部标已读${I0>0?` (${I0})`:""}`),b?K("button",{type:"button",className:"ghost-btn",disabled:g||Zl,onClick:()=>void _K(),"data-testid":"codex-load-full-trace-button"},g?"加载中":jr(b)?"刷新 Summary":"加载 Summary"):null,K("button",{type:"button",className:"codex-session-title-toggle",onClick:()=>Ky((B)=>!B),"data-testid":"code-queue-sidebar-toggle"},Xr?"收起队列":"展开队列"),K("label",{className:"inline-check"},K("input",{type:"checkbox",checked:yl,onChange:(B)=>Qf(Boolean(B.target.checked))}),"自动滚动"),K("button",{type:"button",className:"ghost-btn",disabled:!ML||Zl,onClick:()=>void iK(),"data-testid":"codex-interrupt-button"},"打断"),K("button",{type:"button",className:"ghost-btn",disabled:!RL||Zl,onClick:()=>void yK()},"重试"),b?K(QQ,{title:"Codex Task",data:b,onOpen:l,testId:"raw-codex-task"}):null),className:"codex-output-panel"},K("div",{className:`codex-session-shell ${Xr?"":"queue-collapsed"}`},Xr?K("aside",{className:"codex-session-sidebar","data-testid":"codex-session-sidebar"},K("div",{className:"codex-session-sidebar-head"},K("div",null,K("span",null,kf(mu)?"All queues":"Queue lane"),K("strong",null,`${g0} · ${or.length}/${Number.isFinite(dn)?dn:or.length} sessions · 未读 ${I0}`)),K("button",{type:"button",className:"ghost-btn",onClick:()=>Ky(!1)},"收起")),K7("code-queue-filter-sidebar",!0),QK,K("div",{className:"codex-task-list codex-task-list-session",onScroll:sL,"data-testid":"codex-task-list-scroll"},JK)):null,K("div",{className:"codex-session-main"},K("div",{className:"codex-output-stack"},K(GZ,{task:b,loading:g,onLoadPromptPart:kL,onLoadSteps:k6,onLoadStep:IL}),K(zZ,{task:b})))));if(!i)return K(Ti,{title:"Code Queue 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=code-queue"});let G7=Number(Pf?.totalMs),z7=Number(Pf?.queueMs),T7=Number(Pf?.detailMs),E7=Number(Pf?.transcriptRows),WK=Pf?.phase==="complete"?"complete":String(Pf?.phase||"idle"),wK=h1(qr,an)||{id:an,name:an},LK=Uf?K(aJ,{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:Zl,onClose:()=>Ef(!1),actions:[K("button",{key:"cancel",type:"button",className:"ghost-btn",onClick:()=>Ef(!1),disabled:Zl,"data-testid":"codex-merge-queue-cancel"},"取消"),K("button",{key:"confirm",type:"button",className:"primary-btn",onClick:()=>void lK(),disabled:Zl||Ul||!lf,"data-testid":"codex-merge-queue-confirm"},Zl?"合并中...":"确认合并")]},K("p",{className:"codex-merge-dialog-target"},"目标 queue:",K("code",null,Mt(wK))),K("label",null,"源 queue",K("select",{value:lf,disabled:Zl||Ul,onChange:(B)=>ol(String(B.target.value||"")),"data-testid":"codex-merge-source-queue-select"},K("option",{value:""},"选择要合并进来的源 queue"),on.map((B)=>K("option",{key:String(B?.id||""),value:String(B?.id||"")},Mt(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":WK,"data-load-total-ms":Number.isFinite(G7)?String(Math.round(G7*10)/10):"","data-load-queue-ms":Number.isFinite(z7)?String(Math.round(z7*10)/10):"","data-load-detail-ms":Number.isFinite(T7)?String(Math.round(T7*10)/10):"","data-load-transcript-rows":Number.isFinite(E7)?String(E7):"","data-load-task-id":String(Pf?.taskId||k||""),"data-load-partial":Pf?.partial?"true":"false"},K(il,{error:m6,wide:!0}),LK,K("div",{className:"codex-session-stage codex-session-stage-top"},qK),K("div",{className:"code-queue-layout"},K("div",{className:"codex-left-rail"},K(R1,{title:"提交任务",eyebrow:Ul?"Submitting...":q0.length>1?`${q0.length} tasks`:"Single or Batch",className:"codex-compose-panel",loading:Ul},K("form",{className:`codex-task-form ${Ul?"is-submitting":""}`,onSubmit:fK,"data-testid":"code-queue-task-form","aria-busy":Ul?"true":"false"},K("label",null,"Prompt / 多任务用单独一行 --- 分隔",K("textarea",{value:s,rows:8,disabled:Ul,onChange:(B)=>Nu(B.target.value),placeholder:"写入 Codex 任务;多个任务之间用 --- 分隔。"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选)",K("input",{value:Eu,disabled:Ul,onChange:(B)=>Hu(B.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-reference-task-id"}),Li(Eu).length>0?K("code",null,`后端将解析并注入:${Li(Eu).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:vu,disabled:Ul,onChange:(B)=>ul(String(B.target.value||"default")),"data-testid":"code-queue-id-select"},qr.map((B)=>K("option",{key:String(B?.id||""),value:String(B?.id||"")},Mt(B)))),K("button",{type:"button",className:"ghost-btn codex-rename-queue-btn",onClick:()=>void eL(),disabled:Zl||Ul||!vu,title:"修改当前 queue 的显示名称,ID 不变","data-testid":"codex-rename-queue-button"},"改名"),K("button",{type:"button",className:"ghost-btn codex-merge-queue-btn",onClick:()=>uK(),disabled:Zl||Ul||on.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 dL(),disabled:Zl||Ul,"data-testid":"codex-create-queue-button"},"创建 queue"))),K("label",null,"模型",K("select",{value:Jf,disabled:Ul,onChange:(B)=>pu(B.target.value),"data-testid":"codex-model-select"},Q7.map((B)=>K("option",{key:B,value:B},B)))),K("label",null,"执行 Provider",K("select",{value:Zf,disabled:Ul,onChange:(B)=>bL(String(B.target.value||"D601")),"data-testid":"codex-provider-select"},u$.map((B)=>K("option",{key:B.id,value:B.id},`${B.label||B.id} · ${B.defaultWorkdir||eA(pl,B.id)}${B.supportsWindowsNativeCodex?" · Windows native":""}`)))),K("label",null,"执行模式",K("select",{value:Au,disabled:Ul,onChange:(B)=>vL(String(B.target.value||"default")),"data-testid":"codex-execution-mode-select"},N7.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:ff,disabled:Ul,onChange:(B)=>rf(B.target.value),placeholder:CL||pl?.defaultWorkdir||"/workspace","data-testid":"codex-cwd-input"})),K("label",null,"最大尝试",K("input",{type:"number",min:1,max:99,value:ur,disabled:Ul,onChange:(B)=>nf(Number(B.target.value)),"data-testid":"codex-max-attempts-input"})),K("label",null,"入队份数",K("input",{type:"number",min:1,max:50,value:Of,disabled:Ul,onChange:(B)=>N0(Number(B.target.value)),"data-testid":"codex-repeat-count-input"}))),By>1?K("label",{className:`codex-batch-confirm ${lr?"confirmed":""}`,"data-testid":"codex-batch-confirm-row"},K("input",{type:"checkbox",checked:lr,disabled:Ul,onChange:(B)=>k0(Boolean(B.target.checked)),"data-testid":"codex-batch-confirm-checkbox"}),K("span",null,`确认批量入队 ${By} 个任务(prompt 分段 ${h6.length} × 入队份数 ${rQ(Of)})`)):null,Ul?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:Zl||Ul||s.length===0&&Eu.length===0,onClick:()=>{Nu(""),Hu(""),k0(!1);let B="已清空任务输入栏";vl(B),fr("success",B)},"data-testid":"codex-clear-input-button"},"清空输入"),K("button",{type:"submit",className:"primary-btn",disabled:PL,"data-testid":"codex-enqueue-button"},Ul?"提交中,请等待...":J7?`请确认批量入队 ${By} 个任务`:q0.length>1?`批量入队 ${q0.length} 个任务`:"入队并运行"))))),K("div",{className:"codex-main-stage"},K("div",{className:"codex-detail-grid"},K(R1,{title:"运行控制",eyebrow:ai?"Queued prompt editable":b6?"Active turn steer":"Steer when running",loading:Zl},K("div",{className:"codex-run-control-stack"},K(qZ,{task:b,queueRows:qr,busy:Zl,onMove:tK}),b?.id?K("form",{className:"codex-steer-form codex-edit-prompt-form",onSubmit:nK,"data-testid":"codex-edit-prompt-form"},K("label",null,"编辑 queued 用户 prompt",K("textarea",{value:Yu,rows:5,onChange:(B)=>au(B.target.value),placeholder:"仅 QUEUED 且尚未开始运行的任务可在这里修改原始用户 prompt。",disabled:!ai||Zl,"data-testid":"codex-edit-prompt-textarea"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选,留空会清除引用)",K("input",{value:_l,disabled:!ai||Zl,onChange:(B)=>Pl(B.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-edit-reference-task-id"}),Li(_l).length>0?K("code",null,`将保留/注入:${Li(_l).join(" / ")}`):null),K("div",{className:"codex-form-actions"},K("button",{type:"button",className:"ghost-btn",disabled:!b?.id||Zl,onClick:()=>{au(b?k3(b):""),Pl(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},"data-testid":"codex-edit-prompt-reset"},"恢复当前值"),K("button",{type:"submit",className:"primary-btn",disabled:!ai||Zl||Yu.trim().length===0,title:ai?"保存后会重写尚未运行任务的用户 prompt":"只有 QUEUED 且尚未开始的任务可编辑 prompt","data-testid":"codex-edit-prompt-submit"},"保存 queued prompt"))):null,K("form",{className:"codex-steer-form",onSubmit:rK},K("label",null,"追加 prompt",K("textarea",{value:fu,rows:4,onChange:(B)=>Bu(B.target.value),placeholder:"给正在运行的 Codex session 推入新的指令或纠偏。",disabled:!b6})),K("button",{type:"submit",className:"primary-btn",disabled:!b6||Zl||fu.trim().length===0,"data-testid":"codex-steer-button"},"推入运行中 session")))),K(R1,{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(zi,{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"},MA(b.lastJudge.reason||"--",180)),K(zQ,{judge:b.lastJudge,testId:"codex-task-judge-failure-details"}),b.lastJudge.continuePrompt?K("code",{"data-testid":"codex-task-judge-continue-prompt"},MA(b.lastJudge.continuePrompt,160)):null):K(Ti,{title:"尚未判定",text:"Codex turn 结束后会由 MiniMax M2.7 或 fallback judge 判定 complete/retry/fail;retry 会在已有 thread 追加继续执行 prompt。"}))),K(NZ,{stats:P6,queueName:g0,onRaw:l}),K(R1,{title:"Attempts",eyebrow:"terminal vs interruption",loading:g},K(TZ,{task:b})))))}var bt=Pu(Jl(),1);var Vu=bt.default.createElement,{useEffect:u2}=bt.default,l2=bt.default.useState,EZ=bt.default.useRef,r2=` :root { --surfacePrimary: #ffffff; --surfaceSecondary: #f8fafc; @@ -226,64 +226,64 @@ nav .material-icons::before { display: none !important; } } -`;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("+",` +`;function f2({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){return Vu("section",{className:`panel ${n||""}`},Vu("div",{className:"panel-head"},Vu("div",null,l?Vu("p",{className:"panel-eyebrow"},l):null,Vu(nl,{title:u,loading:i})),f?Vu("div",{className:"panel-actions"},f):null),Vu("div",{className:"panel-body"},r))}function ZZ({title:u,data:l,onOpen:f,testId:r}){return Vu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>f(u,l)},"查看原始JSON")}function OZ({title:u,text:l}){return Vu("div",{className:"empty-state"},Vu("strong",null,u),Vu("span",null,l))}function mQ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function PQ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function CQ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function HZ(u){return u.filter((f)=>f?.id==="filebrowser"||String(f?.id||"").startsWith("filebrowser-")).sort((f,r)=>{let n=(i)=>i.providerId==="D518"?0:i.providerId==="D601"?1:i.id==="filebrowser"?2:3;return n(f)-n(r)||String(f.id).localeCompare(String(r.id))})}function BZ(u){if(u?.providerId==="D518")return"D518";return u?.providerId||u?.name||u?.id||"Unknown"}function VZ(u,l,f="/"){let r=f.startsWith("/")?f:`/${f}`;return`${u}/microservices/${encodeURIComponent(l)}/proxy${r}`}function DZ(u,l){return`${u}/microservices/${encodeURIComponent(l)}/health`}async function XZ(u,l=16000){let f=new AbortController,r=setTimeout(()=>f.abort(),l);try{return await Tu(u,{signal:f.signal,failureFields:[!1]})}finally{clearTimeout(r)}}function MQ(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 a3(u){return u?.status==="OK"||u?.ok===!0}function SZ({service:u,active:l,health:f,onSelect:r,onRaw:n}){let i=mQ(u),y=PQ(u),t=CQ(u),_=i.container||{},c=a3(f?.body);return Vu("button",{type:"button",className:`filebrowser-target-card ${l?"active":""}`,"data-testid":`filebrowser-target-card-${u.id}`,onClick:r},Vu("span",{className:`status-badge ${c?"ok":i.providerStatus==="online"?"running":"warn"}`},c?"Health OK":i.providerStatus||"unknown"),Vu("strong",null,u.name||u.id),Vu("span",null,MQ(u)),Vu("code",null,`${y.nodeBindHost||"--"}:${y.nodePort||"--"}`),Vu("small",null,_.name?`${_.name} / ${_.state||"--"}`:`${t.composeService||"--"}`),Vu("span",{className:"filebrowser-card-raw",onClick:(A)=>{A.stopPropagation(),n(`${u.name} service`,u)}},"JSON"))}function RQ(u){try{return u?.contentDocument||u?.contentWindow?.document||null}catch{return null}}function n2(u){let l=RQ(u);if(l===null||l.head===null)return!1;let f=l.getElementById("unidesk-filebrowser-compact-style");if(f===null)f=l.createElement("style"),f.id="unidesk-filebrowser-compact-style",l.head.appendChild(f);if(f.textContent!==r2)f.textContent=r2;return!0}function YZ(u,l){let f=URL.createObjectURL(u),r=document.createElement("a");r.href=f,r.download=l,document.body.appendChild(r),r.click(),r.remove(),setTimeout(()=>URL.revokeObjectURL(f),2000)}function pZ(u,l){let f=RQ(u);if(f===null||f.documentElement===null)throw Error("无法访问 File Browser iframe 文档");n2(u);let r=Math.max(640,Math.ceil(u.clientWidth||f.documentElement.clientWidth||1280)),n=Math.max(480,Math.ceil(u.clientHeight||f.documentElement.clientHeight||720)),i=f.documentElement.cloneNode(!0);i.querySelectorAll("script, style, link[rel='stylesheet'], link[rel='preload'], link[rel='icon']").forEach((A)=>A.remove()),i.querySelectorAll("img").forEach((A)=>{A.removeAttribute("src"),A.removeAttribute("srcset")});let y=i.querySelector("head");if(y===null)y=f.createElement("head"),i.insertBefore(y,i.firstChild);let t=f.createElement("style");t.textContent=`${r2} +html,body{width:${r}px!important;min-height:${n}px!important;overflow:hidden!important;}`,y.appendChild(t);let _=new XMLSerializer().serializeToString(i),c=`${_}`;YZ(new Blob([c],{type:"image/svg+xml;charset=utf-8"}),l.replace(/\.png$/i,".svg"))}function xQ({microservices:u,onRaw:l,apiBaseUrl:f="/api"}){let r=HZ(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||"",[t,_]=l2(y),[c,A]=l2({loading:!1,refreshedAt:null,health:{},error:""}),[j,F]=l2({exporting:!1,message:"",error:""}),J=EZ(null),Q=r.find((Z)=>Z.id===t)||r[0]||null,w=mQ(Q),L=PQ(Q),U=CQ(Q),N=Q?c.health[Q.id]:null,q=Q?VZ(f,Q.id,"/"):"about:blank";u2(()=>{if(r.length===0)return;if(!t||!r.some((Z)=>Z.id===t))_(r[0].id)},[r.map((Z)=>Z.id).join(",")]),u2(()=>{let Z=0,H=setInterval(()=>{if(Z+=1,n2(J.current)||Z>=24)clearInterval(H)},500);return()=>clearInterval(H)},[q]),u2(()=>{if(r.length===0)return;let Z=!1;async function H(){A((h)=>({...h,loading:!0,error:""}));let D=await Promise.all(r.map(async(h)=>{try{let V=await XZ(DZ(f,h.id));return[h.id,{ok:!0,body:V}]}catch(V){return[h.id,{ok:!1,error:Ou(V,"File Browser health failed")}]}}));if(Z)return;A({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(","),f]);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 pZ(J.current,`unidesk-filebrowser-${Q?.id||"target"}-${Z}.png`),F({exporting:!1,message:"截图已导出",error:""})}catch(Z){F({exporting:!1,message:"",error:Ou(Z,"截图导出失败")})}}if(r.length===0)return Vu(OZ,{title:"File Browser 未登记",text:"请在 config.json 的 microservices 中登记 id=filebrowser 或 filebrowser-* 用户服务"});return Vu("div",{className:"filebrowser-page","data-testid":"filebrowser-page"},c.error?Vu(il,{error:c.error,wide:!0}):null,Vu(f2,{title:"文件管理器",eyebrow:"File Browser / Host Files",loading:c.loading,actions:Vu("div",{className:"panel-actions"},Q?Vu("button",{type:"button",className:"ghost-btn",onClick:z,disabled:j.exporting,"data-testid":"filebrowser-export-screenshot"},j.exporting?"导出中...":"导出截图"):null,Q?Vu("a",{className:"ghost-btn",href:q,target:"_blank",rel:"noreferrer"},"新窗口打开"):null,Q?Vu(ZZ,{title:"File Browser 当前目标",data:{service:Q,health:N},onOpen:l,testId:"raw-filebrowser-active"}):null)},Vu("div",{className:"filebrowser-hero"},Vu("div",null,Vu("span",{className:`status-badge ${a3(N?.body)?"ok":"warn"}`},a3(N?.body)?"Health OK":"Health Pending"),Vu("h3",null,Q?.name||"File Browser"),Vu("p",{className:"muted paragraph"},Q?.description||"通过 UniDesk 登录态代理访问,不开放 File Browser 公网端口。"),j.error?Vu("p",{className:"filebrowser-shot-error"},j.error):null,j.message?Vu("p",{className:"filebrowser-shot-ok"},j.message):null),Vu("div",{className:"microservice-ref-card"},Vu("span",null,"Provider"),Vu("strong",null,Q?.providerId||"--"),Vu("code",null,w.providerName||Q?.providerId||"--")),Vu("div",{className:"microservice-ref-card"},Vu("span",null,"Private Backend"),Vu("strong",null,`${L.nodeBindHost||"--"}:${L.nodePort||"--"}`),Vu("code",null,L.nodeBaseUrl||"--")),Vu("div",{className:"microservice-ref-card"},Vu("span",null,"Image"),Vu("strong",null,U.dockerfile||"filebrowser/filebrowser:v2.63.3"),Vu("code",null,U.commitId||"--")),Vu("div",{className:"microservice-ref-card"},Vu("span",null,"Mount"),Vu("strong",null,MQ(Q)),Vu("code",null,Q?.providerId==="main-server"?"/root, /var, /home":"/home, /mnt/c, /mnt/d")))),Vu(f2,{title:"浏览目标",eyebrow:`${r.length} host targets`,loading:c.loading},Vu("div",{className:"filebrowser-target-grid"},r.map((Z)=>Vu(SZ,{key:Z.id,service:Z,active:Z.id===Q?.id,health:c.health[Z.id],onSelect:()=>W(Z.id),onRaw:l})))),Vu(f2,{title:`${BZ(Q)} 文件视图`,eyebrow:N?.body?`Health ${a3(N.body)?"OK":"UNKNOWN"} / ${c.refreshedAt?tl(c.refreshedAt):"--"}`:"Embedded WebUI",className:"filebrowser-frame-panel"},Vu("div",{className:"filebrowser-frame-shell"},Vu("div",{className:"filebrowser-frame-toolbar"},Vu("span",null,"BaseURL"),Vu("code",null,`/api/microservices/${Q?.id||"filebrowser"}/proxy`),Vu("span",null,"Root"),Vu("code",null,"/srv"),Vu("span",{className:"filebrowser-compact-note"},"Compact layout injected")),Vu("iframe",{ref:J,key:q,title:`${Q?.name||"File Browser"} WebUI`,src:q,className:"filebrowser-frame","data-testid":"filebrowser-frame",onLoad:(Z)=>n2(Z.currentTarget),sandbox:"allow-downloads allow-forms allow-modals allow-same-origin allow-scripts"}))))}var uc=Pu(Jl(),1);var Uu=uc.default.createElement,{useEffect:mZ}=uc.default,PZ=uc.default.useState;function o3({status:u,children:l}){let f=String(u||"unknown").toLowerCase();return Uu("span",{className:`status-badge ${f}`},l||u||"unknown")}function On({label:u,value:l,hint:f,tone:r}){return Uu("article",{className:`metric-card ${r||""}`},Uu("div",{className:"metric-label"},u),Uu("div",{className:"metric-value"},l),Uu("div",{className:"metric-hint"},f))}function d3({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){return Uu("section",{className:`panel ${n||""}`},Uu("div",{className:"panel-head"},Uu("div",null,l?Uu("p",{className:"panel-eyebrow"},l):null,Uu(nl,{title:u,loading:i})),f?Uu("div",{className:"panel-actions"},f):null),Uu("div",{className:"panel-body"},r))}function e3({title:u,data:l,onOpen:f,testId:r}){return Uu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>f(u,l)},"查看原始JSON")}function i2({title:u,text:l}){return Uu("div",{className:"empty-state"},Uu("strong",null,u),Uu("span",null,l))}function CZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function MZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function RZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Ei(u,l){let f=u&&typeof u==="object"?u[l]:void 0;return Number.isFinite(Number(f))?String(f):"--"}function xZ(u){return(Array.isArray(u?.jobs)?u.jobs:[]).slice(0,40)}function hZ(u){return(Array.isArray(u?.drafts)?u.drafts:[]).slice(0,12)}function hQ({microservices:u,onRaw:l,apiBaseUrl:f="/api"}){let r=u.find((Q)=>Q.id==="findjob")||null,[n,i]=PZ({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,w,L,U]=await Promise.all([Tu(`${f}/microservices/findjob/health`),Tu(`${f}/microservices/findjob/proxy/api/summary`),Tu(`${f}/microservices/findjob/proxy/api/jobs?__unideskArrayLimit=jobs:40`),Tu(`${f}/microservices/findjob/proxy/api/drafts`)]);i({loading:!1,error:"",health:Q,summary:w,jobs:L,drafts:U,refreshedAt:new Date})}catch(Q){i((w)=>({...w,loading:!1,error:Ou(Q,"FindJob 加载失败")}))}}if(mZ(()=>{y()},[r?.id,r?.runtime?.providerStatus]),!r)return Uu(i2,{title:"FindJob 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=findjob"});let t=CZ(r),_=RZ(r),c=MZ(r),A=n.summary||{},j=xZ(n.jobs),F=hZ(n.drafts),J=n.jobs?._unidesk?.arrayLimits?.jobs;return Uu("div",{className:"findjob-page","data-testid":"findjob-page"},Uu(d3,{title:"FindJob 工作台",eyebrow:"D601 用户服务",loading:n.loading,actions:Uu("div",{className:"panel-actions"},Uu("button",{type:"button",className:"ghost-btn",onClick:y,disabled:n.loading,"data-testid":"findjob-refresh-button"},n.loading?"刷新中":"刷新"),Uu(e3,{title:"FindJob 用户服务",data:r,onOpen:l,testId:"raw-findjob-service"}))},Uu("div",{className:"findjob-hero"},Uu("div",null,Uu("div",{className:"node-version-line"},Uu(o3,{status:t.providerStatus==="online"?"online":"warn"},t.providerStatus||"unknown"),Uu("span",null,r.providerId),Uu("span",null,c.public?"公网暴露":"仅 UniDesk frontend 代理访问")),Uu("p",{className:"muted paragraph"},r.description)),Uu("div",{className:"microservice-ref-card"},Uu("span",null,"Repo"),Uu("strong",null,_.url||"--"),Uu("code",null,_.commitId||"--")),Uu("div",{className:"microservice-ref-card"},Uu("span",null,"D601 Docker"),Uu("strong",null,`${c.nodeBindHost||"--"}:${c.nodePort||"--"}`),Uu("code",null,`${_.composeFile||"--"} / ${_.composeService||"--"}`))),Uu(il,{error:n.error,wide:!0})),Uu("div",{className:"findjob-grid"},Uu(d3,{title:"岗位指标",eyebrow:n.refreshedAt?`Updated ${tl(n.refreshedAt)}`:"Summary",loading:n.loading},Uu("div",{className:"metric-grid"},Uu(On,{label:"岗位总量",value:Ei(A,"totalJobs"),hint:"tracked jobs",tone:"ok"}),Uu(On,{label:"原始岗位",value:Ei(A,"rawJobs"),hint:"raw queue"}),Uu(On,{label:"已验证",value:Ei(A,"verifiedJobs"),hint:"verified set"}),Uu(On,{label:"优先处理",value:Ei(A,"prioritizedJobs"),hint:"prioritized"}),Uu(On,{label:"过期",value:Ei(A,"staleJobs"),hint:"stale jobs",tone:"warn"}),Uu(On,{label:"无效",value:Ei(A,"invalidJobs"),hint:"invalid jobs",tone:"warn"}),Uu(On,{label:"上海",value:Ei(A,"shanghaiJobs"),hint:"city filter"}),Uu(On,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /api/health"})),Uu("div",{className:"panel-actions inline-actions"},Uu(e3,{title:"FindJob Summary",data:A,onOpen:l,testId:"raw-findjob-summary"}))),Uu(d3,{title:"近期岗位",eyebrow:J?`${J.returnedLength}/${J.originalLength} Preview`:`${j.length} Preview`,loading:n.loading},j.length===0?Uu(i2,{title:"暂无岗位预览",text:"等待 D601 findjob backend 返回 /api/jobs"}):Uu("div",{className:"table-wrap findjob-job-table"},Uu("table",null,Uu("thead",null,Uu("tr",null,Uu("th",null,"优先级"),Uu("th",null,"状态"),Uu("th",null,"单位"),Uu("th",null,"职位"),Uu("th",null,"城市"),Uu("th",null,"阶段"),Uu("th",null,"截止"),Uu("th",null,"证据"))),Uu("tbody",null,j.map((Q)=>Uu("tr",{key:Q.id},Uu("td",null,Uu(o3,{status:String(Q.priority||"").toLowerCase()||"unknown"},Q.priority||"--")),Uu("td",null,Uu(o3,{status:String(Q.status||"").toLowerCase()||"unknown"},Q.status||"--")),Uu("td",null,Q.organization_name||"--",Uu("code",null,Q.id||"--")),Uu("td",null,Q.display_title||Q.title||"--"),Uu("td",null,Q.display_city||Q.city||"--"),Uu("td",null,Q.workflow_stage||"--"),Uu("td",null,Q.deadline||"--"),Uu("td",null,Q.evidence_url?Uu("a",{href:Q.evidence_url,target:"_blank",rel:"noreferrer"},"打开"):Uu("span",{className:"muted"},"无"))))))),Uu("div",{className:"panel-actions inline-actions"},Uu(e3,{title:"FindJob Jobs Preview",data:n.jobs,onOpen:l,testId:"raw-findjob-jobs"}))),Uu(d3,{title:"草稿与报告",eyebrow:`${F.length} Drafts`,loading:n.loading},F.length===0?Uu(i2,{title:"暂无草稿",text:"D601 findjob backend 未返回 drafts"}):Uu("div",{className:"draft-list"},F.map((Q)=>Uu("article",{key:Q.id,className:"draft-card"},Uu("div",{className:"node-card-head"},Uu("strong",null,Q.id),Uu(o3,{status:Q.status},Q.status||"--")),Uu("div",{className:"docker-meta compact"},Uu("span",null,Q.workflow_stage||"--"),Uu("span",null,`jobs ${Q.counts?.jobs??0}`),Uu("span",null,`reports ${Q.counts?.reports??0}`)),Uu("span",null,Q.latestReportPath||"暂无报告"),Uu("code",null,qu(Q.updated_at||Q.updatedAt))))),Uu("div",{className:"panel-actions inline-actions"},Uu(e3,{title:"FindJob Drafts",data:n.drafts,onOpen:l,testId:"raw-findjob-drafts"})))))}var gt=Pu(Jl(),1);var M=gt.default.createElement,{useEffect:bZ}=gt.default,y2=gt.default.useState;function vt(u){let l=Number(u);return Number.isFinite(l)?`${Math.max(0,Math.min(100,l)).toFixed(1)}%`:"--"}function _2(u){if(u===null||u===void 0||u==="")return"--";let l=Number(u);if(!Number.isFinite(l))return"--";if(l<60)return`${Math.max(0,Math.round(l))}s`;if(l<3600)return`${Math.floor(l/60)}m ${Math.round(l%60)}s`;return`${Math.floor(l/3600)}h ${Math.floor(l%3600/60)}m`}function $2(u,l=2){let f=Number(u);if(!Number.isFinite(f))return u===!1?"false":u===!0?"true":"--";let r=Math.abs(f);if(Number.isInteger(f)||r>=1000)return f.toLocaleString("zh-CN",{maximumFractionDigits:0});if(r>=1)return f.toLocaleString("zh-CN",{maximumFractionDigits:l});return f.toLocaleString("zh-CN",{maximumFractionDigits:Math.max(l,6)})}function It(u){if(u===null||u===void 0||u==="")return"--";if(typeof u==="boolean")return u?"true":"false";if(typeof u==="number")return $2(u,4);if(Array.isArray(u))return u.map((l)=>It(l)).join(" x ");if(typeof u==="object")return"已上报";return String(u)}function lc(u){let l=Number(u);if(!Number.isFinite(l)||l<=0)return"--";let f=l>=100?0:l>=10?1:2;return`${l.toLocaleString("zh-CN",{maximumFractionDigits:f})} epoch/h`}function fc(u){return u.replace(/[^a-zA-Z0-9_-]/g,"-")}function If(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function kt({status:u,children:l}){let f=String(u||"unknown").toLowerCase();return M("span",{className:`status-badge ${f}`},l||u||"unknown")}function Hn({label:u,value:l,hint:f,tone:r}){return M("article",{className:`metric-card ${r||""}`},M("div",{className:"metric-label"},u),M("div",{className:"metric-value"},l),M("div",{className:"metric-hint"},f))}function t2({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){return M("section",{className:`panel ${n||""}`},M("div",{className:"panel-head"},M("div",null,l?M("p",{className:"panel-eyebrow"},l):null,M(nl,{title:u,loading:i})),f?M("div",{className:"panel-actions"},f):null),M("div",{className:"panel-body"},r))}function v1({title:u,data:l,onOpen:f,testId:r}){return M("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),f(u,l)}},"查看原始JSON")}function p0({title:u,text:l}){return M("div",{className:"empty-state"},M("strong",null,u),M("span",null,l))}function vZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function kZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function IZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function gZ(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function sZ(u){return Array.isArray(u?.jobs)?u.jobs.slice(0,240):[]}function aZ(u){return Array.isArray(u?.projects)?u.projects.slice(0,1000):[]}function rc(u){return Array.isArray(u?.projects)?u.projects:[]}function oZ(u,l){if(Array.isArray(l?.gpu))return l.gpu;if(Array.isArray(u?.gpu))return u.gpu;return[]}function Fr(u,l){return`${u}/microservices/met-nonlinear/proxy${l}`}function bQ(u){return u.startedAt&&u.finishedAt?_2((Date.parse(u.finishedAt)-Date.parse(u.startedAt))/1000):"--"}function dZ(u){let l=u.progress||{};if(l.etaSeconds!==null&&l.etaSeconds!==void 0&&l.etaSeconds!==""){let y=Number(l.etaSeconds);if(Number.isFinite(y))return Math.max(0,y)}let f=Number(l.currentEpoch),r=Number(l.epochTarget??u.epochTarget),n=Date.parse(u.startedAt||"");if(!Number.isFinite(f)||f<=0||!Number.isFinite(r)||r<=f||!Number.isFinite(n))return null;let i=Math.max(0,(Date.now()-n)/1000);if(i<=0)return null;return Math.max(0,i/f*(r-f))}function vQ(u){let l=u.progress||{},f=Number(l.epochPerHour);if(Number.isFinite(f)&&f>0)return f;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(l.currentEpoch??u.epochTarget);if(!Number.isFinite(i)||i<=0)return null;return i/((n-r)/3600000)}function kQ(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 IQ(u,l,f){return{name:u,path:l,depth:f,count:0,children:[],project:null}}function eZ(u){let l=IQ("","",-1);for(let r of u){let i=String(r?.projectPath||"").replace(/\\/g,"/").split("/").filter(Boolean);if(i.length===0)continue;let y=l,t=[];for(let[_,c]of i.entries()){t.push(c);let A=t.join("/"),j=y.children.find((F)=>F.path===A);if(!j)j=IQ(c,A,_),y.children.push(j);if(_===i.length-1)j.project=r;y=j}}let f=(r)=>{let n=r.children.reduce((i,y)=>i+f(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 f(l),l}function uO(u){let l=If(u.data);return If(l.project).projectPath?If(l.project):l}function lO(u){return If(If(u.data).job)}function gQ({microservices:u,onRaw:l,apiBaseUrl:f="/api"}){let r=u.find((P)=>P.id==="met-nonlinear")||null,[n,i]=y2({loading:!1,actionBusy:!1,error:"",health:null,summary:null,queue:null,projects:null,history:null,images:null,refreshedAt:null}),[y,t]=y2({loading:!1,error:"",kind:"",key:"",title:"",data:null}),[_,c]=y2(()=>({activeTab:"projects",selectedProjects:{},expandedProjectDirs:{},sourceProject:"",forkCount:1,forkEpochs:200,forkPrefix:`ui_fork_${Date.now()}`,maxConcurrency:3,targetGpuName:"2080 Ti",actionMessage:""}));function A(P){c((e)=>({...e,...P}))}async function j(P=_.activeTab){if(!r)return;i((e)=>({...e,loading:!0,error:""}));try{let e=[["health",Tu(`${f}/microservices/met-nonlinear/health`)],["summary",Tu(Fr(f,"/api/summary"))]];if(P==="projects")e.push(["projectsRoot",Tu(Fr(f,"/api/projects?root=projects&limit=500"))]),e.push(["exProjectsRoot",Tu(Fr(f,"/api/projects?root=ex_projects&limit=500"))]);if(P==="current"||P==="completed"||P==="failed")e.push(["queue",Tu(Fr(f,"/api/queue"))]);if(P==="completed"||P==="failed")e.push(["history",Tu(Fr(f,"/api/history"))]);if(P==="gpu")e.push(["images",Tu(Fr(f,"/api/images"))]);let uu=Object.fromEntries(await Promise.all(e.map(async([s,Nu])=>[s,await Nu]))),Ku={loading:!1,actionBusy:!1,error:"",health:uu.health,summary:uu.summary,refreshedAt:new Date};if(uu.projectsRoot||uu.exProjectsRoot){let{projectsRoot:s,exProjectsRoot:Nu}=uu;Ku.projects={ok:s?.ok!==!1&&Nu?.ok!==!1,roots:[{root:"projects",count:rc(s).length},{root:"ex_projects",count:rc(Nu).length}],projects:[...rc(s),...rc(Nu)]}}if(uu.queue)Ku.queue=uu.queue;if(uu.history)Ku.history=uu.history;if(uu.images)Ku.images=uu.images;i((s)=>({...s,...Ku}))}catch(e){i((uu)=>({...uu,loading:!1,actionBusy:!1,error:Ou(e,"MET Nonlinear 加载失败")}))}}async function F(P,e){i((uu)=>({...uu,actionBusy:!0,error:""})),A({actionMessage:`${P}...`});try{let uu=await e();A({actionMessage:uu||`${P}完成`}),await j()}catch(uu){i((Ku)=>({...Ku,actionBusy:!1,error:Ou(uu,`${P}失败`)}))}}async function J(){await F("保存并发设置",async()=>{await Tu(Fr(f,"/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 w(){let P=Q();if(P.length===0)throw Error("请先选择至少一个 project");await F("加入待启动队列",async()=>{await Tu(Fr(f,"/api/queue"),{method:"POST",body:JSON.stringify({projectPaths:P,maxConcurrency:Number(_.maxConcurrency),targetGpuName:_.targetGpuName,start:!1})}),A({activeTab:"current",selectedProjects:{}})})}async function L(){let P=_.sourceProject||p[0]?.projectPath;if(!P)throw Error("请先选择源 project");await F("Fork Project",async()=>{let e=await Tu(Fr(f,"/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:[],Ku=uu.reduce((s,Nu)=>{return s[Nu]=!0,s},{..._.selectedProjects});return A({selectedProjects:Ku}),`已 fork ${uu.length} 个 project,并已自动勾选;请确认后点击加入待启动队列。`})}async function U(){await F("启动队列",async()=>{await Tu(Fr(f,"/api/queue/start"),{method:"POST",body:JSON.stringify({maxConcurrency:Number(_.maxConcurrency),targetGpuName:_.targetGpuName})}),A({activeTab:"current"})})}async function N(P){await F("取消任务",async()=>{await Tu(Fr(f,`/api/jobs/${encodeURIComponent(P.id)}/cancel`),{method:"POST",body:JSON.stringify({})})})}async function q(P){let e=String(P?.projectPath||"");if(!e)return;t({loading:!0,error:"",kind:"project",key:e,title:e,data:null});try{let uu=await Tu(Fr(f,`/api/projects/config?path=${encodeURIComponent(e)}`));t({loading:!1,error:"",kind:"project",key:e,title:e,data:uu})}catch(uu){t({loading:!1,error:Ou(uu,"Project 详情加载失败"),kind:"project",key:e,title:e,data:null})}}async function W(P){let e=String(P?.id||"");if(!e)return;t({loading:!0,error:"",kind:"job",key:e,title:P.projectPath||e,data:null});try{let uu=await Tu(Fr(f,`/api/jobs/${encodeURIComponent(e)}`));t({loading:!1,error:"",kind:"job",key:e,title:uu?.job?.projectPath||P.projectPath||e,data:uu})}catch(uu){t({loading:!1,error:Ou(uu,"Job 详情加载失败"),kind:"job",key:e,title:P.projectPath||e,data:null})}}if(bZ(()=>{j(_.activeTab)},[r?.id,r?.runtime?.providerStatus,_.activeTab]),!r)return M(p0,{title:"MET Nonlinear 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=met-nonlinear"});let z=vZ(r),Z=IZ(r),H=kZ(r),E=gZ(n.queue?.queue||n.summary?.queue),D=oZ(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||{},S=sZ(n.queue),p=aZ(n.projects),O=eZ(p),m=_.sourceProject||p[0]?.projectPath||"",X=S.filter((P)=>["staged","queued","running"].includes(P.status)),v=S.filter((P)=>P.status==="succeeded"),T=S.filter((P)=>["failed","canceled"].includes(P.status)),Y=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 M(p0,{title:e==="current"?"当前队列为空":"暂无记录",text:e==="current"?"从项目库选择或 fork project 后先加入待启动队列,再启动队列。":"终态任务会显示耗时、exit code 和失败诊断。"});return M("div",{className:"table-wrap met-job-table"},M("table",null,M("thead",null,M("tr",null,M("th",null,"状态"),M("th",null,"Project"),M("th",null,"Epoch"),M("th",null,"速度"),M("th",null,"ETA/耗时"),M("th",null,"GPU"),M("th",null,"Exit"),M("th",null,"更新时间"),M("th",null,"操作"))),M("tbody",null,P.map((uu)=>{let Ku=uu.progress||{},s=["staged","queued","running"].includes(uu.status),Nu=y.kind==="job"&&y.key===uu.id;return M("tr",{key:uu.id,className:`met-click-row ${Nu?"active":""}`,onClick:()=>W(uu),"data-testid":`met-job-row-${fc(uu.id)}`},M("td",null,M(kt,{status:uu.status},kQ(uu.status))),M("td",null,M("button",{type:"button",className:"met-inline-link",onClick:(Eu)=>{Eu.stopPropagation(),W(uu)}},uu.projectPath),M("code",null,uu.id)),M("td",null,M("span",null,`${Ku.currentEpoch??"--"} / ${Ku.epochTarget??uu.epochTarget??"--"}`),M("div",{className:"met-progress"},M("span",{style:{width:vt(Ku.progressPercent)}}))),M("td",null,M("strong",null,lc(vQ(uu)))),M("td",null,uu.status==="succeeded"||uu.status==="failed"||uu.status==="canceled"?bQ(uu):uu.status==="running"?`ETA ${_2(dZ(uu))}`:"--"),M("td",null,uu.gpuName||"--"),M("td",null,uu.exitCode??"--"),M("td",null,qu(uu.updatedAt)),M("td",null,s?M("button",{type:"button",className:"ghost-btn mini",onClick:(Eu)=>{Eu.stopPropagation(),N(uu)},disabled:n.actionBusy},"取消"):null,M(v1,{title:`MET Job ${uu.id}`,data:uu,onOpen:l,testId:`raw-met-job-${uu.id}`})))}))))}function b(){return M("div",{className:"met-queue-summary","data-testid":"met-current-summary"},M(kt,{status:"staged"},`待启动 ${E.staged??0}`),M(kt,{status:"queued"},`排队中 ${E.queued??0}`),M(kt,{status:"running"},`训练中 ${E.running??0}`),M("span",null,`最大并发 ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??_.maxConcurrency}`),M("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);A({expandedProjectDirs:{..._.expandedProjectDirs,[P]:!uu}})}function x(P){let e=8+Math.max(0,P.depth)*16;if(Boolean(P.project)){let s=P.project,Nu=Boolean(_.selectedProjects[s.projectPath]),Eu=y.kind==="project"&&y.key===s.projectPath;return M("div",{key:P.path,className:`met-tree-row project ${Nu?"selected":""} ${Eu?"active":""}`,style:{paddingLeft:e},onClick:()=>q(s),"data-testid":`met-project-node-${fc(s.projectPath)}`},M("div",{className:"met-tree-name"},M("input",{type:"checkbox",checked:Nu,onClick:(Hu)=>Hu.stopPropagation(),onChange:(Hu)=>A({selectedProjects:{..._.selectedProjects,[s.projectPath]:Hu.target.checked}}),"data-testid":`met-project-checkbox-${fc(s.projectPath)}`}),M("button",{type:"button",className:"met-inline-link project-path",onClick:(Hu)=>{Hu.stopPropagation(),q(s)}},P.name)),M("span",null,s.useModel||"--"),M("span",null,s.epochTrain??"--"),M("span",null,vt(s.progress?.progressPercent)),M("span",null,lc(s.progress?.epochPerHour)))}let Ku=o(P.path,P.depth);return M(gt.default.Fragment,{key:P.path},M("div",{className:"met-tree-row folder",style:{paddingLeft:e},"data-testid":`met-project-folder-${fc(P.path)}`},M("button",{type:"button",className:"met-tree-toggle",onClick:()=>g(P.path,P.depth),"aria-label":Ku?`折叠 ${P.path}`:`展开 ${P.path}`},Ku?"-":"+"),M("strong",null,P.name),M("span",{className:"met-tree-count"},`${P.count} projects`)),Ku?P.children.map((s)=>x(s)):null)}function lu(P){return M("div",{className:"met-detail-kv"},P.map((e)=>M("div",{key:e.label,className:"met-detail-kv-item"},M("span",null,e.label),M("strong",null,It(e.value)),e.hint?M("small",null,e.hint):null)))}function _u(P,e){return M("div",{className:"met-detail-section"},M("h3",null,P),lu(e))}function $u(P){if(!Array.isArray(P)||P.length===0)return M(p0,{title:"模型层未上报",text:"等待 data/model_info.json 或 compute_analysis.json 生成。"});return M("div",{className:"table-wrap met-layer-table"},M("table",null,M("thead",null,M("tr",null,M("th",null,"Layer"),M("th",null,"Type"),M("th",null,"Params"),M("th",null,"Trainable"),M("th",null,"Compute"))),M("tbody",null,P.slice(0,18).map((e,uu)=>M("tr",{key:`${e.name||"layer"}-${uu}`},M("td",null,e.name||`#${uu+1}`),M("td",null,e.type||"--"),M("td",null,$2(e.num_params)),M("td",null,e.trainable===void 0?"--":String(Boolean(e.trainable))),M("td",null,$2(e.compute?.total??e.estimated_cost?.weighted_units?.total)))))))}function ju(P){let e=Array.isArray(P)?P:[];if(e.length===0)return M(p0,{title:"data/ 暂无文件",text:"训练或评估完成后会生成 training_state、metrics、model_info 等文件。"});return M("div",{className:"met-file-chip-grid"},e.slice(0,48).map((uu)=>M("span",{key:uu},uu)),e.length>48?M("span",null,`+${e.length-48}`):null)}function zu(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 M(p0,{title:"暂无日志尾部",text:"该任务未上报 logTail 或日志已轮转。"});return M("div",{className:"met-log-lines"},e.map((uu,Ku)=>M("div",{key:`${Ku}-${uu.slice(0,16)}`},uu)))}function Wu(){if(y.loading)return M("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},M("div",{className:"panel-head compact"},M("div",null,M("p",{className:"panel-eyebrow"},"Detail Loading"),M(nl,{title:"详情加载中",loading:!0}))),M(p0,{title:"详情加载中",text:y.title||"正在读取 D601 data/ 和 config.json"}));if(y.error)return M("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},M(il,{error:y.error,wide:!0}));if(!y.data)return M("section",{className:"met-detail-panel muted","data-testid":"met-detail-panel"},M(p0,{title:"选择一个项目或任务查看详情",text:"项目库、当前队列、已完成和失败诊断中的行都可以点击;默认只展示结构化字段,原始 JSON 需显式点击按钮。"}));let P=uO(y),e=lO(y),uu=If(P.config),Ku=If(P.progress||e.progress),s=If(P.data),Nu=If(P.metrics||s.metrics||Ku.trainingInfo?.evaluation_metrics),Eu=If(s.trainingInfo||Ku.trainingInfo),Hu=If(s.trainingState),vu=If(P.model||s.model),ul=Array.isArray(vu.modelSummary)&&vu.modelSummary.length>0?vu.modelSummary:vu.computeLayers,mu=If(Eu.evaluation_metrics),Fl=y.kind==="job"?"训练任务详情":"Project 详情";return M("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},M("div",{className:"panel-head compact"},M("div",null,M("p",{className:"panel-eyebrow"},y.kind==="job"?"Job + Project Detail":"Project Library Detail"),M(nl,{title:Fl}),M("code",null,P.projectPath||e.projectPath||y.title)),M("div",{className:"panel-actions"},M(v1,{title:`MET ${Fl}`,data:y.data,onOpen:l,testId:"raw-met-detail"}))),y.kind==="job"?_u("任务状态",[{label:"Job ID",value:e.id},{label:"状态",value:kQ(e.status)},{label:"GPU",value:e.gpuName},{label:"Exit Code",value:e.exitCode},{label:"耗时",value:bQ(e)},{label:"训练速度",value:lc(vQ({...e,progress:Ku}))}]):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:`${Ku.currentEpoch??Hu.current_epoch??Hu.completed_epoch??"--"} / ${Ku.epochTarget??uu.epoch_train??"--"}`},{label:"Progress",value:vt(Ku.progressPercent)},{label:"Last Loss",value:Ku.lastLoss??Hu.loss},{label:"Last Val Loss",value:Ku.lastValLoss??Hu.val_loss},{label:"Min Loss",value:Eu.min_loss??Hu.min_loss},{label:"Min Val Loss",value:Eu.min_val_loss??Hu.min_val_loss},{label:"Log Lines",value:Ku.logLineCount},{label:"ETA",value:_2(Ku.etaSeconds??Hu.remaining_time)},{label:"训练速度",value:lc(Ku.epochPerHour??Hu.smoothed_speed)},{label:"Training Alive",value:Hu.training_alive}]),_u("模型参数",[{label:"Model Type",value:vu.modelType??uu.use_model},{label:"Total Params",value:vu.totalParams,hint:vu.totalParams===null||vu.totalParams===void 0?"未上报":"data/model_info.json"},{label:"Trainable",value:vu.trainableParams},{label:"Non-trainable",value:vu.nonTrainableParams},{label:"Compute Cost",value:vu.computeCost},{label:"Estimate Status",value:vu.estimateStatus},{label:"Unsupported Layers",value:vu.unsupportedLayerCount}]),_u("指标",[{label:"train_loss",value:Nu.train_loss??mu.train_loss},{label:"val_loss",value:Nu.val_loss??mu.val_loss},{label:"train_mae",value:Nu.train_mae??mu.train_mae},{label:"val_mae",value:Nu.val_mae??mu.val_mae},{label:"train_afmae",value:Nu.train_afmae??mu.train_afmae},{label:"val_afmae",value:Nu.val_afmae??mu.val_afmae},{label:"freq_drift_hz",value:Nu.freq_drift_hz},{label:"sens_drift_percent",value:Nu.sens_drift_percent},{label:"linearity_percent",value:Nu.linearity_percent},{label:"weights_source",value:Nu.weights_source??mu.weights_source},{label:"lr min/mean/max",value:`${It(Eu.learning_rate_min)} / ${It(Eu.learning_rate_mean)} / ${It(Eu.learning_rate_max)}`}]),M("div",{className:"met-detail-section"},M("h3",null,"模型层"),$u(ul)),M("div",{className:"met-detail-section"},M("h3",null,"data/ 文件"),ju(s.files)),y.kind==="job"?M("div",{className:"met-detail-section"},M("h3",null,"日志尾部"),zu(If(y.data).logTail)):null)}return M("div",{className:"met-page","data-testid":"met-nonlinear-page"},M(t2,{title:"MET Nonlinear 训练编排",eyebrow:"D601 GPU 用户服务",loading:n.loading||n.actionBusy,actions:M("div",{className:"panel-actions"},M("button",{type:"button",className:"ghost-btn",onClick:j,disabled:n.loading,"data-testid":"met-refresh-button"},n.loading?"刷新中":"刷新"),M(v1,{title:"MET Nonlinear 用户服务",data:r,onOpen:l,testId:"raw-met-service"}))},M("div",{className:"findjob-hero"},M("div",null,M("div",{className:"node-version-line"},M(kt,{status:z.providerStatus==="online"?"online":"warn"},z.providerStatus||"unknown"),M("span",null,r.providerId),M("span",null,H.public?"公网暴露":"仅 UniDesk frontend 代理访问")),M("p",{className:"muted paragraph"},r.description)),M("div",{className:"microservice-ref-card"},M("span",null,"Repo"),M("strong",null,Z.url||"--"),M("code",null,Z.commitId||"--")),M("div",{className:"microservice-ref-card"},M("span",null,"D601 Docker"),M("strong",null,`${H.nodeBindHost||"--"}:${H.nodePort||"--"}`),M("code",null,`${Z.composeFile||"--"} / ${Z.containerName||"--"}`))),M(il,{error:n.error,wide:!0}),_.actionMessage?M("div",{className:"met-action-log","data-testid":"met-action-message"},_.actionMessage):null),M("div",{className:"met-grid"},M(t2,{title:"核心状态",eyebrow:n.refreshedAt?`Updated ${tl(n.refreshedAt)}`:"Queue + GPU",loading:n.loading},M("div",{className:"metric-grid"},M(Hn,{label:"Staged",value:E.staged??0,hint:"加入队列未开始",tone:Number(E.staged||0)>0?"warn":""}),M(Hn,{label:"Queued",value:E.queued??0,hint:"排队等待调度",tone:Number(E.queued||0)>0?"warn":""}),M(Hn,{label:"Running",value:E.running??0,hint:`max ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??"--"}`,tone:Number(E.running||0)>0?"ok":""}),M(Hn,{label:"Succeeded",value:E.succeeded??0,hint:"已完成"}),M(Hn,{label:"Failed",value:E.failed??0,hint:"需要诊断",tone:Number(E.failed||0)>0?"warn":""}),M(Hn,{label:"2080Ti Free",value:h?vt(Number(h.freeRatio)*100):"--",hint:h?`${h.memoryFreeMiB}/${h.memoryTotalMiB} MiB`:"等待 GPU 上报"}),M(Hn,{label:"ML Image",value:V.present?"READY":"MISSING",hint:V.image||"met-nonlinear-ml:tf26",tone:V.present?"ok":"warn"}),M(Hn,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /health"}))),M(t2,{title:"队列控制",eyebrow:"Downloader-like staging",loading:n.actionBusy},M("div",{className:"met-control-strip"},M("label",null,"最大并发",M("input",{type:"number",min:1,max:16,value:_.maxConcurrency,"data-testid":"met-max-concurrency-input",onChange:(P)=>A({maxConcurrency:P.target.value})})),M("label",null,"目标 GPU",M("input",{value:_.targetGpuName,"data-testid":"met-target-gpu-input",onChange:(P)=>A({targetGpuName:P.target.value})})),M("button",{type:"button",className:"ghost-btn",onClick:J,disabled:n.actionBusy,"data-testid":"met-save-settings-button"},"保存设置"),M("button",{type:"button",className:"primary-btn",onClick:U,disabled:n.actionBusy||Number(E.staged||0)===0,"data-testid":"met-start-queue-button"},"启动队列")),M("p",{className:"muted paragraph"},"Project 先进入待启动队列,不会立即训练;点击启动队列后才切换为排队中,并由 D601 scheduler 按最大并发和 2080Ti 显存策略调度。")),M("section",{className:"panel met-workspace"},M("div",{className:"met-tabs",role:"tablist"},k.map((P)=>M("button",{key:P.id,type:"button",className:_.activeTab===P.id?"active":"",onClick:()=>A({activeTab:P.id}),"data-testid":`met-tab-${P.id}`},`${P.label} ${P.count}`))),M("div",{className:"panel-body"},_.activeTab==="projects"?M("div",{className:"met-form-grid","data-testid":"met-projects-pane"},M("div",{className:"met-fork-card"},M("h3",null,"Fork Project"),M("label",null,"源 Project",M("select",{value:m,"data-testid":"met-source-project-select",onChange:(P)=>A({sourceProject:P.target.value})},p.map((P)=>M("option",{key:P.projectPath,value:P.projectPath},`${P.projectPath} · ${P.useModel||"model?"}`)))),M("label",null,"Fork 数量",M("input",{type:"number",min:1,max:100,value:_.forkCount,"data-testid":"met-fork-count-input",onChange:(P)=>A({forkCount:P.target.value})})),M("label",null,"训练轮数",M("input",{type:"number",min:1,max:1e5,value:_.forkEpochs,"data-testid":"met-fork-epochs-input",onChange:(P)=>A({forkEpochs:P.target.value})})),M("label",null,"目标前缀",M("input",{value:_.forkPrefix,"data-testid":"met-fork-prefix-input",onChange:(P)=>A({forkPrefix:P.target.value})})),M("button",{type:"button",className:"primary-btn",onClick:L,disabled:n.actionBusy||!m,"data-testid":"met-fork-button"},"Fork Project"),M("p",{className:"muted paragraph"},"Fork 只创建新 Project 并自动勾选,不会直接训练;需要在右侧确认后加入待启动队列。")),M("div",{className:"met-project-list"},M("div",{className:"panel-head compact"},M("div",null,M("p",{className:"panel-eyebrow"},`Existing Projects · ${(n.projects?.roots||[]).map((P)=>`${P.root} ${P.count}`).join(" / ")}`),M(nl,{title:"选择已有 Project",loading:n.loading||n.actionBusy})),M("button",{type:"button",className:"ghost-btn",onClick:w,disabled:n.actionBusy||Q().length===0,"data-testid":"met-stage-selected-button"},`加入待启动队列 (${Q().length})`)),p.length===0?M(p0,{title:"暂无 project",text:"等待 D601 返回 /api/projects"}):M("div",{className:"met-project-table","data-testid":"met-project-tree"},M("div",{className:"met-tree-header"},M("span",null,"文件树 Project"),M("span",null,"Model"),M("span",null,"Epochs"),M("span",null,"Progress"),M("span",null,"速度")),O.children.map((P)=>x(P)))),Wu()):null,_.activeTab==="current"?M("div",{"data-testid":"met-current-pane"},b(),I(X,"current"),Wu(),M("div",{className:"panel-actions inline-actions"},M(v1,{title:"MET Queue",data:n.queue,onOpen:l,testId:"raw-met-queue"}))):null,_.activeTab==="completed"?M("div",{"data-testid":"met-completed-pane"},I(v.length>0?v:Y.filter((P)=>P.status==="succeeded"),"completed"),Wu()):null,_.activeTab==="failed"?M("div",{"data-testid":"met-failed-pane"},I(T.length>0?T:Y.filter((P)=>["failed","canceled"].includes(P.status)),"failed"),Wu(),M("div",{className:"panel-actions inline-actions"},M(v1,{title:"MET History",data:n.history,onOpen:l,testId:"raw-met-history"}))):null,_.activeTab==="gpu"?M("div",{className:"met-gpu-pane","data-testid":"met-gpu-pane"},D.length===0?M(p0,{title:"暂无 GPU 上报",text:"等待 D601 met-nonlinear-ts 或 ML image 提供 nvidia-smi 数据"}):M("div",{className:"table-wrap"},M("table",null,M("thead",null,M("tr",null,M("th",null,"Index"),M("th",null,"Name"),M("th",null,"Free"),M("th",null,"Policy"))),M("tbody",null,D.map((P)=>M("tr",{key:P.index},M("td",null,P.index),M("td",null,P.name),M("td",null,`${P.memoryFreeMiB} / ${P.memoryTotalMiB} MiB`,M("div",{className:"met-progress"},M("span",{style:{width:vt(Number(P.freeRatio)*100)}}))),M("td",null,String(P.name||"").includes("2080")?"target 2080Ti, <20% 限制并发":"non-target")))))),M("div",{className:"panel-actions inline-actions"},M(v1,{title:"MET Images",data:n.images,onOpen:l,testId:"raw-met-images"}))):null))))}var ic=[{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:"v3sctl",label:"V3S Control"},{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:"安全边界"}]}],st=Object.fromEntries(ic.map((u)=>[u.id,u.tabs[0]?.id??""]));function fO(u){let l=String(u||"").trim();if(!l)return"";try{return decodeURIComponent(l)}catch{return l}}function nc(u){let l=String(u||"/"),[f]=l.split(/[?#]/u,1);if(f==="/")return"/";let n=`/${f.split("/").map(fO).filter(Boolean).join("/")}`;return n.endsWith("/")?n:`${n}/`}function rO(u){let l=2166136261;for(let f of u)l^=f.charCodeAt(0),l=Math.imul(l,16777619);return Math.abs(l>>>0).toString(36)}function c2(u){return String(u||"").normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"")}function sQ(u){return String(u||"").trim().toLowerCase().replace(/[\s/\\?#%]+/gu,"-").replace(/-+/gu,"-").replace(/^-+|-+$/gu,"")}function aQ(u){let l=c2(u.routeSegment||"")||sQ(u.routeSegment||"");if(l)return l;let f=c2(u.id||"");if(f)return f;let r=c2(u.label||"")||sQ(u.label||"");if(r)return r;return`route-${rO(JSON.stringify(u))}`}function A2(u,l){return`${u}:${l}`}function oQ(u){let l=u.map((_)=>{let c=aQ(_);return{..._,routeSegment:c,tabs:_.tabs.map((A)=>({...A,routeSegment:aQ(A)}))}}),f={},r={},n={},i=l.map((_)=>{let c=_.tabs[0]?.id??"";n[_.id]=c;let A=_.tabs.map((J)=>{let Q=`/${_.routeSegment}/${J.routeSegment}/`,w=[Q],L={moduleId:_.id,tabId:J.id};for(let U of w)f[nc(U)]=L;return r[A2(_.id,J.id)]=Q,{...J,canonicalPath:Q,aliases:w}}),j=`/${_.routeSegment}/`,F={moduleId:_.id,tabId:c};return f[nc(j)]=F,{..._,routeSegment:_.routeSegment,canonicalPath:j,tabs:A}}),y=i[0],t={moduleId:y?.id||"",tabId:y?.tabs[0]?.id||""};return f["/"]=t,{modules:i,moduleById:Object.fromEntries(i.map((_)=>[_.id,_])),defaultActiveTabs:n,routeMap:f,canonicalPathByTarget:r,fallbackTarget:t}}function j2(u,l){return u.routeMap[nc(l)]||u.fallbackTarget}function yc(u,l,f){return u.canonicalPathByTarget[A2(l,f)]||u.canonicalPathByTarget[A2(u.fallbackTarget.moduleId,u.fallbackTarget.tabId)]||"/"}function dQ(u,l){let f=u.routeMap[nc(l)];if(!f)return null;return yc(u,f.moduleId,f.tabId)}var cc=Pu(Jl(),1);var iu=cc.default.createElement,{useEffect:eQ,useMemo:nO}=cc.default,F2=cc.default.useState;function $c({status:u,children:l,title:f}){let r=String(u||"unknown").toLowerCase();return iu("span",{className:`status-badge ${r}`,title:f},l||u||"unknown")}function at({label:u,value:l,hint:f,tone:r}){return iu("article",{className:`metric-card ${r||""}`},iu("div",{className:"metric-label"},u),iu("div",{className:"metric-value"},l),iu("div",{className:"metric-hint"},f))}function tc({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){return iu("section",{className:`panel ${n||""}`},iu("div",{className:"panel-head"},iu("div",null,l?iu("p",{className:"panel-eyebrow"},l):null,iu(nl,{title:u,loading:i})),f?iu("div",{className:"panel-actions"},f):null),iu("div",{className:"panel-body"},r))}function ot({title:u,data:l,onOpen:f,testId:r}){return iu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>f?.(u,l)},"查看原始JSON")}function U2({title:u,text:l}){return iu("div",{className:"empty-state"},iu("strong",null,u),iu("span",null,l))}function iO(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function m0(u){return Array.isArray(u)?u:[]}function gf(u){let l=Number(u);return Number.isFinite(l)?l.toLocaleString("zh-CN"):"--"}function uN(u,l=140){if(u===null||u===void 0)return"--";let f=typeof u==="string"?u:JSON.stringify(u),r=String(f||"").replace(/\s+/gu," ").trim();return r.length>l?`${r.slice(0,l-1)}...`:r||"--"}function yO(u){return m0(u?.tags).map((l)=>String(l||"").trim()).filter(Boolean)}function Zi(u){let l=Number(u);return Number.isFinite(l)&&l>=0?Math.floor(l):0}function tO(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function _O(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function $O(u){return String(u||"").split(/[\s,]+/u).map((l)=>l.trim()).filter(Boolean).join(",")}function _c(u,l){return`${u}/microservices/oa-event-flow/proxy${l}`}function cO(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 AO(u){let l=String(u?.subjectKind||"trace"),f=String(u?.subjectId||u?.scopeId||"");return f?`${l}:${f}`:String(u?.scopeId||"--")}function jO({tags:u}){let l=yO({tags:u}).slice(0,6);return iu("div",{className:"oa-tag-rail"},l.length===0?iu("span",{className:"muted"},"--"):l.map((f)=>iu("code",{key:f},f)))}function FO({events:u,onRaw:l}){let f=[...m0(u)].reverse();return f.length===0?iu(U2,{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,f.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,gf(r?.sequence))),iu("td",null,iu($c,{status:cO(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(jO,{tags:r?.tags})),iu("td",null,iu("span",{className:"oa-payload-preview"},uN(r?.payload,180))),iu("td",null,qu(r?.createdAt)),iu("td",null,iu(ot,{title:`OA Event ${r?.sequence||""}`,data:r,onOpen:l,testId:`raw-oa-event-${r?.sequence||"unknown"}`})))}))))}function UO({stats:u,onRaw:l}){let f=m0(u);return f.length===0?iu(U2,{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,f.map((r)=>iu("tr",{key:r?.scopeId||`${r?.serviceId}-${r?.subjectId}`},iu("td",null,iu("strong",null,AO(r)),iu("code",null,r?.scopeId||"--")),iu("td",null,iu($c,{status:String(r?.serviceId||"unknown")==="code-queue"?"running":"queued"},r?.serviceId||"--")),iu("td",null,iu("strong",null,gf(Zi(r?.stepCount??r?.llmStepCount)))),iu("td",null,gf(Zi(r?.readCount))),iu("td",null,gf(Zi(r?.editCount))),iu("td",null,gf(Zi(r?.runCount))),iu("td",null,gf(Zi(r?.errorCount))),iu("td",null,iu("code",null,gf(Zi(r?.outputMaxSeq)))),iu("td",null,gf(Zi(r?.statsRevision))),iu("td",null,qu(r?.updatedAt)),iu("td",null,iu(ot,{title:`OA Trace Stats ${r?.scopeId||""}`,data:r,onOpen:l,testId:`raw-oa-stats-${String(r?.scopeId||"unknown").replace(/[^a-zA-Z0-9_-]/gu,"_")}`})))))))}function lN({microservices:u,onRaw:l,apiBaseUrl:f="/api"}){let r=u.find((z)=>z.id==="oa-event-flow")||null,[n,i]=F2("service:code-queue"),[y,t]=F2({loading:!1,error:"",health:null,diagnostics:null,events:[],stats:[],refreshedAt:null}),[_,c]=F2({status:"idle",message:"未连接",lastEventAt:""}),A=nO(()=>$O(n),[n]);async function j(){if(!r)return;t((z)=>({...z,loading:!0,error:""}));try{let z=A?`tags=${encodeURIComponent(A)}&`:"",[Z,H,E,D]=await Promise.all([Tu(`${f}/microservices/oa-event-flow/health`,{failureFields:[]}),Tu(_c(f,"/api/diagnostics")),Tu(_c(f,`/api/events?${z}limit=100`)),Tu(_c(f,`/api/stats/trace?${z}limit=100`))]);t({loading:!1,error:"",health:Z,diagnostics:H,events:m0(E?.events),stats:m0(D?.stats),refreshedAt:new Date})}catch(z){t((Z)=>({...Z,loading:!1,error:Ou(z,"OA Event Flow 加载失败")}))}}if(eQ(()=>{j()},[r?.id,r?.runtime?.providerStatus,A]),eQ(()=>{if(!r||typeof EventSource>"u")return;let z=A?`?tags=${encodeURIComponent(A)}`:"",Z=new EventSource(`${_c(f,"/api/events/stream")}${z}`,{withCredentials:!0});c({status:"running",message:"SSE connecting",lastEventAt:""});let H=(h)=>{c({status:"online",message:uN(h.data,120),lastEventAt:new Date().toISOString()})},E=(h)=>{try{let V=JSON.parse(String(h.data||"{}"));c({status:"online",message:String(V?.type||h.type||"event"),lastEventAt:new Date().toISOString()}),t((S)=>{let p=[...m0(S.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"&&iO(V?.payload?.stats)?[V.payload.stats,...m0(S.stats).filter((m)=>String(m?.scopeId||"")!==String(V.payload.stats.scopeId||""))].slice(0,100):S.stats;return{...S,events:p,stats:O}})}catch(V){c({status:"warn",message:Ou(V,"SSE 事件解析失败"),lastEventAt:new Date().toISOString()})}},D=()=>{c((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,f,A]),!r)return iu(U2,{title:"OA Event Flow 未登记",text:"请在 config.json 的 microservices 中登记 id=oa-event-flow"});let F=tO(r),J=_O(r),Q=y.diagnostics||{},w=y.health||{},L=Q.eventCount??w.eventCount,U=Q.traceStatsCount??w.traceStatsCount,N=Q.latestSequence??w.latestSequence,q=Q.pipelineBridge||w.pipelineBridge||{},W=m0(Q.eventTypes).slice(0,8);return iu("div",{className:"oa-event-flow-page","data-testid":"oa-event-flow-page"},iu(tc,{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(ot,{title:"OA Event Flow Service",data:r,onOpen:l,testId:"raw-oa-event-flow-service"}))},iu("div",{className:"oa-flow-hero"},iu("div",null,iu("div",{className:"node-version-line"},iu($c,{status:w?.ok||F.providerStatus==="online"?"online":"warn"},w?.ok?"HEALTH OK":F.providerStatus||"unknown"),iu($c,{status:_.status},_.status.toUpperCase()),iu("span",null,J.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?tl(new Date(_.lastEventAt)):"waiting"))),iu(il,{error:y.error,wide:!0})),iu("div",{className:"oa-flow-metrics"},iu(at,{label:"事件总量",value:gf(L),hint:`latest seq ${gf(N)}`,tone:"ok"}),iu(at,{label:"Trace Stats",value:gf(U),hint:"oa_trace_stats 投影"}),iu(at,{label:"SSE Clients",value:gf(w?.sseClientCount??m0(Q.sseClients).length),hint:_.message||"tag subscription"}),iu(at,{label:"Pipeline Bridge",value:q?.enabled?gf(q?.insertedCount):"OFF",hint:q?.lastError||q?.lastFinishedAt||`${q?.mode||"snapshot"} service:pipeline`}),iu(at,{label:"DB",value:w?.databaseReady||Q.databaseReady?"READY":"WAIT",hint:w?.databaseLastError||Q.databaseLastError||"PostgreSQL persisted"})),iu(tc,{title:"标签订阅",eyebrow:y.refreshedAt?`Updated ${tl(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,A||"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} ${gf(z.count)}`)))),iu("div",{className:"oa-flow-grid"},iu(tc,{title:"事件表",eyebrow:"oa_events persisted log",className:"oa-flow-wide",loading:y.loading,actions:iu(ot,{title:"OA Event Query",data:{events:y.events,diagnostics:Q},onOpen:l,testId:"raw-oa-events"})},iu(FO,{events:y.events,onRaw:l})),iu(tc,{title:"统计中心",eyebrow:"oa_trace_stats read model",className:"oa-flow-wide",loading:y.loading,actions:iu(ot,{title:"OA Trace Stats",data:y.stats,onOpen:l,testId:"raw-oa-trace-stats"})},iu(UO,{stats:y.stats,onRaw:l}))))}var hn=Pu(Jl(),1);var ru=Pu(iN(),1),yu=Pu(Jl(),1);function Sl(u){if(typeof u==="string"||typeof u==="number")return""+u;let l="";if(Array.isArray(u)){for(let f=0,r;f{}};function tN(){for(var u=0,l=arguments.length,f={},r;u=0)r=f.slice(n+1),f=f.slice(0,n);if(f&&!l.hasOwnProperty(f))throw Error("unknown type: "+f);return{type:f,name:r}})}jc.prototype=tN.prototype={constructor:jc,on:function(u,l){var f=this._,r=KO(u+"",f),n,i=-1,y=r.length;if(arguments.length<2){while(++i0)for(var f=Array(n),r=0,n,i;r=0&&(l=u.slice(0,f))!=="xmlns")u=u.slice(f+1);return J2.hasOwnProperty(l)?{space:J2[l],local:u}:u}function Q2(u){let l;while(l=u.sourceEvent)u=l;return u}function Gf(u,l){if(u=Q2(u),l===void 0)l=u.currentTarget;if(l){var f=l.ownerSVGElement||l;if(f.createSVGPoint){var r=f.createSVGPoint();return r.x=u.clientX,r.y=u.clientY,r=r.matrixTransform(l.getScreenCTM().inverse()),[r.x,r.y]}if(l.getBoundingClientRect){var n=l.getBoundingClientRect();return[u.clientX-n.left-l.clientLeft,u.clientY-n.top-l.clientTop]}}return[u.pageX,u.pageY]}function zO(){}function Bn(u){return u==null?zO:function(){return this.querySelector(u)}}function N2(u){if(typeof u!=="function")u=Bn(u);for(var l=this._groups,f=l.length,r=Array(f),n=0;n=q)q=N+1;while(!(z=L[q])&&++q=0;)if(y=r[n]){if(i&&y.compareDocumentPosition(i)^4)i.parentNode.insertBefore(y,i);i=y}return this}function B2(u){if(!u)u=mO;function l(j,F){return j&&F?u(j.__data__,F.__data__):!j-!F}for(var f=this._groups,r=f.length,n=Array(r),i=0;il?1:u>=l?0:NaN}function V2(){var u=arguments[0];return arguments[0]=this,u.apply(null,arguments),this}function D2(){return Array.from(this)}function X2(){for(var u=this._groups,l=0,f=u.length;l1?this.each((l==null?bO:typeof l==="function"?kO:vO)(u,l,f==null?"":f)):Vn(this.node(),u)}function Vn(u,l){return u.style.getPropertyValue(l)||u_(u).getComputedStyle(u,null).getPropertyValue(l)}function IO(u){return function(){delete this[u]}}function gO(u,l){return function(){this[u]=l}}function sO(u,l){return function(){var f=l.apply(this,arguments);if(f==null)delete this[u];else this[u]=f}}function C2(u,l){return arguments.length>1?this.each((l==null?IO:typeof l==="function"?sO:gO)(u,l)):this.node()[u]}function _N(u){return u.trim().split(/^|\s+/)}function M2(u){return u.classList||new $N(u)}function $N(u){this._node=u,this._names=_N(u.getAttribute("class")||"")}$N.prototype={add:function(u){var l=this._names.indexOf(u);if(l<0)this._names.push(u),this._node.setAttribute("class",this._names.join(" "))},remove:function(u){var l=this._names.indexOf(u);if(l>=0)this._names.splice(l,1),this._node.setAttribute("class",this._names.join(" "))},contains:function(u){return this._names.indexOf(u)>=0}};function cN(u,l){var f=M2(u),r=-1,n=l.length;while(++r=0)f=l.slice(r+1),l=l.slice(0,r);return{type:l,name:f}})}function JH(u){return function(){var l=this.__on;if(!l)return;for(var f=0,r=-1,n=l.length,i;f()=>u;function n_(u,{sourceEvent:l,subject:f,target:r,identifier:n,active:i,x:y,y:t,dx:_,dy:c,dispatch:A}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:l,enumerable:!0,configurable:!0},subject:{value:f,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:t,enumerable:!0,configurable:!0},dx:{value:_,enumerable:!0,configurable:!0},dy:{value:c,enumerable:!0,configurable:!0},_:{value:A}})}n_.prototype.on=function(){var u=this._.on.apply(this._,arguments);return u===this._?this:u};function ZH(u){return!u.ctrlKey&&!u.button}function OH(){return this.parentNode}function HH(u,l){return l==null?{x:u.x,y:u.y}:l}function BH(){return navigator.maxTouchPoints||"ontouchstart"in this}function i_(){var u=ZH,l=OH,f=HH,r=BH,n={},i=Oi("start","drag","end"),y=0,t,_,c,A,j=0;function F(W){W.on("mousedown.drag",J).filter(r).on("touchstart.drag",L).on("touchmove.drag",U,UN).on("touchend.drag touchcancel.drag",N).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function J(W,z){if(A||!u.call(this,W,z))return;var Z=q(this,l.call(this,W,z),W,z,"mouse");if(!Z)return;sl(W.view).on("mousemove.drag",Q,Hi).on("mouseup.drag",w,Hi),g1(W.view),Jc(W),c=!1,t=W.clientX,_=W.clientY,Z("start",W)}function Q(W){if(C0(W),!c){var z=W.clientX-t,Z=W.clientY-_;c=z*z+Z*Z>j}n.mouse("drag",W)}function w(W){sl(W.view).on("mousemove.drag mouseup.drag",null),f_(W.view,c),C0(W),n.mouse("end",W)}function L(W,z){if(!u.call(this,W,z))return;var Z=W.changedTouches,H=l.call(this,W,z),E=Z.length,D,h;for(D=0;D>8&15|l>>4&240,l>>4&15|l&240,(l&15)<<4|l&15,1):f===8?Qc(l>>24&255,l>>16&255,l>>8&255,(l&255)/255):f===4?Qc(l>>12&15|l>>8&240,l>>8&15|l>>4&240,l>>4&15|l&240,((l&15)<<4|l&15)/255):null):(l=DH.exec(u))?new sf(l[1],l[2],l[3],1):(l=XH.exec(u))?new sf(l[1]*255/100,l[2]*255/100,l[3]*255/100,1):(l=SH.exec(u))?Qc(l[1],l[2],l[3],l[4]):(l=YH.exec(u))?Qc(l[1]*255/100,l[2]*255/100,l[3]*255/100,l[4]):(l=pH.exec(u))?LN(l[1],l[2]/100,l[3]/100,1):(l=mH.exec(u))?LN(l[1],l[2]/100,l[3]/100,l[4]):JN.hasOwnProperty(u)?qN(JN[u]):u==="transparent"?new sf(NaN,NaN,NaN,0):null}function qN(u){return new sf(u>>16&255,u>>8&255,u&255,1)}function Qc(u,l,f,r){if(r<=0)u=l=f=NaN;return new sf(u,l,f,r)}function MH(u){if(!(u instanceof $_))u=kr(u);if(!u)return new sf;return u=u.rgb(),new sf(u.r,u.g,u.b,u.opacity)}function a1(u,l,f,r){return arguments.length===1?MH(u):new sf(u,l,f,r==null?1:r)}function sf(u,l,f,r){this.r=+u,this.g=+l,this.b=+f,this.opacity=+r}y_(sf,a1,l5($_,{brighter(u){return u=u==null?qc:Math.pow(qc,u),new sf(this.r*u,this.g*u,this.b*u,this.opacity)},darker(u){return u=u==null?t_:Math.pow(t_,u),new sf(this.r*u,this.g*u,this.b*u,this.opacity)},rgb(){return this},clamp(){return new sf(Vi(this.r),Vi(this.g),Vi(this.b),Wc(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:WN,formatHex:WN,formatHex8:RH,formatRgb:wN,toString:wN}));function WN(){return`#${Bi(this.r)}${Bi(this.g)}${Bi(this.b)}`}function RH(){return`#${Bi(this.r)}${Bi(this.g)}${Bi(this.b)}${Bi((isNaN(this.opacity)?1:this.opacity)*255)}`}function wN(){let u=Wc(this.opacity);return`${u===1?"rgb(":"rgba("}${Vi(this.r)}, ${Vi(this.g)}, ${Vi(this.b)}${u===1?")":`, ${u})`}`}function Wc(u){return isNaN(u)?1:Math.max(0,Math.min(1,u))}function Vi(u){return Math.max(0,Math.min(255,Math.round(u)||0))}function Bi(u){return u=Vi(u),(u<16?"0":"")+u.toString(16)}function LN(u,l,f,r){if(r<=0)u=l=f=NaN;else if(f<=0||f>=1)u=l=NaN;else if(l<=0)u=NaN;return new vr(u,l,f,r)}function GN(u){if(u instanceof vr)return new vr(u.h,u.s,u.l,u.opacity);if(!(u instanceof $_))u=kr(u);if(!u)return new vr;if(u instanceof vr)return u;u=u.rgb();var l=u.r/255,f=u.g/255,r=u.b/255,n=Math.min(l,f,r),i=Math.max(l,f,r),y=NaN,t=i-n,_=(i+n)/2;if(t){if(l===i)y=(f-r)/t+(f0&&_<1?0:y;return new vr(y,t,_,u.opacity)}function zN(u,l,f,r){return arguments.length===1?GN(u):new vr(u,l,f,r==null?1:r)}function vr(u,l,f,r){this.h=+u,this.s=+l,this.l=+f,this.opacity=+r}y_(vr,zN,l5($_,{brighter(u){return u=u==null?qc:Math.pow(qc,u),new vr(this.h,this.s,this.l*u,this.opacity)},darker(u){return u=u==null?t_:Math.pow(t_,u),new vr(this.h,this.s,this.l*u,this.opacity)},rgb(){var u=this.h%360+(this.h<0)*360,l=isNaN(u)||isNaN(this.s)?0:this.s,f=this.l,r=f+(f<0.5?f:1-f)*l,n=2*f-r;return new sf(f5(u>=240?u-240:u+120,n,r),f5(u,n,r),f5(u<120?u+240:u-120,n,r),this.opacity)},clamp(){return new vr(KN(this.h),Nc(this.s),Nc(this.l),Wc(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=Wc(this.opacity);return`${u===1?"hsl(":"hsla("}${KN(this.h)}, ${Nc(this.s)*100}%, ${Nc(this.l)*100}%${u===1?")":`, ${u})`}`}}));function KN(u){return u=(u||0)%360,u<0?u+360:u}function Nc(u){return Math.max(0,Math.min(1,u||0))}function f5(u,l,f){return(u<60?l+(f-l)*u/60:u<180?f:u<240?l+(f-l)*(240-u)/60:l)*255}function r5(u,l,f,r,n){var i=u*u,y=i*u;return((1-3*u+3*i-y)*l+(4-6*i+3*y)*f+(1+3*u+3*i-3*y)*r+y*n)/6}function n5(u){var l=u.length-1;return function(f){var r=f<=0?f=0:f>=1?(f=1,l-1):Math.floor(f*l),n=u[r],i=u[r+1],y=r>0?u[r-1]:2*n-i,t=r()=>u;function hH(u,l){return function(f){return u+f*l}}function bH(u,l,f){return u=Math.pow(u,f),l=Math.pow(l,f)-u,f=1/f,function(r){return Math.pow(u+r*l,f)}}function TN(u){return(u=+u)===1?Lc:function(l,f){return f-l?bH(l,f,u):c_(isNaN(l)?f:l)}}function Lc(u,l){var f=l-u;return f?hH(u,f):c_(isNaN(u)?l:u)}var Di=function u(l){var f=TN(l);function r(n,i){var y=f((n=a1(n)).r,(i=a1(i)).r),t=f(n.g,i.g),_=f(n.b,i.b),c=Lc(n.opacity,i.opacity);return function(A){return n.r=y(A),n.g=t(A),n.b=_(A),n.opacity=c(A),n+""}}return r.gamma=u,r}(1);function EN(u){return function(l){var f=l.length,r=Array(f),n=Array(f),i=Array(f),y,t;for(y=0;yf)if(i=l.slice(f,i),t[y])t[y]+=i;else t[++y]=i;if((r=r[0])===(n=n[0]))if(t[y])t[y]+=n;else t[++y]=n;else t[++y]=null,_.push({i:y,x:zf(r,n)});f=$5.lastIndex}if(f180)A+=360;else if(A-c>180)c+=360;F.push({i:j.push(n(j)+"rotate(",null,r)-2,x:zf(c,A)})}else if(A)j.push(n(j)+"rotate("+A+r)}function t(c,A,j,F){if(c!==A)F.push({i:j.push(n(j)+"skewX(",null,r)-2,x:zf(c,A)});else if(A)j.push(n(j)+"skewX("+A+r)}function _(c,A,j,F,J,Q){if(c!==j||A!==F){var w=J.push(n(J)+"scale(",null,",",null,")");Q.push({i:w-4,x:zf(c,j)},{i:w-2,x:zf(A,F)})}else if(j!==1||F!==1)J.push(n(J)+"scale("+j+","+F+")")}return function(c,A){var j=[],F=[];return c=u(c),A=u(A),i(c.translateX,c.translateY,A.translateX,A.translateY,j,F),y(c.rotate,A.rotate,j,F),t(c.skewX,A.skewX,j,F),_(c.scaleX,c.scaleY,A.scaleX,A.scaleY,j,F),c=A=null,function(J){var Q=-1,w=F.length,L;while(++Q=0)u._call.call(void 0,l);u=u._next}--d1}function mN(){Si=(Ec=U_.now())+Zc,d1=j_=0;try{MN()}finally{d1=0,jB(),Si=0}}function AB(){var u=U_.now(),l=u-Ec;if(l>PN)Zc-=l,Ec=u}function jB(){var u,l=Tc,f,r=1/0;while(l)if(l._call){if(r>l._time)r=l._time;u=l,l=l._next}else f=l._next,l._next=null,l=u?u._next=f:Tc=f;F_=u,F5(r)}function F5(u){if(d1)return;if(j_)j_=clearTimeout(j_);var l=u-Si;if(l>24){if(u<1/0)j_=setTimeout(mN,u-U_.now()-Zc);if(A_)A_=clearInterval(A_)}else{if(!A_)Ec=U_.now(),A_=setInterval(AB,PN);d1=1,CN(mN)}}function N_(u,l,f){var r=new J_;return l=l==null?0:+l,r.restart((n)=>{r.stop(),u(n+l)},l,f),r}var UB=Oi("start","end","cancel","interrupt"),JB=[],hN=0,RN=1,Bc=2,Hc=3,xN=4,Vc=5,q_=6;function M0(u,l,f,r,n,i){var y=u.__transition;if(!y)u.__transition={};else if(f in y)return;QB(u,f,{name:l,index:r,group:n,on:UB,tween:JB,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:hN})}function W_(u,l){var f=al(u,l);if(f.state>hN)throw Error("too late; already scheduled");return f}function Ff(u,l){var f=al(u,l);if(f.state>Hc)throw Error("too late; already running");return f}function al(u,l){var f=u.__transition;if(!f||!(f=f[l]))throw Error("transition not found");return f}function QB(u,l,f){var r=u.__transition,n;r[l]=f,f.timer=Oc(i,0,f.time);function i(c){if(f.state=RN,f.timer.restart(y,f.delay,f.time),f.delay<=c)y(c-f.delay)}function y(c){var A,j,F,J;if(f.state!==RN)return _();for(A in r){if(J=r[A],J.name!==f.name)continue;if(J.state===Hc)return N_(y);if(J.state===xN)J.state=q_,J.timer.stop(),J.on.call("interrupt",u,u.__data__,J.index,J.group),delete r[A];else if(+ABc&&r.state=0)l=l.slice(0,f);return!l||l==="start"})}function pB(u,l,f){var r,n,i=YB(l)?W_:Ff;return function(){var y=i(this,u),t=y.on;if(t!==r)(n=(r=t).copy()).on(l,f);y.on=n}}function z5(u,l){var f=this._id;return arguments.length<2?al(this.node(),f).on.on(u):this.each(pB(f,u,l))}function mB(u){return function(){var l=this.parentNode;for(var f in this.__transition)if(+f!==u)return;if(l)l.removeChild(this)}}function T5(){return this.on("end.remove",mB(this._id))}function E5(u){var l=this._name,f=this._id;if(typeof u!=="function")u=Bn(u);for(var r=this._groups,n=r.length,i=Array(n),y=0;y()=>u;function p5(u,{sourceEvent:l,target:f,transform:r,dispatch:n}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:l,enumerable:!0,configurable:!0},target:{value:f,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:n}})}function Ir(u,l,f){this.k=u,this.x=l,this.y=f}Ir.prototype={constructor:Ir,scale:function(u){return u===1?this:new Ir(this.k*u,this.x,this.y)},translate:function(u,l){return u===0&l===0?this:new Ir(this.k,this.x+this.k*u,this.y+this.k*l)},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 Yi=new Ir(1,0,0);K_.prototype=Ir.prototype;function K_(u){while(!u.__zoom)if(!(u=u.parentNode))return Yi;return u.__zoom}function xc(u){u.stopImmediatePropagation()}function pi(u){u.preventDefault(),u.stopImmediatePropagation()}function eB(u){return(!u.ctrlKey||u.type==="wheel")&&!u.button}function uV(){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 kN(){return this.__zoom||Yi}function lV(u){return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*(u.ctrlKey?10:1)}function fV(){return navigator.maxTouchPoints||"ontouchstart"in this}function rV(u,l,f){var r=u.invertX(l[0][0])-f[0][0],n=u.invertX(l[1][0])-f[1][0],i=u.invertY(l[0][1])-f[0][1],y=u.invertY(l[1][1])-f[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 G_(){var u=eB,l=uV,f=rV,r=lV,n=fV,i=[0,1/0],y=[[-1/0,-1/0],[1/0,1/0]],t=250,_=Xi,c=Oi("start","zoom","end"),A,j,F,J=500,Q=150,w=0,L=10;function U(O){O.property("__zoom",kN).on("wheel.zoom",E,{passive:!1}).on("mousedown.zoom",D).on("dblclick.zoom",h).filter(n).on("touchstart.zoom",V).on("touchmove.zoom",S).on("touchend.zoom touchcancel.zoom",p).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}U.transform=function(O,m,X,v){var T=O.selection?O.selection():O;if(T.property("__zoom",kN),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()})},U.scaleBy=function(O,m,X,v){U.scaleTo(O,function(){var T=this.__zoom.k,Y=typeof m==="function"?m.apply(this,arguments):m;return T*Y},X,v)},U.scaleTo=function(O,m,X,v){U.transform(O,function(){var T=l.apply(this,arguments),Y=this.__zoom,k=X==null?W(T):typeof X==="function"?X.apply(this,arguments):X,I=Y.invert(k),b=typeof m==="function"?m.apply(this,arguments):m;return f(q(N(Y,b),k,I),T,y)},X,v)},U.translateBy=function(O,m,X,v){U.transform(O,function(){return f(this.__zoom.translate(typeof m==="function"?m.apply(this,arguments):m,typeof X==="function"?X.apply(this,arguments):X),l.apply(this,arguments),y)},null,v)},U.translateTo=function(O,m,X,v,T){U.transform(O,function(){var Y=l.apply(this,arguments),k=this.__zoom,I=v==null?W(Y):typeof v==="function"?v.apply(this,arguments):v;return f(Yi.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),Y,y)},v,T)};function N(O,m){return m=Math.max(i[0],Math.min(i[1],m)),m===O.k?O:new Ir(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 Ir(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,Y=arguments,k=Z(T,Y).event(v),I=l.apply(T,Y),b=X==null?W(I):typeof X==="function"?X.apply(T,Y):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,Y):m,lu=_(g.invert(b).concat(o/g.k),x.invert(b).concat(o/x.k));return function(_u){if(_u===1)_u=x;else{var $u=lu(_u),ju=o/$u[2];_u=new Ir(ju,b[0]-$u[0]*ju,b[1]-$u[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=l.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=sl(this.that).datum();c.call(O,this.that,new p5(O,{sourceEvent:this.sourceEvent,target:U,type:O,transform:this.that.__zoom,dispatch:c}),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)))),Y=Gf(O);if(X.wheel){if(X.mouse[0][0]!==Y[0]||X.mouse[0][1]!==Y[1])X.mouse[1]=v.invert(X.mouse[0]=Y);clearTimeout(X.wheel)}else if(v.k===T)return;else X.mouse=[Y,v.invert(Y)],Dn(this),X.start();pi(O),X.wheel=setTimeout(k,Q),X.zoom("mouse",f(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=sl(O.view).on("mousemove.zoom",b,!0).on("mouseup.zoom",o,!0),Y=Gf(O,X),k=O.clientX,I=O.clientY;g1(O.view),xc(O),v.mouse=[Y,this.__zoom.invert(Y)],Dn(this),v.start();function b(g){if(pi(g),!v.moved){var x=g.clientX-k,lu=g.clientY-I;v.moved=x*x+lu*lu>w}v.event(g).zoom("mouse",f(q(v.that.__zoom,v.mouse[0]=Gf(g,X),v.mouse[1]),v.extent,y))}function o(g){T.on("mousemove.zoom mouseup.zoom",null),f_(g.view,v.moved),pi(g),v.event(g).end()}}function h(O,...m){if(!u.apply(this,arguments))return;var X=this.__zoom,v=Gf(O.changedTouches?O.changedTouches[0]:O,this),T=X.invert(v),Y=X.k*(O.shiftKey?0.5:2),k=f(q(N(X,Y),v,T),l.apply(this,m),y);if(pi(O),t>0)sl(this).transition().duration(t).call(z,k,v,O);else sl(this).call(U.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),Y,k,I,b;xc(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:l,sourceHandle:f,targetHandle:r})=>`Couldn't create edge for ${u} handle id: "${u==="source"?f:r}", edge id: ${l}.`,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."},ny=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],R5=["Enter"," ","Escape"],x5={"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:l,y:f})=>`Moved selected node ${u}. New position, x: ${l}, y: ${f}`,"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 x0;(function(u){u.Free="free",u.Vertical="vertical",u.Horizontal="horizontal"})(x0||(x0={}));var mi;(function(u){u.Partial="partial",u.Full="full"})(mi||(mi={}));var h5={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null},c0;(function(u){u.Bezier="default",u.Straight="straight",u.Step="step",u.SmoothStep="smoothstep",u.SimpleBezier="simplebezier"})(c0||(c0={}));var pn;(function(u){u.Arrow="arrow",u.ArrowClosed="arrowclosed"})(pn||(pn={}));var Lu;(function(u){u.Left="left",u.Top="top",u.Right="right",u.Bottom="bottom"})(Lu||(Lu={}));var IN={[Lu.Left]:Lu.Right,[Lu.Right]:Lu.Left,[Lu.Top]:Lu.Bottom,[Lu.Bottom]:Lu.Top};function b5(u){return u===null?null:u?"valid":"invalid"}var v5=(u)=>("id"in u)&&("source"in u)&&("target"in u),yq=(u)=>("id"in u)&&("position"in u)&&!("source"in u)&&!("target"in u),k5=(u)=>("id"in u)&&("internals"in u)&&!("source"in u)&&!("target"in u);var E_=(u,l=[0,0])=>{let{width:f,height:r}=A0(u),n=u.origin??l,i=f*n[0],y=r*n[1];return{x:u.position.x-i,y:u.position.y-y}},I5=(u,l={nodeOrigin:[0,0]})=>{if(u.length===0)return{x:0,y:0,width:0,height:0};let f=u.reduce((r,n)=>{let i=typeof n==="string",y=!l.nodeLookup&&!i?n:void 0;if(l.nodeLookup)y=i?l.nodeLookup.get(n):!k5(n)?l.nodeLookup.get(n.id):n;let t=y?vc(y,l.nodeOrigin):{x:0,y:0,x2:0,y2:0};return Ic(r,t)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return gc(f)},iy=(u,l={})=>{let f={x:1/0,y:1/0,x2:-1/0,y2:-1/0},r=!1;return u.forEach((n)=>{if(l.filter===void 0||l.filter(n))f=Ic(f,vc(n)),r=!0}),r?gc(f):{x:0,y:0,width:0,height:0}},kc=(u,l,[f,r,n]=[0,0,1],i=!1,y=!1)=>{let t={..._y(l,[f,r,n]),width:l.width/n,height:l.height/n},_=[];for(let c of u.values()){let{measured:A,selectable:j=!0,hidden:F=!1}=c;if(y&&!j||F)continue;let J=A.width??c.width??c.initialWidth??null,Q=A.height??c.height??c.initialHeight??null,w=yy(t,Ci(c)),L=(J??0)*(Q??0),U=i&&w>0;if(!c.internals.handleBounds||U||w>=L||c.dragging)_.push(c)}return _},tq=(u,l)=>{let f=new Set;return u.forEach((r)=>{f.add(r.id)}),l.filter((r)=>f.has(r.source)||f.has(r.target))};function nV(u,l){let f=new Map,r=l?.nodes?new Set(l.nodes.map((n)=>n.id)):null;return u.forEach((n)=>{if(n.measured.width&&n.measured.height&&(l?.includeHiddenNodes||!n.hidden)&&(!r||r.has(n.id)))f.set(n.id,n)}),f}async function _q({nodes:u,width:l,height:f,panZoom:r,minZoom:n,maxZoom:i},y){if(u.size===0)return Promise.resolve(!0);let t=nV(u,y),_=iy(t),c=Z_(_,l,f,y?.minZoom??n,y?.maxZoom??i,y?.padding??0.1);return await r.setViewport(c,{duration:y?.duration,ease:y?.ease,interpolate:y?.interpolate}),Promise.resolve(!0)}function g5({nodeId:u,nextPosition:l,nodeLookup:f,nodeOrigin:r=[0,0],nodeExtent:n,onError:i}){let y=f.get(u),t=y.parentId?f.get(y.parentId):void 0,{x:_,y:c}=t?t.internals.positionAbsolute:{x:0,y:0},A=y.origin??r,j=y.extent||n;if(y.extent==="parent"&&!y.expandParent)if(!t)i?.("005",Ur.error005());else{let J=t.measured.width,Q=t.measured.height;if(J&&Q)j=[[_,c],[_+J,c+Q]]}else if(t&&ry(y.extent))j=[[y.extent[0][0]+_,y.extent[0][1]+c],[y.extent[1][0]+_,y.extent[1][1]+c]];let F=ry(j)?Pi(l,j,y.measured):l;if(y.measured.width===void 0||y.measured.height===void 0)i?.("015",Ur.error015());return{position:{x:F.x-_+(y.measured.width??0)*A[0],y:F.y-c+(y.measured.height??0)*A[1]},positionAbsolute:F}}async function $q({nodesToRemove:u=[],edgesToRemove:l=[],nodes:f,edges:r,onBeforeDelete:n}){let i=new Set(u.map((F)=>F.id)),y=[];for(let F of f){if(F.deletable===!1)continue;let J=i.has(F.id),Q=!J&&F.parentId&&y.find((w)=>w.id===F.parentId);if(J||Q)y.push(F)}let t=new Set(l.map((F)=>F.id)),_=r.filter((F)=>F.deletable!==!1),A=tq(y,_);for(let F of _)if(t.has(F.id)&&!A.find((Q)=>Q.id===F.id))A.push(F);if(!n)return{edges:A,nodes:y};let j=await n({nodes:y,edges:A});if(typeof j==="boolean")return j?{edges:A,nodes:y}:{edges:[],nodes:[]};return j}var fy=(u,l=0,f=1)=>Math.min(Math.max(u,l),f),Pi=(u={x:0,y:0},l,f)=>({x:fy(u.x,l[0][0],l[1][0]-(f?.width??0)),y:fy(u.y,l[0][1],l[1][1]-(f?.height??0))});function cq(u,l,f){let{width:r,height:n}=A0(f),{x:i,y}=f.internals.positionAbsolute;return Pi(u,[[i,y],[i+r,y+n]],l)}var gN=(u,l,f)=>{if(uf)return-fy(Math.abs(u-f),1,l)/l;return 0},Aq=(u,l,f=15,r=40)=>{let n=gN(u.x,r,l.width-r)*f,i=gN(u.y,r,l.height-r)*f;return[n,i]},Ic=(u,l)=>({x:Math.min(u.x,l.x),y:Math.min(u.y,l.y),x2:Math.max(u.x2,l.x2),y2:Math.max(u.y2,l.y2)}),M5=({x:u,y:l,width:f,height:r})=>({x:u,y:l,x2:u+f,y2:l+r}),gc=({x:u,y:l,x2:f,y2:r})=>({x:u,y:l,width:f-u,height:r-l}),Ci=(u,l=[0,0])=>{let{x:f,y:r}=k5(u)?u.internals.positionAbsolute:E_(u,l);return{x:f,y:r,width:u.measured?.width??u.width??u.initialWidth??0,height:u.measured?.height??u.height??u.initialHeight??0}},vc=(u,l=[0,0])=>{let{x:f,y:r}=k5(u)?u.internals.positionAbsolute:E_(u,l);return{x:f,y:r,x2:f+(u.measured?.width??u.width??u.initialWidth??0),y2:r+(u.measured?.height??u.height??u.initialHeight??0)}},s5=(u,l)=>gc(Ic(M5(u),M5(l))),yy=(u,l)=>{let f=Math.max(0,Math.min(u.x+u.width,l.x+l.width)-Math.max(u.x,l.x)),r=Math.max(0,Math.min(u.y+u.height,l.y+l.height)-Math.max(u.y,l.y));return Math.ceil(f*r)},a5=(u)=>Zr(u.width)&&Zr(u.height)&&Zr(u.x)&&Zr(u.y),Zr=(u)=>!isNaN(u)&&isFinite(u),o5=(u,l)=>{},ty=(u,l=[1,1])=>{return{x:l[0]*Math.round(u.x/l[0]),y:l[1]*Math.round(u.y/l[1])}},_y=({x:u,y:l},[f,r,n],i=!1,y=[1,1])=>{let t={x:(u-f)/n,y:(l-r)/n};return i?ty(t,y):t},T_=({x:u,y:l},[f,r,n])=>{return{x:u*n+f,y:l*n+r}};function uy(u,l){if(typeof u==="number")return Math.floor((l-l/(1+u))*0.5);if(typeof u==="string"&&u.endsWith("px")){let f=parseFloat(u);if(!Number.isNaN(f))return Math.floor(f)}if(typeof u==="string"&&u.endsWith("%")){let f=parseFloat(u);if(!Number.isNaN(f))return Math.floor(l*f*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 iV(u,l,f){if(typeof u==="string"||typeof u==="number"){let r=uy(u,f),n=uy(u,l);return{top:r,right:n,bottom:r,left:n,x:n*2,y:r*2}}if(typeof u==="object"){let r=uy(u.top??u.y??0,f),n=uy(u.bottom??u.y??0,f),i=uy(u.left??u.x??0,l),y=uy(u.right??u.x??0,l);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 yV(u,l,f,r,n,i){let{x:y,y:t}=T_(u,[l,f,r]),{x:_,y:c}=T_({x:u.x+u.width,y:u.y+u.height},[l,f,r]),A=n-_,j=i-c;return{left:Math.floor(y),top:Math.floor(t),right:Math.floor(A),bottom:Math.floor(j)}}var Z_=(u,l,f,r,n,i)=>{let y=iV(i,l,f),t=(l-y.x)/u.width,_=(f-y.y)/u.height,c=Math.min(t,_),A=fy(c,r,n),j=u.x+u.width/2,F=u.y+u.height/2,J=l/2-j*A,Q=f/2-F*A,w=yV(u,J,Q,A,l,f),L={left:Math.min(w.left-y.left,0),top:Math.min(w.top-y.top,0),right:Math.min(w.right-y.right,0),bottom:Math.min(w.bottom-y.bottom,0)};return{x:J-L.left+L.right,y:Q-L.top+L.bottom,zoom:A}},$y=()=>typeof navigator<"u"&&navigator?.userAgent?.indexOf("Mac")>=0;function ry(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 d5(u){return(u.measured?.width??u.width??u.initialWidth)!==void 0&&(u.measured?.height??u.height??u.initialHeight)!==void 0}function e5(u,l={width:0,height:0},f,r,n){let i={...u},y=r.get(f);if(y){let t=y.origin||n;i.x+=y.internals.positionAbsolute.x-(l.width??0)*t[0],i.y+=y.internals.positionAbsolute.y-(l.height??0)*t[1]}return i}function u9(u,l){if(u.size!==l.size)return!1;for(let f of u)if(!l.has(f))return!1;return!0}function jq(){let u,l;return{promise:new Promise((r,n)=>{u=r,l=n}),resolve:u,reject:l}}function Fq(u){return{...x5,...u||{}}}function z_(u,{snapGrid:l=[0,0],snapToGrid:f=!1,transform:r,containerBounds:n}){let{x:i,y}=Or(u),t=_y({x:i-(n?.left??0),y:y-(n?.top??0)},r),{x:_,y:c}=f?ty(t,l):t;return{xSnapped:_,ySnapped:c,...t}}var sc=(u)=>({width:u.offsetWidth,height:u.offsetHeight}),l9=(u)=>u?.getRootNode?.()||window?.document,tV=["INPUT","SELECT","TEXTAREA"];function f9(u){let l=u.composedPath?.()?.[0]||u.target;if(l?.nodeType!==1)return!1;return tV.includes(l.nodeName)||l.hasAttribute("contenteditable")||!!l.closest(".nokey")}var r9=(u)=>("clientX"in u),Or=(u,l)=>{let f=r9(u),r=f?u.clientX:u.touches?.[0].clientX,n=f?u.clientY:u.touches?.[0].clientY;return{x:r-(l?.left??0),y:n-(l?.top??0)}},sN=(u,l,f,r,n)=>{let i=l.querySelectorAll(`.${u}`);if(!i||!i.length)return null;return Array.from(i).map((y)=>{let t=y.getBoundingClientRect();return{id:y.getAttribute("data-handleid"),type:u,nodeId:n,position:y.getAttribute("data-handlepos"),x:(t.left-f.left)/r,y:(t.top-f.top)/r,...sc(y)}})};function ac({sourceX:u,sourceY:l,targetX:f,targetY:r,sourceControlX:n,sourceControlY:i,targetControlX:y,targetControlY:t}){let _=u*0.125+n*0.375+y*0.375+f*0.125,c=l*0.125+i*0.375+t*0.375+r*0.125,A=Math.abs(_-u),j=Math.abs(c-l);return[_,c,A,j]}function hc(u,l){if(u>=0)return 0.5*u;return l*25*Math.sqrt(-u)}function aN({pos:u,x1:l,y1:f,x2:r,y2:n,c:i}){switch(u){case Lu.Left:return[l-hc(l-r,i),f];case Lu.Right:return[l+hc(r-l,i),f];case Lu.Top:return[l,f-hc(f-n,i)];case Lu.Bottom:return[l,f+hc(n-f,i)]}}function oc({sourceX:u,sourceY:l,sourcePosition:f=Lu.Bottom,targetX:r,targetY:n,targetPosition:i=Lu.Top,curvature:y=0.25}){let[t,_]=aN({pos:f,x1:u,y1:l,x2:r,y2:n,c:y}),[c,A]=aN({pos:i,x1:r,y1:n,x2:u,y2:l,c:y}),[j,F,J,Q]=ac({sourceX:u,sourceY:l,targetX:r,targetY:n,sourceControlX:t,sourceControlY:_,targetControlX:c,targetControlY:A});return[`M${u},${l} C${t},${_} ${c},${A} ${r},${n}`,j,F,J,Q]}function n9({sourceX:u,sourceY:l,targetX:f,targetY:r}){let n=Math.abs(f-u)/2,i=f0}var _V=({source:u,sourceHandle:l,target:f,targetHandle:r})=>`xy-edge__${u}${l||""}-${f}${r||""}`,$V=(u,l)=>{return l.some((f)=>f.source===u.source&&f.target===u.target&&(f.sourceHandle===u.sourceHandle||!f.sourceHandle&&!u.sourceHandle)&&(f.targetHandle===u.targetHandle||!f.targetHandle&&!u.targetHandle))},i9=(u,l,f={})=>{if(!u.source||!u.target)return o5("006",Ur.error006()),l;let r=f.getEdgeId||_V,n;if(v5(u))n={...u};else n={...u,id:r(u)};if($V(n,l))return l;if(n.sourceHandle===null)delete n.sourceHandle;if(n.targetHandle===null)delete n.targetHandle;return l.concat(n)};function dc({sourceX:u,sourceY:l,targetX:f,targetY:r}){let[n,i,y,t]=n9({sourceX:u,sourceY:l,targetX:f,targetY:r});return[`M ${u},${l}L ${f},${r}`,n,i,y,t]}var oN={[Lu.Left]:{x:-1,y:0},[Lu.Right]:{x:1,y:0},[Lu.Top]:{x:0,y:-1},[Lu.Bottom]:{x:0,y:1}},cV=({source:u,sourcePosition:l=Lu.Bottom,target:f})=>{if(l===Lu.Left||l===Lu.Right)return u.xMath.sqrt(Math.pow(l.x-u.x,2)+Math.pow(l.y-u.y,2));function AV({source:u,sourcePosition:l=Lu.Bottom,target:f,targetPosition:r=Lu.Top,center:n,offset:i,stepPosition:y}){let t=oN[l],_=oN[r],c={x:u.x+t.x*i,y:u.y+t.y*i},A={x:f.x+_.x*i,y:f.y+_.y*i},j=cV({source:c,sourcePosition:l,target:A}),F=j.x!==0?"x":"y",J=j[F],Q=[],w,L,U={x:0,y:0},N={x:0,y:0},[,,q,W]=n9({sourceX:u.x,sourceY:u.y,targetX:f.x,targetY:f.y});if(t[F]*_[F]===-1){if(F==="x")w=n.x??c.x+(A.x-c.x)*y,L=n.y??(c.y+A.y)/2;else w=n.x??(c.x+A.x)/2,L=n.y??c.y+(A.y-c.y)*y;let E=[{x:w,y:c.y},{x:w,y:A.y}],D=[{x:c.x,y:L},{x:A.x,y:L}];if(t[F]===J)Q=F==="x"?E:D;else Q=F==="x"?D:E}else{let E=[{x:c.x,y:A.y}],D=[{x:A.x,y:c.y}];if(F==="x")Q=t.x===J?D:E;else Q=t.y===J?E:D;if(l===r){let O=Math.abs(u[F]-f[F]);if(O<=i){let m=Math.min(i-1,i-O);if(t[F]===J)U[F]=(c[F]>u[F]?-1:1)*m;else N[F]=(A[F]>f[F]?-1:1)*m}}if(l!==r){let O=F==="x"?"y":"x",m=t[F]===_[O],X=c[O]>A[O],v=c[O]=p)w=(h.x+V.x)/2,L=Q[0].y;else w=Q[0].x,L=(h.y+V.y)/2}let z={x:c.x+U.x,y:c.y+U.y},Z={x:A.x+N.x,y:A.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]:[],f],w,L,q,W]}function jV(u,l,f,r){let n=Math.min(dN(u,l)/2,dN(l,f)/2,r),{x:i,y}=l;if(u.x===i&&i===f.x||u.y===y&&y===f.y)return`L${i} ${y}`;if(u.y===y){let c=u.xf.id===l))||null}function ec(u,l){if(!u)return"";if(typeof u==="string")return u;return`${l?`${l}__`:""}${Object.keys(u).sort().map((r)=>`${r}=${u[r]}`).join("&")}`}function Nq(u,{id:l,defaultColor:f,defaultMarkerStart:r,defaultMarkerEnd:n}){let i=new Set;return u.reduce((y,t)=>{return[t.markerStart||r,t.markerEnd||n].forEach((_)=>{if(_&&typeof _==="object"){let c=ec(_,l);if(!i.has(c))y.push({id:c,color:_.color||f,..._}),i.add(c)}}),y},[]).sort((y,t)=>y.id.localeCompare(t.id))}var qq=1000,FV=10,y9={nodeOrigin:[0,0],nodeExtent:ny,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},UV={...y9,checkEquality:!0};function t9(u,l){let f={...u};for(let r in l)if(l[r]!==void 0)f[r]=l[r];return f}function Wq(u,l,f){let r=t9(y9,f);for(let n of u.values())if(n.parentId)$9(n,u,l,r);else{let i=E_(n,r.nodeOrigin),y=ry(n.extent)?n.extent:r.nodeExtent,t=Pi(i,y,A0(n));n.internals.positionAbsolute=t}}function JV(u,l){if(!u.handles)return!u.measured?void 0:l?.internals.handleBounds;let f=[],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")f.push(i);else if(n.type==="target")r.push(i)}return{source:f,target:r}}function _9(u){return u==="manual"}function u6(u,l,f,r={}){let n=t9(UV,r),i={i:0},y=new Map(l),t=n?.elevateNodesOnSelect&&!_9(n.zIndexMode)?qq:0,_=u.length>0,c=!1;l.clear(),f.clear();for(let A of u){let j=y.get(A.id);if(n.checkEquality&&A===j?.internals.userNode)l.set(A.id,j);else{let F=E_(A,n.nodeOrigin),J=ry(A.extent)?A.extent:n.nodeExtent,Q=Pi(F,J,A0(A));j={...n.defaults,...A,measured:{width:A.measured?.width,height:A.measured?.height},internals:{positionAbsolute:Q,handleBounds:JV(A,j),z:wq(A,t,n.zIndexMode),userNode:A}},l.set(A.id,j)}if((j.measured===void 0||j.measured.width===void 0||j.measured.height===void 0)&&!j.hidden)_=!1;if(A.parentId)$9(j,l,f,r,i);c||=A.selected??!1}return{nodesInitialized:_,hasSelectedNodes:c}}function QV(u,l){if(!u.parentId)return;let f=l.get(u.parentId);if(f)f.set(u.id,u);else l.set(u.parentId,new Map([[u.id,u]]))}function $9(u,l,f,r,n){let{elevateNodesOnSelect:i,nodeOrigin:y,nodeExtent:t,zIndexMode:_}=t9(y9,r),c=u.parentId,A=l.get(c);if(!A){console.warn(`Parent node ${c} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}if(QV(u,f),n&&!A.parentId&&A.internals.rootParentIndex===void 0&&_==="auto")A.internals.rootParentIndex=++n.i,A.internals.z=A.internals.z+n.i*FV;if(n&&A.internals.rootParentIndex!==void 0)n.i=A.internals.rootParentIndex;let j=i&&!_9(_)?qq:0,{x:F,y:J,z:Q}=NV(u,A,y,t,j,_),{positionAbsolute:w}=u.internals,L=F!==w.x||J!==w.y;if(L||Q!==u.internals.z)l.set(u.id,{...u,internals:{...u.internals,positionAbsolute:L?{x:F,y:J}:w,z:Q}})}function wq(u,l,f){let r=Zr(u.zIndex)?u.zIndex:0;if(_9(f))return r;return r+(u.selected?l:0)}function NV(u,l,f,r,n,i){let{x:y,y:t}=l.internals.positionAbsolute,_=A0(u),c=E_(u,f),A=ry(u.extent)?Pi(c,u.extent,_):c,j=Pi({x:y+A.x,y:t+A.y},r,_);if(u.extent==="parent")j=cq(j,_,l);let F=wq(u,n,i),J=l.internals.z??0;return{x:j.x,y:j.y,z:J>=F?J+1:F}}function l6(u,l,f,r=[0,0]){let n=[],i=new Map;for(let y of u){let t=l.get(y.parentId);if(!t)continue;let _=i.get(y.parentId)?.expandedRect??Ci(t),c=s5(_,y.rect);i.set(y.parentId,{expandedRect:c,parent:t})}if(i.size>0)i.forEach(({expandedRect:y,parent:t},_)=>{let c=t.internals.positionAbsolute,A=A0(t),j=t.origin??r,F=y.x0||J>0||L||U)n.push({id:_,type:"position",position:{x:t.position.x-F+L,y:t.position.y-J+U}}),f.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+J}})});if(A.width0){let J=l6(F,l,f,n);c.push(...J)}return{changes:c,updatedInternals:_}}async function Kq({delta:u,panZoom:l,transform:f,translateExtent:r,width:n,height:i}){if(!l||!u.x&&!u.y)return Promise.resolve(!1);let y=await l.setViewportConstrained({x:f[0]+u.x,y:f[1]+u.y,zoom:f[2]},[[0,0],[n,i]],r),t=!!y&&(y.x!==f[0]||y.y!==f[1]||y.k!==f[2]);return Promise.resolve(t)}function fq(u,l,f,r,n,i){let y=n,t=r.get(y)||new Map;r.set(y,t.set(f,l)),y=`${n}-${u}`;let _=r.get(y)||new Map;if(r.set(y,_.set(f,l)),i){y=`${n}-${u}-${i}`;let c=r.get(y)||new Map;r.set(y,c.set(f,l))}}function c9(u,l,f){u.clear(),l.clear();for(let r of f){let{source:n,target:i,sourceHandle:y=null,targetHandle:t=null}=r,_={edgeId:r.id,source:n,target:i,sourceHandle:y,targetHandle:t},c=`${n}-${y}--${i}-${t}`,A=`${i}-${t}--${n}-${y}`;fq("source",_,A,u,n,y),fq("target",_,c,u,i,t),l.set(r.id,r)}}function Gq(u,l){if(!u.parentId)return!1;let f=l.get(u.parentId);if(!f)return!1;if(f.selected)return!0;return Gq(f,l)}function rq(u,l,f){let r=u;do{if(r?.matches?.(l))return!0;if(r===f)return!1;r=r?.parentElement}while(r);return!1}function qV(u,l,f,r){let n=new Map;for(let[i,y]of u)if((y.selected||y.id===r)&&(!y.parentId||!Gq(y,u))&&(y.draggable||l&&typeof y.draggable>"u")){let t=u.get(i);if(t)n.set(i,{id:i,position:t.position||{x:0,y:0},distance:{x:f.x-t.internals.positionAbsolute.x,y:f.y-t.internals.positionAbsolute.y},extent:t.extent,parentId:t.parentId,origin:t.origin,expandParent:t.expandParent,internals:{positionAbsolute:t.internals.positionAbsolute||{x:0,y:0}},measured:{width:t.measured.width??0,height:t.measured.height??0}})}return n}function m5({nodeId:u,dragItems:l,nodeLookup:f,dragging:r=!0}){let n=[];for(let[y,t]of l){let _=f.get(y)?.internals.userNode;if(_)n.push({..._,position:t.position,dragging:r})}if(!u)return[n[0],n];let i=f.get(u)?.internals.userNode;return[!i?n[0]:{...i,position:l.get(u)?.position||i.position,dragging:r},n]}function WV({dragItems:u,snapGrid:l,x:f,y:r}){let n=u.values().next().value;if(!n)return null;let i={x:f-n.distance.x,y:r-n.distance.y},y=ty(i,l);return{x:y.x-i.x,y:y.y-i.y}}function zq({onNodeMouseDown:u,getStoreItems:l,onDragStart:f,onDrag:r,onDragStop:n}){let i={x:null,y:null},y=0,t=new Map,_=!1,c={x:0,y:0},A=null,j=!1,F=null,J=!1,Q=!1,w=null;function L({noDragClassName:N,handleSelector:q,domNode:W,isSelectable:z,nodeId:Z,nodeClickDistance:H=0}){F=sl(W);function E({x:S,y:p}){let{nodeLookup:O,nodeExtent:m,snapGrid:X,snapToGrid:v,nodeOrigin:T,onNodeDrag:Y,onSelectionDrag:k,onError:I,updateNodePositions:b}=l();i={x:S,y:p};let o=!1,g=t.size>1,x=g&&m?M5(iy(t)):null,lu=g&&v?WV({dragItems:t,snapGrid:X,x:S,y:p}):null;for(let[_u,$u]of t){if(!O.has(_u))continue;let ju={x:S-$u.distance.x,y:p-$u.distance.y};if(v)ju=lu?{x:Math.round(ju.x+lu.x),y:Math.round(ju.y+lu.y)}:ty(ju,X);let zu=null;if(g&&m&&!$u.extent&&x){let{positionAbsolute:e}=$u.internals,uu=e.x-x.x+m[0][0],Ku=e.x+$u.measured.width-x.x2+m[1][0],s=e.y-x.y+m[0][1],Nu=e.y+$u.measured.height-x.y2+m[1][1];zu=[[uu,s],[Ku,Nu]]}let{position:Wu,positionAbsolute:P}=g5({nodeId:_u,nextPosition:ju,nodeLookup:O,nodeExtent:zu?zu:m,nodeOrigin:T,onError:I});o=o||$u.position.x!==Wu.x||$u.position.y!==Wu.y,$u.position=Wu,$u.internals.positionAbsolute=P}if(Q=Q||o,!o)return;if(b(t,!0),w&&(r||Y||!Z&&k)){let[_u,$u]=m5({nodeId:Z,dragItems:t,nodeLookup:O});if(r?.(w,t,_u,$u),Y?.(w,_u,$u),!Z)k?.(w,$u)}}async function D(){if(!A)return;let{transform:S,panBy:p,autoPanSpeed:O,autoPanOnNodeDrag:m}=l();if(!m){_=!1,cancelAnimationFrame(y);return}let[X,v]=Aq(c,A,O);if(X!==0||v!==0){if(i.x=(i.x??0)-X/S[2],i.y=(i.y??0)-v/S[2],await p({x:X,y:v}))E(i)}y=requestAnimationFrame(D)}function h(S){let{nodeLookup:p,multiSelectionActive:O,nodesDraggable:m,transform:X,snapGrid:v,snapToGrid:T,selectNodesOnDrag:Y,onNodeDragStart:k,onSelectionDragStart:I,unselectNodesAndEdges:b}=l();if(j=!0,(!Y||!z)&&!O&&Z){if(!p.get(Z)?.selected)b()}if(z&&Y&&Z)u?.(Z);let o=z_(S.sourceEvent,{transform:X,snapGrid:v,snapToGrid:T,containerBounds:A});if(i=o,t=qV(p,m,o,Z),t.size>0&&(f||k||!Z&&I)){let[g,x]=m5({nodeId:Z,dragItems:t,nodeLookup:p});if(f?.(S.sourceEvent,t,g,x),k?.(S.sourceEvent,g,x),!Z)I?.(S.sourceEvent,x)}}let V=i_().clickDistance(H).on("start",(S)=>{let{domNode:p,nodeDragThreshold:O,transform:m,snapGrid:X,snapToGrid:v}=l();if(A=p?.getBoundingClientRect()||null,J=!1,Q=!1,w=S.sourceEvent,O===0)h(S);i=z_(S.sourceEvent,{transform:m,snapGrid:X,snapToGrid:v,containerBounds:A}),c=Or(S.sourceEvent,A)}).on("drag",(S)=>{let{autoPanOnNodeDrag:p,transform:O,snapGrid:m,snapToGrid:X,nodeDragThreshold:v,nodeLookup:T}=l(),Y=z_(S.sourceEvent,{transform:O,snapGrid:m,snapToGrid:X,containerBounds:A});if(w=S.sourceEvent,S.sourceEvent.type==="touchmove"&&S.sourceEvent.touches.length>1||Z&&!T.has(Z))J=!0;if(J)return;if(!_&&p&&j)_=!0,D();if(!j){let k=Or(S.sourceEvent,A),I=k.x-c.x,b=k.y-c.y;if(Math.sqrt(I*I+b*b)>v)h(S)}if((i.x!==Y.xSnapped||i.y!==Y.ySnapped)&&t&&j)c=Or(S.sourceEvent,A),E(Y)}).on("end",(S)=>{if(!j||J)return;if(_=!1,j=!1,cancelAnimationFrame(y),t.size>0){let{nodeLookup:p,updateNodePositions:O,onNodeDragStop:m,onSelectionDragStop:X}=l();if(Q)O(t,!1),Q=!1;if(n||m||!Z&&X){let[v,T]=m5({nodeId:Z,dragItems:t,nodeLookup:p,dragging:!1});if(n?.(S.sourceEvent,t,v,T),m?.(S.sourceEvent,v,T),!Z)X?.(S.sourceEvent,T)}}}).filter((S)=>{let p=S.target;return!S.button&&(!N||!rq(p,`.${N}`,W))&&(!q||rq(p,q,W))});F.call(V)}function U(){F?.on(".drag",null)}return{update:L,destroy:U}}function wV(u,l,f){let r=[],n={x:u.x-f,y:u.y-f,width:f*2,height:f*2};for(let i of l.values())if(yy(n,Ci(i))>0)r.push(i);return r}var LV=250;function KV(u,l,f,r){let n=[],i=1/0,y=wV(u,f,l+LV);for(let t of y){let _=[...t.internals.handleBounds?.source??[],...t.internals.handleBounds?.target??[]];for(let c of _){if(r.nodeId===c.nodeId&&r.type===c.type&&r.id===c.id)continue;let{x:A,y:j}=mn(t,c,c.position,!0),F=Math.sqrt(Math.pow(A-u.x,2)+Math.pow(j-u.y,2));if(F>l)continue;if(F1){let t=r.type==="source"?"target":"source";return n.find((_)=>_.type===t)??n[0]}return n[0]}function Tq(u,l,f,r,n,i=!1){let y=r.get(u);if(!y)return null;let t=n==="strict"?y.internals.handleBounds?.[l]:[...y.internals.handleBounds?.source??[],...y.internals.handleBounds?.target??[]],_=(f?t?.find((c)=>c.id===f):t?.[0])??null;return _&&i?{..._,...mn(y,_,_.position,!0)}:_}function Eq(u,l){if(u)return u;else if(l?.classList.contains("target"))return"target";else if(l?.classList.contains("source"))return"source";return null}function GV(u,l){let f=null;if(l)f=!0;else if(u&&!l)f=!1;return f}var Zq=()=>!0;function zV(u,{connectionMode:l,connectionRadius:f,handleId:r,nodeId:n,edgeUpdaterType:i,isTarget:y,domNode:t,nodeLookup:_,lib:c,autoPanOnConnect:A,flowId:j,panBy:F,cancelConnection:J,onConnectStart:Q,onConnect:w,onConnectEnd:L,isValidConnection:U=Zq,onReconnectEnd:N,updateConnection:q,getTransform:W,getFromHandle:z,autoPanSpeed:Z,dragThreshold:H=1,handleDomNode:E}){let D=l9(u.target),h=0,V,{x:S,y:p}=Or(u),O=Eq(i,E),m=t?.getBoundingClientRect(),X=!1;if(!m||!O)return;let v=Tq(n,O,r,_,l);if(!v)return;let T=Or(u,m),Y=!1,k=null,I=!1,b=null;function o(){if(!A||!m)return;let[Wu,P]=Aq(T,m,Z);F({x:Wu,y:P}),h=requestAnimationFrame(o)}let g={...v,nodeId:n,type:O,position:v.position},x=_.get(n),_u={inProgress:!0,isValid:null,from:mn(x,g,Lu.Left,!0),fromHandle:g,fromPosition:g.position,fromNode:x,to:T,toHandle:null,toPosition:IN[g.position],toNode:null,pointer:T};function $u(){X=!0,q(_u),Q?.(u,{nodeId:n,handleId:r,handleType:O})}if(H===0)$u();function ju(Wu){if(!X){let{x:Nu,y:Eu}=Or(Wu),Hu=Nu-S,vu=Eu-p;if(!(Hu*Hu+vu*vu>H*H))return;$u()}if(!z()||!g){zu(Wu);return}let P=W();if(T=Or(Wu,m),V=KV(_y(T,P,!1,[1,1]),f,_,g),!Y)o(),Y=!0;let e=Oq(Wu,{handle:V,connectionMode:l,fromNodeId:n,fromHandleId:r,fromType:y?"target":"source",isValidConnection:U,doc:D,lib:c,flowId:j,nodeLookup:_});b=e.handleDomNode,k=e.connection,I=GV(!!V,e.isValid);let uu=_.get(n),Ku=uu?mn(uu,g,Lu.Left,!0):_u.from,s={..._u,from:Ku,isValid:I,to:e.toHandle&&I?T_({x:e.toHandle.x,y:e.toHandle.y},P):T,toHandle:e.toHandle,toPosition:I&&e.toHandle?e.toHandle.position:IN[g.position],toNode:e.toHandle?_.get(e.toHandle.nodeId):null,pointer:T};q(s),_u=s}function zu(Wu){if("touches"in Wu&&Wu.touches.length>0)return;if(X){if((V||b)&&k&&I)w?.(k);let{inProgress:P,...e}=_u,uu={...e,toPosition:_u.toHandle?_u.toPosition:null};if(L?.(Wu,uu),i)N?.(Wu,uu)}J(),cancelAnimationFrame(h),Y=!1,I=!1,k=null,b=null,D.removeEventListener("mousemove",ju),D.removeEventListener("mouseup",zu),D.removeEventListener("touchmove",ju),D.removeEventListener("touchend",zu)}D.addEventListener("mousemove",ju),D.addEventListener("mouseup",zu),D.addEventListener("touchmove",ju),D.addEventListener("touchend",zu)}function Oq(u,{handle:l,connectionMode:f,fromNodeId:r,fromHandleId:n,fromType:i,doc:y,lib:t,flowId:_,isValidConnection:c=Zq,nodeLookup:A}){let j=i==="target",F=l?y.querySelector(`.${t}-flow__handle[data-id="${_}-${l?.nodeId}-${l?.id}-${l?.type}"]`):null,{x:J,y:Q}=Or(u),w=y.elementFromPoint(J,Q),L=w?.classList.contains(`${t}-flow__handle`)?w:F,U={handleDomNode:L,isValid:!1,connection:null,toHandle:null};if(L){let N=Eq(void 0,L),q=L.getAttribute("data-nodeid"),W=L.getAttribute("data-handleid"),z=L.classList.contains("connectable"),Z=L.classList.contains("connectableend");if(!q||!N)return U;let H={source:j?q:r,sourceHandle:j?W:n,target:j?r:q,targetHandle:j?n:W};U.connection=H;let D=z&&Z&&(f===Yn.Strict?j&&N==="source"||!j&&N==="target":q!==r||W!==n);U.isValid=D&&c(H),U.toHandle=Tq(q,N,W,A,f,!0)}return U}var f6={onPointerDown:zV,isValid:Oq};function Hq({domNode:u,panZoom:l,getTransform:f,getViewScale:r}){let n=sl(u);function i({translateExtent:t,width:_,height:c,zoomStep:A=1,pannable:j=!0,zoomable:F=!0,inversePan:J=!1}){let Q=(q)=>{if(q.sourceEvent.type!=="wheel"||!l)return;let W=f(),z=q.sourceEvent.ctrlKey&&$y()?10:1,Z=-q.sourceEvent.deltaY*(q.sourceEvent.deltaMode===1?0.05:q.sourceEvent.deltaMode?1:0.002)*A,H=W[2]*Math.pow(2,Z*z);l.scaleTo(H)},w=[0,0],L=(q)=>{if(q.sourceEvent.type==="mousedown"||q.sourceEvent.type==="touchstart")w=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY]},U=(q)=>{let W=f();if(q.sourceEvent.type!=="mousemove"&&q.sourceEvent.type!=="touchmove"||!l)return;let z=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY],Z=[z[0]-w[0],z[1]-w[1]];w=z;let H=r()*Math.max(W[2],Math.log(W[2]))*(J?-1:1),E={x:W[0]-Z[0]*H,y:W[1]-Z[1]*H},D=[[0,0],[_,c]];l.setViewportConstrained({x:E.x,y:E.y,zoom:W[2]},D,t)},N=G_().on("start",L).on("zoom",j?U:null).on("zoom.wheel",F?Q:null);n.call(N,{})}function y(){n.on("zoom",null)}return{update:i,destroy:y,pointer:Gf}}var r6=(u)=>({x:u.x,y:u.y,zoom:u.k}),P5=({x:u,y:l,zoom:f})=>Yi.translate(u,l).scale(f),ly=(u,l)=>u.target.closest(`.${l}`),Bq=(u,l)=>l===2&&Array.isArray(u)&&u.includes(2),TV=(u)=>((u*=2)<=1?u*u*u:(u-=2)*u*u+2)/2,C5=(u,l=0,f=TV,r=()=>{})=>{let n=typeof l==="number"&&l>0;if(!n)r();return n?u.transition().duration(l).ease(f).on("end",r):u},Vq=(u)=>{let l=u.ctrlKey&&$y()?10:1;return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*l};function EV({zoomPanValues:u,noWheelClassName:l,d3Selection:f,d3Zoom:r,panOnScrollMode:n,panOnScrollSpeed:i,zoomOnPinch:y,onPanZoomStart:t,onPanZoom:_,onPanZoomEnd:c}){return(A)=>{if(ly(A,l)){if(A.ctrlKey)A.preventDefault();return!1}A.preventDefault(),A.stopImmediatePropagation();let j=f.property("__zoom").k||1;if(A.ctrlKey&&y){let L=Gf(A),U=Vq(A),N=j*Math.pow(2,U);r.scaleTo(f,N,L,A);return}let F=A.deltaMode===1?20:1,J=n===x0.Vertical?0:A.deltaX*F,Q=n===x0.Horizontal?0:A.deltaY*F;if(!$y()&&A.shiftKey&&n!==x0.Vertical)J=A.deltaY*F,Q=0;r.translateBy(f,-(J/j)*i,-(Q/j)*i,{internal:!0});let w=r6(f.property("__zoom"));if(clearTimeout(u.panScrollTimeout),!u.isPanScrolling)u.isPanScrolling=!0,t?.(A,w);else _?.(A,w),u.panScrollTimeout=setTimeout(()=>{c?.(A,w),u.isPanScrolling=!1},150)}}function ZV({noWheelClassName:u,preventScrolling:l,d3ZoomHandler:f}){return function(r,n){let i=r.type==="wheel",y=!l&&i&&!r.ctrlKey,t=ly(r,u);if(r.ctrlKey&&i&&t)r.preventDefault();if(y||t)return null;r.preventDefault(),f.call(this,r,n)}}function OV({zoomPanValues:u,onDraggingChange:l,onPanZoomStart:f}){return(r)=>{if(r.sourceEvent?.internal)return;let n=r6(r.transform);if(u.mouseButton=r.sourceEvent?.button||0,u.isZoomingOrPanning=!0,u.prevViewport=n,r.sourceEvent?.type==="mousedown")l(!0);if(f)f?.(r.sourceEvent,n)}}function HV({zoomPanValues:u,panOnDrag:l,onPaneContextMenu:f,onTransformChange:r,onPanZoom:n}){return(i)=>{if(u.usedRightMouseButton=!!(f&&Bq(l,u.mouseButton??0)),!i.sourceEvent?.sync)r([i.transform.x,i.transform.y,i.transform.k]);if(n&&!i.sourceEvent?.internal)n?.(i.sourceEvent,r6(i.transform))}}function BV({zoomPanValues:u,panOnDrag:l,panOnScroll:f,onDraggingChange:r,onPanZoomEnd:n,onPaneContextMenu:i}){return(y)=>{if(y.sourceEvent?.internal)return;if(u.isZoomingOrPanning=!1,i&&Bq(l,u.mouseButton??0)&&!u.usedRightMouseButton&&y.sourceEvent)i(y.sourceEvent);if(u.usedRightMouseButton=!1,r(!1),n){let t=r6(y.transform);u.prevViewport=t,clearTimeout(u.timerId),u.timerId=setTimeout(()=>{n?.(y.sourceEvent,t)},f?150:0)}}}function VV({zoomActivationKeyPressed:u,zoomOnScroll:l,zoomOnPinch:f,panOnDrag:r,panOnScroll:n,zoomOnDoubleClick:i,userSelectionActive:y,noWheelClassName:t,noPanClassName:_,lib:c,connectionInProgress:A}){return(j)=>{let F=u||l,J=f&&j.ctrlKey,Q=j.type==="wheel";if(j.button===1&&j.type==="mousedown"&&(ly(j,`${c}-flow__node`)||ly(j,`${c}-flow__edge`)))return!0;if(!r&&!F&&!n&&!i&&!f)return!1;if(y)return!1;if(A&&!Q)return!1;if(ly(j,t)&&Q)return!1;if(ly(j,_)&&(!Q||n&&Q&&!u))return!1;if(!f&&j.ctrlKey&&Q)return!1;if(!f&&j.type==="touchstart"&&j.touches?.length>1)return j.preventDefault(),!1;if(!F&&!n&&!J&&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 w=Array.isArray(r)&&r.includes(j.button)||!j.button||j.button<=1;return(!j.ctrlKey||Q)&&w}}function Dq({domNode:u,minZoom:l,maxZoom:f,translateExtent:r,viewport:n,onPanZoom:i,onPanZoomStart:y,onPanZoomEnd:t,onDraggingChange:_}){let c={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},A=u.getBoundingClientRect(),j=G_().scaleExtent([l,f]).translateExtent(r),F=sl(u).call(j);N({x:n.x,y:n.y,zoom:fy(n.zoom,l,f)},[[0,0],[A.width,A.height]],r);let J=F.on("wheel.zoom"),Q=F.on("dblclick.zoom");j.wheelDelta(Vq);function w(V,S){if(F)return new Promise((p)=>{j?.interpolate(S?.interpolate==="linear"?$0:Xi).transform(C5(F,S?.duration,S?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function L({noWheelClassName:V,noPanClassName:S,onPaneContextMenu:p,userSelectionActive:O,panOnScroll:m,panOnDrag:X,panOnScrollMode:v,panOnScrollSpeed:T,preventScrolling:Y,zoomOnPinch:k,zoomOnScroll:I,zoomOnDoubleClick:b,zoomActivationKeyPressed:o,lib:g,onTransformChange:x,connectionInProgress:lu,paneClickDistance:_u,selectionOnDrag:$u}){if(O&&!c.isZoomingOrPanning)U();let ju=m&&!o&&!O;j.clickDistance($u?1/0:!Zr(_u)||_u<0?0:_u);let zu=ju?EV({zoomPanValues:c,noWheelClassName:V,d3Selection:F,d3Zoom:j,panOnScrollMode:v,panOnScrollSpeed:T,zoomOnPinch:k,onPanZoomStart:y,onPanZoom:i,onPanZoomEnd:t}):ZV({noWheelClassName:V,preventScrolling:Y,d3ZoomHandler:J});if(F.on("wheel.zoom",zu,{passive:!1}),!O){let P=OV({zoomPanValues:c,onDraggingChange:_,onPanZoomStart:y});j.on("start",P);let e=HV({zoomPanValues:c,panOnDrag:X,onPaneContextMenu:!!p,onPanZoom:i,onTransformChange:x});j.on("zoom",e);let uu=BV({zoomPanValues:c,panOnDrag:X,panOnScroll:m,onPaneContextMenu:p,onPanZoomEnd:t,onDraggingChange:_});j.on("end",uu)}let Wu=VV({zoomActivationKeyPressed:o,panOnDrag:X,zoomOnScroll:I,panOnScroll:m,zoomOnDoubleClick:b,zoomOnPinch:k,userSelectionActive:O,noPanClassName:S,noWheelClassName:V,lib:g,connectionInProgress:lu});if(j.filter(Wu),b)F.on("dblclick.zoom",Q);else F.on("dblclick.zoom",null)}function U(){j.on("zoom",null)}async function N(V,S,p){let O=P5(V),m=j?.constrain()(O,S,p);if(m)await w(m);return new Promise((X)=>X(m))}async function q(V,S){let p=P5(V);return await w(p,S),new Promise((O)=>O(p))}function W(V){if(F){let S=P5(V),p=F.property("__zoom");if(p.k!==V.zoom||p.x!==V.x||p.y!==V.y)j?.transform(F,S,null,{sync:!0})}}function z(){let V=F?K_(F.node()):{x:0,y:0,k:1};return{x:V.x,y:V.y,zoom:V.k}}function Z(V,S){if(F)return new Promise((p)=>{j?.interpolate(S?.interpolate==="linear"?$0:Xi).scaleTo(C5(F,S?.duration,S?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function H(V,S){if(F)return new Promise((p)=>{j?.interpolate(S?.interpolate==="linear"?$0:Xi).scaleBy(C5(F,S?.duration,S?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function E(V){j?.scaleExtent(V)}function D(V){j?.translateExtent(V)}function h(V){let S=!Zr(V)||V<0?0:V;j?.clickDistance(S)}return{update:L,destroy:U,setViewport:q,setViewportConstrained:N,getViewport:z,scaleTo:Z,scaleBy:H,setScaleExtent:E,setTranslateExtent:D,syncViewport:W,setClickDistance:h}}var Pn;(function(u){u.Line="line",u.Handle="handle"})(Pn||(Pn={}));function DV({width:u,prevWidth:l,height:f,prevHeight:r,affectsX:n,affectsY:i}){let y=u-l,t=f-r,_=[y>0?1:y<0?-1:0,t>0?1:t<0?-1:0];if(y&&n)_[0]=_[0]*-1;if(t&&i)_[1]=_[1]*-1;return _}function nq(u){let l=u.includes("right")||u.includes("left"),f=u.includes("bottom")||u.includes("top"),r=u.includes("left"),n=u.includes("top");return{isHorizontal:l,isVertical:f,affectsX:r,affectsY:n}}function Xn(u,l){return Math.max(0,l-u)}function Sn(u,l){return Math.max(0,u-l)}function bc(u,l,f){return Math.max(0,l-u,u-f)}function iq(u,l){return u?!l:l}function XV(u,l,f,r,n,i,y,t){let{affectsX:_,affectsY:c}=l,{isHorizontal:A,isVertical:j}=l,F=A&&j,{xSnapped:J,ySnapped:Q}=f,{minWidth:w,maxWidth:L,minHeight:U,maxHeight:N}=r,{x:q,y:W,width:z,height:Z,aspectRatio:H}=u,E=Math.floor(A?J-u.pointerX:0),D=Math.floor(j?Q-u.pointerY:0),h=z+(_?-E:E),V=Z+(c?-D:D),S=-i[0]*z,p=-i[1]*Z,O=bc(h,w,L),m=bc(V,U,N);if(y){let T=0,Y=0;if(_&&E<0)T=Xn(q+E+S,y[0][0]);else if(!_&&E>0)T=Sn(q+h+S,y[1][0]);if(c&&D<0)Y=Xn(W+D+p,y[0][1]);else if(!c&&D>0)Y=Sn(W+V+p,y[1][1]);O=Math.max(O,T),m=Math.max(m,Y)}if(t){let T=0,Y=0;if(_&&E>0)T=Sn(q+E,t[0][0]);else if(!_&&E<0)T=Xn(q+h,t[1][0]);if(c&&D>0)Y=Sn(W+D,t[0][1]);else if(!c&&D<0)Y=Xn(W+V,t[1][1]);O=Math.max(O,T),m=Math.max(m,Y)}if(n){if(A){let T=bc(h/H,U,N)*H;if(O=Math.max(O,T),y){let Y=0;if(!_&&!c||_&&!c&&F)Y=Sn(W+p+h/H,y[1][1])*H;else Y=Xn(W+p+(_?E:-E)/H,y[0][1])*H;O=Math.max(O,Y)}if(t){let Y=0;if(!_&&!c||_&&!c&&F)Y=Xn(W+h/H,t[1][1])*H;else Y=Sn(W+(_?E:-E)/H,t[0][1])*H;O=Math.max(O,Y)}}if(j){let T=bc(V*H,w,L)/H;if(m=Math.max(m,T),y){let Y=0;if(!_&&!c||c&&!_&&F)Y=Sn(q+V*H+S,y[1][0])/H;else Y=Xn(q+(c?D:-D)*H+S,y[0][0])/H;m=Math.max(m,Y)}if(t){let Y=0;if(!_&&!c||c&&!_&&F)Y=Xn(q+V*H,t[1][0])/H;else Y=Sn(q+(c?D:-D)*H,t[0][0])/H;m=Math.max(m,Y)}}}if(D=D+(D<0?m:-m),E=E+(E<0?O:-O),n)if(F)if(h>V*H)D=(iq(_,c)?-E:E)/H;else E=(iq(_,c)?-D:D)*H;else if(A)D=E/H,c=_;else E=D*H,_=c;let X=_?q+E:q,v=c?W+D:W;return{width:z+(_?-E:E),height:Z+(c?-D:D),x:i[0]*E*(!_?1:-1)+X,y:i[1]*D*(!c?1:-1)+v}}var Xq={width:0,height:0,x:0,y:0},SV={...Xq,pointerX:0,pointerY:0,aspectRatio:1};function YV(u){return[[0,0],[u.measured.width,u.measured.height]]}function pV(u,l,f){let r=l.position.x+u.position.x,n=l.position.y+u.position.y,i=u.measured.width??0,y=u.measured.height??0,t=f[0]*i,_=f[1]*y;return[[r-t,n-_],[r+i-t,n+y-_]]}function Sq({domNode:u,nodeId:l,getStoreItems:f,onChange:r,onEnd:n}){let i=sl(u),y={controlDirection:nq("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function t({controlPosition:c,boundaries:A,keepAspectRatio:j,resizeDirection:F,onResizeStart:J,onResize:Q,onResizeEnd:w,shouldResize:L}){let U={...Xq},N={...SV};y={boundaries:A,resizeDirection:F,keepAspectRatio:j,controlDirection:nq(c)};let q=void 0,W=null,z=[],Z=void 0,H=void 0,E=void 0,D=!1,h=i_().on("start",(V)=>{let{nodeLookup:S,transform:p,snapGrid:O,snapToGrid:m,nodeOrigin:X,paneDomNode:v}=f();if(q=S.get(l),!q)return;W=v?.getBoundingClientRect()??null;let{xSnapped:T,ySnapped:Y}=z_(V.sourceEvent,{transform:p,snapGrid:O,snapToGrid:m,containerBounds:W});if(U={width:q.measured.width??0,height:q.measured.height??0,x:q.position.x??0,y:q.position.y??0},N={...U,pointerX:T,pointerY:Y,aspectRatio:U.width/U.height},Z=void 0,q.parentId&&(q.extent==="parent"||q.expandParent))Z=S.get(q.parentId),H=Z&&q.extent==="parent"?YV(Z):void 0;z=[],E=void 0;for(let[k,I]of S)if(I.parentId===l){if(z.push({id:k,position:{...I.position},extent:I.extent}),I.extent==="parent"||I.expandParent){let b=pV(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}}J?.(V,{...U})}).on("drag",(V)=>{let{transform:S,snapGrid:p,snapToGrid:O,nodeOrigin:m}=f(),X=z_(V.sourceEvent,{transform:S,snapGrid:p,snapToGrid:O,containerBounds:W}),v=[];if(!q)return;let{x:T,y:Y,width:k,height:I}=U,b={},o=q.origin??m,{width:g,height:x,x:lu,y:_u}=XV(N,y.controlDirection,X,y.boundaries,y.keepAspectRatio,o,H,E),$u=g!==k,ju=x!==I,zu=lu!==T&&$u,Wu=_u!==Y&&ju;if(!zu&&!Wu&&!$u&&!ju)return;if(zu||Wu||o[0]===1||o[1]===1){if(b.x=zu?lu:U.x,b.y=Wu?_u:U.y,U.x=b.x,U.y=b.y,z.length>0){let Ku=lu-T,s=_u-Y;for(let Nu of z)Nu.position={x:Nu.position.x-Ku+o[0]*(g-k),y:Nu.position.y-s+o[1]*(x-I)},v.push(Nu)}}if($u||ju)b.width=$u&&(!y.resizeDirection||y.resizeDirection==="horizontal")?g:U.width,b.height=ju&&(!y.resizeDirection||y.resizeDirection==="vertical")?x:U.height,U.width=b.width,U.height=b.height;if(Z&&q.expandParent){let Ku=o[0]*(b.width??0);if(b.x&&b.x{if(!D)return;w?.(V,{...U}),n?.({...U}),D=!1});i.call(h)}function _(){i.on(".drag",null)}return{update:t,destroy:_}}var kq=Pu(Jl(),1),Iq=Pu(xq(),1);var hq=(u)=>{let l,f=new Set,r=(A,j)=>{let F=typeof A==="function"?A(l):A;if(!Object.is(F,l)){let J=l;l=(j!=null?j:typeof F!=="object"||F===null)?F:Object.assign({},l,F),f.forEach((Q)=>Q(l,J))}},n=()=>l,_={setState:r,getState:n,getInitialState:()=>c,subscribe:(A)=>{return f.add(A),()=>f.delete(A)},destroy:()=>{f.clear()}},c=l=u(r,n,_);return _},bq=(u)=>u?hq(u):hq;var{useDebugValue:uD}=kq.default,{useSyncExternalStoreWithSelector:lD}=Iq.default,fD=(u)=>u;function j9(u,l=fD,f){let r=lD(u.subscribe,u.getState,u.getServerState||u.getInitialState,l,f);return uD(r),r}var vq=(u,l)=>{let f=bq(u),r=(n,i=l)=>j9(f,n,i);return Object.assign(r,f),r},gq=(u,l)=>u?vq(u,l):vq;function Gl(u,l){if(Object.is(u,l))return!0;if(typeof u!=="object"||u===null||typeof l!=="object"||l===null)return!1;if(u instanceof Map&&l instanceof Map){if(u.size!==l.size)return!1;for(let[r,n]of u)if(!Object.is(n,l.get(r)))return!1;return!0}if(u instanceof Set&&l instanceof Set){if(u.size!==l.size)return!1;for(let r of u)if(!l.has(r))return!1;return!0}let f=Object.keys(u);if(f.length!==Object.keys(l).length)return!1;for(let r of f)if(!Object.prototype.hasOwnProperty.call(l,r)||!Object.is(u[r],l[r]))return!1;return!0}var rD=Pu(WA(),1),_6=yu.createContext(null),nD=_6.Provider,qW=Ur.error001();function fl(u,l){let f=yu.useContext(_6);if(f===null)throw Error(qW);return j9(f,u,l)}function El(){let u=yu.useContext(_6);if(u===null)throw Error(qW);return yu.useMemo(()=>({getState:u.getState,setState:u.setState,subscribe:u.subscribe}),[u])}var sq={display:"none"},iD={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},WW="react-flow__node-desc",wW="react-flow__edge-desc",yD="react-flow__aria-live",tD=(u)=>u.ariaLiveMessage,_D=(u)=>u.ariaLabelConfig;function $D({rfId:u}){let l=fl(tD);return ru.jsx("div",{id:`${yD}-${u}`,"aria-live":"assertive","aria-atomic":"true",style:iD,children:l})}function cD({rfId:u,disableKeyboardA11y:l}){let f=fl(_D);return ru.jsxs(ru.Fragment,{children:[ru.jsx("div",{id:`${WW}-${u}`,style:sq,children:l?f["node.a11yDescription.default"]:f["node.a11yDescription.keyboardDisabled"]}),ru.jsx("div",{id:`${wW}-${u}`,style:sq,children:f["edge.a11yDescription.default"]}),!l&&ru.jsx($D,{rfId:u})]})}var $6=yu.forwardRef(({position:u="top-left",children:l,className:f,style:r,...n},i)=>{let y=`${u}`.split("-");return ru.jsx("div",{className:Sl(["react-flow__panel",f,...y]),style:r,ref:i,...n,children:l})});$6.displayName="Panel";function AD({proOptions:u,position:l="bottom-right"}){if(u?.hideAttribution)return null;return ru.jsx($6,{position:l,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 jD=(u)=>{let l=[],f=[];for(let[,r]of u.nodeLookup)if(r.selected)l.push(r.internals.userNode);for(let[,r]of u.edgeLookup)if(r.selected)f.push(r);return{selectedNodes:l,selectedEdges:f}},i6=(u)=>u.id;function FD(u,l){return Gl(u.selectedNodes.map(i6),l.selectedNodes.map(i6))&&Gl(u.selectedEdges.map(i6),l.selectedEdges.map(i6))}function UD({onSelectionChange:u}){let l=El(),{selectedNodes:f,selectedEdges:r}=fl(jD,FD);return yu.useEffect(()=>{let n={nodes:f,edges:r};u?.(n),l.getState().onSelectionChangeHandlers.forEach((i)=>i(n))},[f,r,u]),null}var JD=(u)=>!!u.onSelectionChangeHandlers;function QD({onSelectionChange:u}){let l=fl(JD);if(u||l)return ru.jsx(UD,{onSelectionChange:u});return null}var J9=typeof window<"u"?yu.useLayoutEffect:yu.useEffect,LW=[0,0],ND={x:0,y:0,zoom:1},qD=["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"],aq=[...qD,"rfId"],WD=(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}),oq={translateExtent:ny,nodeOrigin:LW,minZoom:0.5,maxZoom:2,elementsSelectable:!0,noPanClassName:"nopan",rfId:"1"};function wD(u){let{setNodes:l,setEdges:f,setMinZoom:r,setMaxZoom:n,setTranslateExtent:i,setNodeExtent:y,reset:t,setDefaultNodesAndEdges:_}=fl(WD,Gl),c=El();J9(()=>{return _(u.defaultNodes,u.defaultEdges),()=>{A.current=oq,t()}},[]);let A=yu.useRef(oq);return J9(()=>{for(let j of aq){let F=u[j],J=A.current[j];if(F===J)continue;if(typeof u[j]>"u")continue;if(j==="nodes")l(F);else if(j==="edges")f(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")c.setState({ariaLabelConfig:Fq(F)});else if(j==="fitView")c.setState({fitViewQueued:F});else if(j==="fitViewOptions")c.setState({fitViewOptions:F});else c.setState({[j]:F})}A.current=u},aq.map((j)=>u[j])),null}function dq(){if(typeof window>"u"||!window.matchMedia)return null;return window.matchMedia("(prefers-color-scheme: dark)")}function LD(u){let[l,f]=yu.useState(u==="system"?null:u);return yu.useEffect(()=>{if(u!=="system"){f(u);return}let r=dq(),n=()=>f(r?.matches?"dark":"light");return n(),r?.addEventListener("change",n),()=>{r?.removeEventListener("change",n)}},[u]),l!==null?l:dq()?.matches?"dark":"light"}var eq=typeof document<"u"?document:null;function H_(u=null,l={target:eq,actInsideInputWithModifier:!0}){let[f,r]=yu.useState(!1),n=yu.useRef(!1),i=yu.useRef(new Set([])),[y,t]=yu.useMemo(()=>{if(u!==null){let c=(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??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(` +`)),A=c.reduce((j,F)=>j.concat(...F),[]);return[c,A]}return[[],[]]},[u]);return yu.useEffect(()=>{let _=l?.target??eq,c=l?.actInsideInputWithModifier??!0;if(u!==null){let A=(J)=>{if(n.current=J.ctrlKey||J.metaKey||J.shiftKey||J.altKey,(!n.current||n.current&&!c)&&f9(J))return!1;let w=lW(J.code,t);if(i.current.add(J[w]),uW(y,i.current,!1)){let L=J.composedPath?.()?.[0]||J.target,U=L?.nodeName==="BUTTON"||L?.nodeName==="A";if(l.preventDefault!==!1&&(n.current||!U))J.preventDefault();r(!0)}},j=(J)=>{let Q=lW(J.code,t);if(uW(y,i.current,!0))r(!1),i.current.clear();else i.current.delete(J[Q]);if(J.key==="Meta")i.current.clear();n.current=!1},F=()=>{i.current.clear(),r(!1)};return _?.addEventListener("keydown",A),_?.addEventListener("keyup",j),window.addEventListener("blur",F),window.addEventListener("contextmenu",F),()=>{_?.removeEventListener("keydown",A),_?.removeEventListener("keyup",j),window.removeEventListener("blur",F),window.removeEventListener("contextmenu",F)}}},[u,r]),f}function uW(u,l,f){return u.filter((r)=>f||r.length===l.size).some((r)=>r.every((n)=>l.has(n)))}function lW(u,l){return l.includes(u)?"code":"key"}var KD=()=>{let u=El();return yu.useMemo(()=>{return{zoomIn:(l)=>{let{panZoom:f}=u.getState();return f?f.scaleBy(1.2,l):Promise.resolve(!1)},zoomOut:(l)=>{let{panZoom:f}=u.getState();return f?f.scaleBy(0.8333333333333334,l):Promise.resolve(!1)},zoomTo:(l,f)=>{let{panZoom:r}=u.getState();return r?r.scaleTo(l,f):Promise.resolve(!1)},getZoom:()=>u.getState().transform[2],setViewport:async(l,f)=>{let{transform:[r,n,i],panZoom:y}=u.getState();if(!y)return Promise.resolve(!1);return await y.setViewport({x:l.x??r,y:l.y??n,zoom:l.zoom??i},f),Promise.resolve(!0)},getViewport:()=>{let[l,f,r]=u.getState().transform;return{x:l,y:f,zoom:r}},setCenter:async(l,f,r)=>{return u.getState().setCenter(l,f,r)},fitBounds:async(l,f)=>{let{width:r,height:n,minZoom:i,maxZoom:y,panZoom:t}=u.getState(),_=Z_(l,r,n,i,y,f?.padding??0.1);if(!t)return Promise.resolve(!1);return await t.setViewport(_,{duration:f?.duration,ease:f?.ease,interpolate:f?.interpolate}),Promise.resolve(!0)},screenToFlowPosition:(l,f={})=>{let{transform:r,snapGrid:n,snapToGrid:i,domNode:y}=u.getState();if(!y)return l;let{x:t,y:_}=y.getBoundingClientRect(),c={x:l.x-t,y:l.y-_},A=f.snapGrid??n,j=f.snapToGrid??i;return _y(c,r,j,A)},flowToScreenPosition:(l)=>{let{transform:f,domNode:r}=u.getState();if(!r)return l;let{x:n,y:i}=r.getBoundingClientRect(),y=T_(l,f);return{x:y.x+n,y:y.y+i}}}},[])};function KW(u,l){let f=[],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 l){let y=r.get(i.id);if(!y){f.push(i);continue}if(y[0].type==="remove")continue;if(y[0].type==="replace"){f.push({...y[0].item});continue}let t={...i};for(let _ of y)GD(_,t);f.push(t)}if(n.length)n.forEach((i)=>{if(i.index!==void 0)f.splice(i.index,0,{...i.item});else f.push({...i.item})});return f}function GD(u,l){switch(u.type){case"select":{l.selected=u.selected;break}case"position":{if(typeof u.position<"u")l.position=u.position;if(typeof u.dragging<"u")l.dragging=u.dragging;break}case"dimensions":{if(typeof u.dimensions<"u"){if(l.measured={...u.dimensions},u.setAttributes){if(u.setAttributes===!0||u.setAttributes==="width")l.width=u.dimensions.width;if(u.setAttributes===!0||u.setAttributes==="height")l.height=u.dimensions.height}}if(typeof u.resizing==="boolean")l.resizing=u.resizing;break}}}function zD(u,l){return KW(u,l)}function TD(u,l){return KW(u,l)}function Mi(u,l){return{id:u,type:"select",selected:l}}function Ay(u,l=new Set,f=!1){let r=[];for(let[n,i]of u){let y=l.has(n);if(!(i.selected===void 0&&!y)&&i.selected!==y){if(f)i.selected=y;r.push(Mi(i.id,y))}}return r}function fW({items:u=[],lookup:l}){let f=[],r=new Map(u.map((n)=>[n.id,n]));for(let[n,i]of u.entries()){let y=l.get(i.id),t=y?.internals?.userNode??y;if(t!==void 0&&t!==i)f.push({id:i.id,item:i,type:"replace"});if(t===void 0)f.push({item:i,type:"add",index:n})}for(let[n]of l)if(r.get(n)===void 0)f.push({id:n,type:"remove"});return f}function rW(u){return{id:u.id,type:"remove"}}var nW=(u)=>yq(u),ED=(u)=>v5(u);function GW(u){return yu.forwardRef(u)}function iW(u){let[l,f]=yu.useState(BigInt(0)),[r]=yu.useState(()=>ZD(()=>f((n)=>n+BigInt(1))));return J9(()=>{let n=r.get();if(n.length)u(n),r.reset()},[l]),r}function ZD(u){let l=[];return{get:()=>l,reset:()=>{l=[]},push:(f)=>{l.push(f),u()}}}var zW=yu.createContext(null);function OD({children:u}){let l=El(),f=yu.useCallback((t)=>{let{nodes:_=[],setNodes:c,hasDefaultNodes:A,onNodesChange:j,nodeLookup:F,fitViewQueued:J,onNodesChangeMiddlewareMap:Q}=l.getState(),w=_;for(let U of t)w=typeof U==="function"?U(w):U;let L=fW({items:w,lookup:F});for(let U of Q.values())L=U(L);if(A)c(w);if(L.length>0)j?.(L);else if(J)window.requestAnimationFrame(()=>{let{fitViewQueued:U,nodes:N,setNodes:q}=l.getState();if(U)q(N)})},[]),r=iW(f),n=yu.useCallback((t)=>{let{edges:_=[],setEdges:c,hasDefaultEdges:A,onEdgesChange:j,edgeLookup:F}=l.getState(),J=_;for(let Q of t)J=typeof Q==="function"?Q(J):Q;if(A)c(J);else if(j)j(fW({items:J,lookup:F}))},[]),i=iW(n),y=yu.useMemo(()=>({nodeQueue:r,edgeQueue:i}),[]);return ru.jsx(zW.Provider,{value:y,children:u})}function HD(){let u=yu.useContext(zW);if(!u)throw Error("useBatchContext must be used within a BatchProvider");return u}var BD=(u)=>!!u.panZoom;function N9(){let u=KD(),l=El(),f=HD(),r=fl(BD),n=yu.useMemo(()=>{let i=(j)=>l.getState().nodeLookup.get(j),y=(j)=>{f.nodeQueue.push(j)},t=(j)=>{f.edgeQueue.push(j)},_=(j)=>{let{nodeLookup:F,nodeOrigin:J}=l.getState(),Q=nW(j)?j:F.get(j.id),w=Q.parentId?e5(Q.position,Q.measured,Q.parentId,F,J):Q.position,L={...Q,position:w,width:Q.measured?.width??Q.width,height:Q.measured?.height??Q.height};return Ci(L)},c=(j,F,J={replace:!1})=>{y((Q)=>Q.map((w)=>{if(w.id===j){let L=typeof F==="function"?F(w):F;return J.replace&&nW(L)?L:{...w,...L}}return w}))},A=(j,F,J={replace:!1})=>{t((Q)=>Q.map((w)=>{if(w.id===j){let L=typeof F==="function"?F(w):F;return J.replace&&ED(L)?L:{...w,...L}}return w}))};return{getNodes:()=>l.getState().nodes.map((j)=>({...j})),getNode:(j)=>i(j)?.internals.userNode,getInternalNode:i,getEdges:()=>{let{edges:j=[]}=l.getState();return j.map((F)=>({...F}))},getEdge:(j)=>l.getState().edgeLookup.get(j),setNodes:y,setEdges:t,addNodes:(j)=>{let F=Array.isArray(j)?j:[j];f.nodeQueue.push((J)=>[...J,...F])},addEdges:(j)=>{let F=Array.isArray(j)?j:[j];f.edgeQueue.push((J)=>[...J,...F])},toObject:()=>{let{nodes:j=[],edges:F=[],transform:J}=l.getState(),[Q,w,L]=J;return{nodes:j.map((U)=>({...U})),edges:F.map((U)=>({...U})),viewport:{x:Q,y:w,zoom:L}}},deleteElements:async({nodes:j=[],edges:F=[]})=>{let{nodes:J,edges:Q,onNodesDelete:w,onEdgesDelete:L,triggerNodeChanges:U,triggerEdgeChanges:N,onDelete:q,onBeforeDelete:W}=l.getState(),{nodes:z,edges:Z}=await $q({nodesToRemove:j,edgesToRemove:F,nodes:J,edges:Q,onBeforeDelete:W}),H=Z.length>0,E=z.length>0;if(H){let D=Z.map(rW);L?.(Z),N(D)}if(E){let D=z.map(rW);w?.(z),U(D)}if(E||H)q?.({nodes:z,edges:Z});return{deletedNodes:z,deletedEdges:Z}},getIntersectingNodes:(j,F=!0,J)=>{let Q=a5(j),w=Q?j:_(j),L=J!==void 0;if(!w)return[];return(J||l.getState().nodes).filter((U)=>{let N=l.getState().nodeLookup.get(U.id);if(N&&!Q&&(U.id===j.id||!N.internals.positionAbsolute))return!1;let q=Ci(L?U:N),W=yy(q,w);return F&&W>0||W>=q.width*q.height||W>=w.width*w.height})},isNodeIntersecting:(j,F,J=!0)=>{let w=a5(j)?j:_(j);if(!w)return!1;let L=yy(w,F);return J&&L>0||L>=F.width*F.height||L>=w.width*w.height},updateNode:c,updateNodeData:(j,F,J={replace:!1})=>{c(j,(Q)=>{let w=typeof F==="function"?F(Q):F;return J.replace?{...Q,data:w}:{...Q,data:{...Q.data,...w}}},J)},updateEdge:A,updateEdgeData:(j,F,J={replace:!1})=>{A(j,(Q)=>{let w=typeof F==="function"?F(Q):F;return J.replace?{...Q,data:w}:{...Q,data:{...Q.data,...w}}},J)},getNodesBounds:(j)=>{let{nodeLookup:F,nodeOrigin:J}=l.getState();return I5(j,{nodeLookup:F,nodeOrigin:J})},getHandleConnections:({type:j,id:F,nodeId:J})=>Array.from(l.getState().connectionLookup.get(`${J}-${j}${F?`-${F}`:""}`)?.values()??[]),getNodeConnections:({type:j,handleId:F,nodeId:J})=>Array.from(l.getState().connectionLookup.get(`${J}${j?F?`-${j}-${F}`:`-${j}`:""}`)?.values()??[]),fitView:async(j)=>{let F=l.getState().fitViewResolver??jq();return l.setState({fitViewQueued:!0,fitViewOptions:j,fitViewResolver:F}),f.nodeQueue.push((J)=>[...J]),F.promise}}},[]);return yu.useMemo(()=>{return{...n,...u,viewportInitialized:r}},[r])}var yW=(u)=>u.selected,VD=typeof window<"u"?window:void 0;function DD({deleteKeyCode:u,multiSelectionKeyCode:l}){let f=El(),{deleteElements:r}=N9(),n=H_(u,{actInsideInputWithModifier:!1}),i=H_(l,{target:VD});yu.useEffect(()=>{if(n){let{edges:y,nodes:t}=f.getState();r({nodes:t.filter(yW),edges:y.filter(yW)}),f.setState({nodesSelectionActive:!1})}},[n]),yu.useEffect(()=>{f.setState({multiSelectionActive:i})},[i])}function XD(u){let l=El();yu.useEffect(()=>{let f=()=>{if(!u.current||!(u.current.checkVisibility?.()??!0))return!1;let r=sc(u.current);if(r.height===0||r.width===0)l.getState().onError?.("004",Ur.error004());l.setState({width:r.width||500,height:r.height||500})};if(u.current){f(),window.addEventListener("resize",f);let r=new ResizeObserver(()=>f());return r.observe(u.current),()=>{if(window.removeEventListener("resize",f),r&&u.current)r.unobserve(u.current)}}},[])}var c6={position:"absolute",width:"100%",height:"100%",top:0,left:0},SD=(u)=>({userSelectionActive:u.userSelectionActive,lib:u.lib,connectionInProgress:u.connection.inProgress});function YD({onPaneContextMenu:u,zoomOnScroll:l=!0,zoomOnPinch:f=!0,panOnScroll:r=!1,panOnScrollSpeed:n=0.5,panOnScrollMode:i=x0.Free,zoomOnDoubleClick:y=!0,panOnDrag:t=!0,defaultViewport:_,translateExtent:c,minZoom:A,maxZoom:j,zoomActivationKeyCode:F,preventScrolling:J=!0,children:Q,noWheelClassName:w,noPanClassName:L,onViewportChange:U,isControlledViewport:N,paneClickDistance:q,selectionOnDrag:W}){let z=El(),Z=yu.useRef(null),{userSelectionActive:H,lib:E,connectionInProgress:D}=fl(SD,Gl),h=H_(F),V=yu.useRef();XD(Z);let S=yu.useCallback((p)=>{if(U?.({x:p[0],y:p[1],zoom:p[2]}),!N)z.setState({transform:p})},[U,N]);return yu.useEffect(()=>{if(Z.current){V.current=Dq({domNode:Z.current,minZoom:A,maxZoom:j,translateExtent:c,viewport:_,onDraggingChange:(X)=>z.setState((v)=>v.paneDragging===X?v:{paneDragging:X}),onPanZoomStart:(X,v)=>{let{onViewportChangeStart:T,onMoveStart:Y}=z.getState();Y?.(X,v),T?.(v)},onPanZoom:(X,v)=>{let{onViewportChange:T,onMove:Y}=z.getState();Y?.(X,v),T?.(v)},onPanZoomEnd:(X,v)=>{let{onViewportChangeEnd:T,onMoveEnd:Y}=z.getState();Y?.(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:l,zoomOnPinch:f,panOnScroll:r,panOnScrollSpeed:n,panOnScrollMode:i,zoomOnDoubleClick:y,panOnDrag:t,zoomActivationKeyPressed:h,preventScrolling:J,noPanClassName:L,userSelectionActive:H,noWheelClassName:w,lib:E,onTransformChange:S,connectionInProgress:D,selectionOnDrag:W,paneClickDistance:q})},[u,l,f,r,n,i,y,t,h,J,L,H,w,E,S,D,W,q]),ru.jsx("div",{className:"react-flow__renderer",ref:Z,style:c6,children:Q})}var pD=(u)=>({userSelectionActive:u.userSelectionActive,userSelectionRect:u.userSelectionRect});function mD(){let{userSelectionActive:u,userSelectionRect:l}=fl(pD,Gl);if(!(u&&l))return null;return ru.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:l.width,height:l.height,transform:`translate(${l.x}px, ${l.y}px)`}})}var F9=(u,l)=>{return(f)=>{if(f.target!==l.current)return;u?.(f)}},PD=(u)=>({userSelectionActive:u.userSelectionActive,elementsSelectable:u.elementsSelectable,connectionInProgress:u.connection.inProgress,dragging:u.paneDragging});function CD({isSelecting:u,selectionKeyPressed:l,selectionMode:f=mi.Full,panOnDrag:r,paneClickDistance:n,selectionOnDrag:i,onSelectionStart:y,onSelectionEnd:t,onPaneClick:_,onPaneContextMenu:c,onPaneScroll:A,onPaneMouseEnter:j,onPaneMouseMove:F,onPaneMouseLeave:J,children:Q}){let w=El(),{userSelectionActive:L,elementsSelectable:U,dragging:N,connectionInProgress:q}=fl(PD,Gl),W=U&&(u||L),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),w.getState().resetSelectedElements(),w.setState({nodesSelectionActive:!1})},V=(T)=>{if(Array.isArray(r)&&r?.includes(2)){T.preventDefault();return}c?.(T)},S=A?(T)=>A(T):void 0,p=(T)=>{if(D.current)T.stopPropagation(),D.current=!1},O=(T)=>{let{domNode:Y}=w.getState();if(Z.current=Y?.getBoundingClientRect(),!Z.current)return;let k=T.target===z.current;if(!k&&!!T.target.closest(".nokey")||!u||!(i&&k||l)||T.button!==0||!T.isPrimary)return;T.target?.setPointerCapture?.(T.pointerId),D.current=!1;let{x:o,y:g}=Or(T.nativeEvent,Z.current);if(w.setState({userSelectionRect:{width:0,height:0,startX:o,startY:g,x:o,y:g}}),!k)T.stopPropagation(),T.preventDefault()},m=(T)=>{let{userSelectionRect:Y,transform:k,nodeLookup:I,edgeLookup:b,connectionLookup:o,triggerNodeChanges:g,triggerEdgeChanges:x,defaultEdgeOptions:lu,resetSelectedElements:_u}=w.getState();if(!Z.current||!Y)return;let{x:$u,y:ju}=Or(T.nativeEvent,Z.current),{startX:zu,startY:Wu}=Y;if(!D.current){let s=l?0:n;if(Math.hypot($u-zu,ju-Wu)<=s)return;_u(),y?.(T)}D.current=!0;let P={startX:zu,startY:Wu,x:$us.id)),E.current=new Set;let Ku=lu?.selectable??!0;for(let s of H.current){let Nu=o.get(s);if(!Nu)continue;for(let{edgeId:Eu}of Nu.values()){let Hu=b.get(Eu);if(Hu&&(Hu.selectable??Ku))E.current.add(Eu)}}if(!u9(e,H.current)){let s=Ay(I,H.current,!0);g(s)}if(!u9(uu,E.current)){let s=Ay(b,E.current);x(s)}w.setState({userSelectionRect:P,userSelectionActive:!0,nodesSelectionActive:!1})},X=(T)=>{if(T.button!==0)return;if(T.target?.releasePointerCapture?.(T.pointerId),!L&&T.target===z.current&&w.getState().userSelectionRect)h?.(T);if(w.setState({userSelectionActive:!1,userSelectionRect:null}),D.current)t?.(T),w.setState({nodesSelectionActive:H.current.size>0})},v=r===!0||Array.isArray(r)&&r.includes(0);return ru.jsxs("div",{className:Sl(["react-flow__pane",{draggable:v,dragging:N,selection:u}]),onClick:W?void 0:F9(h,z),onContextMenu:F9(V,z),onWheel:F9(S,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:J,ref:z,style:c6,children:[Q,ru.jsx(mD,{})]})}function Q9({id:u,store:l,unselect:f=!1,nodeRef:r}){let{addSelectedNodes:n,unselectNodesAndEdges:i,multiSelectionActive:y,nodeLookup:t,onError:_}=l.getState(),c=t.get(u);if(!c){_?.("012",Ur.error012(u));return}if(l.setState({nodesSelectionActive:!1}),!c.selected)n([u]);else if(f||c.selected&&y)i({nodes:[c],edges:[]}),requestAnimationFrame(()=>r?.current?.blur())}function TW({nodeRef:u,disabled:l=!1,noDragClassName:f,handleSelector:r,nodeId:n,isSelectable:i,nodeClickDistance:y}){let t=El(),[_,c]=yu.useState(!1),A=yu.useRef();return yu.useEffect(()=>{A.current=zq({getStoreItems:()=>t.getState(),onNodeMouseDown:(j)=>{Q9({id:j,store:t,nodeRef:u})},onDragStart:()=>{c(!0)},onDragStop:()=>{c(!1)}})},[]),yu.useEffect(()=>{if(l||!u.current||!A.current)return;return A.current.update({noDragClassName:f,handleSelector:r,domNode:u.current,isSelectable:i,nodeId:n,nodeClickDistance:y}),()=>{A.current?.destroy()}},[f,r,l,i,u,n,y]),_}var MD=(u)=>(l)=>l.selected&&(l.draggable||u&&typeof l.draggable>"u");function EW(){let u=El();return yu.useCallback((f)=>{let{nodeExtent:r,snapToGrid:n,snapGrid:i,nodesDraggable:y,onError:t,updateNodePositions:_,nodeLookup:c,nodeOrigin:A}=u.getState(),j=new Map,F=MD(y),J=n?i[0]:5,Q=n?i[1]:5,w=f.direction.x*J*f.factor,L=f.direction.y*Q*f.factor;for(let[,U]of c){if(!F(U))continue;let N={x:U.internals.positionAbsolute.x+w,y:U.internals.positionAbsolute.y+L};if(n)N=ty(N,i);let{position:q,positionAbsolute:W}=g5({nodeId:U.id,nextPosition:N,nodeLookup:c,nodeExtent:r,nodeOrigin:A,onError:t});U.position=q,U.internals.positionAbsolute=W,j.set(U.id,U)}_(j)},[])}var q9=yu.createContext(null),RD=q9.Provider;q9.Consumer;var ZW=()=>{return yu.useContext(q9)},xD=(u)=>({connectOnClick:u.connectOnClick,noPanClassName:u.noPanClassName,rfId:u.rfId}),hD=(u,l,f)=>(r)=>{let{connectionClickStartHandle:n,connectionMode:i,connection:y}=r,{fromHandle:t,toHandle:_,isValid:c}=y,A=_?.nodeId===u&&_?.id===l&&_?.type===f;return{connectingFrom:t?.nodeId===u&&t?.id===l&&t?.type===f,connectingTo:A,clickConnecting:n?.nodeId===u&&n?.id===l&&n?.type===f,isPossibleEndHandle:i===Yn.Strict?t?.type!==f:u!==t?.nodeId||l!==t?.id,connectionInProcess:!!t,clickConnectionInProcess:!!n,valid:A&&c}};function bD({type:u="source",position:l=Lu.Top,isValidConnection:f,isConnectable:r=!0,isConnectableStart:n=!0,isConnectableEnd:i=!0,id:y,onConnect:t,children:_,className:c,onMouseDown:A,onTouchStart:j,...F},J){let Q=y||null,w=u==="target",L=El(),U=ZW(),{connectOnClick:N,noPanClassName:q,rfId:W}=fl(xD,Gl),{connectingFrom:z,connectingTo:Z,clickConnecting:H,isPossibleEndHandle:E,connectionInProcess:D,clickConnectionInProcess:h,valid:V}=fl(hD(U,Q,u),Gl);if(!U)L.getState().onError?.("010",Ur.error010());let S=(m)=>{let{defaultEdgeOptions:X,onConnect:v,hasDefaultEdges:T}=L.getState(),Y={...X,...m};if(T){let{edges:k,setEdges:I}=L.getState();I(i9(Y,k))}v?.(Y),t?.(Y)},p=(m)=>{if(!U)return;let X=r9(m.nativeEvent);if(n&&(X&&m.button===0||!X)){let v=L.getState();f6.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:w,handleId:Q,nodeId:U,flowId:v.rfId,panBy:v.panBy,cancelConnection:v.cancelConnection,onConnectStart:v.onConnectStart,onConnectEnd:(...T)=>L.getState().onConnectEnd?.(...T),updateConnection:v.updateConnection,onConnect:S,isValidConnection:f||((...T)=>L.getState().isValidConnection?.(...T)??!0),getTransform:()=>L.getState().transform,getFromHandle:()=>L.getState().connection.fromHandle,autoPanSpeed:v.autoPanSpeed,dragThreshold:v.connectionDragThreshold})}if(X)A?.(m);else j?.(m)},O=(m)=>{let{onClickConnectStart:X,onClickConnectEnd:v,connectionClickStartHandle:T,connectionMode:Y,isValidConnection:k,lib:I,rfId:b,nodeLookup:o,connection:g}=L.getState();if(!U||!T&&!n)return;if(!T){X?.(m.nativeEvent,{nodeId:U,handleId:Q,handleType:u}),L.setState({connectionClickStartHandle:{nodeId:U,type:u,id:Q}});return}let x=l9(m.target),lu=f||k,{connection:_u,isValid:$u}=f6.isValid(m.nativeEvent,{handle:{nodeId:U,id:Q,type:u},connectionMode:Y,fromNodeId:T.nodeId,fromHandleId:T.id||null,fromType:T.type,isValidConnection:lu,flowId:b,doc:x,lib:I,nodeLookup:o});if($u&&_u)S(_u);let ju=structuredClone(g);delete ju.inProgress,ju.toPosition=ju.toHandle?ju.toHandle.position:null,v?.(m,ju),L.setState({connectionClickStartHandle:null})};return ru.jsx("div",{"data-handleid":Q,"data-nodeid":U,"data-handlepos":l,"data-id":`${W}-${U}-${Q}-${u}`,className:Sl(["react-flow__handle",`react-flow__handle-${l}`,"nodrag",q,c,{source:!w,target:w,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:J,...F,children:_})}var Ri=yu.memo(GW(bD));function vD({data:u,isConnectable:l,sourcePosition:f=Lu.Bottom}){return ru.jsxs(ru.Fragment,{children:[u?.label,ru.jsx(Ri,{type:"source",position:f,isConnectable:l})]})}function kD({data:u,isConnectable:l,targetPosition:f=Lu.Top,sourcePosition:r=Lu.Bottom}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(Ri,{type:"target",position:f,isConnectable:l}),u?.label,ru.jsx(Ri,{type:"source",position:r,isConnectable:l})]})}function ID(){return null}function gD({data:u,isConnectable:l,targetPosition:f=Lu.Top}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(Ri,{type:"target",position:f,isConnectable:l}),u?.label]})}var t6={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},tW={input:vD,default:kD,output:gD,group:ID};function sD(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 aD=(u)=>{let{width:l,height:f,x:r,y:n}=iy(u.nodeLookup,{filter:(i)=>!!i.selected});return{width:Zr(l)?l:null,height:Zr(f)?f:null,userSelectionActive:u.userSelectionActive,transformString:`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]}) translate(${r}px,${n}px)`}};function oD({onSelectionContextMenu:u,noPanClassName:l,disableKeyboardA11y:f}){let r=El(),{width:n,height:i,transformString:y,userSelectionActive:t}=fl(aD,Gl),_=EW(),c=yu.useRef(null);yu.useEffect(()=>{if(!f)c.current?.focus({preventScroll:!0})},[f]);let A=!t&&n!==null&&i!==null;if(TW({nodeRef:c,disabled:!A}),!A)return null;let j=u?(J)=>{let Q=r.getState().nodes.filter((w)=>w.selected);u(J,Q)}:void 0,F=(J)=>{if(Object.prototype.hasOwnProperty.call(t6,J.key))J.preventDefault(),_({direction:t6[J.key],factor:J.shiftKey?4:1})};return ru.jsx("div",{className:Sl(["react-flow__nodesselection","react-flow__container",l]),style:{transform:y},children:ru.jsx("div",{ref:c,className:"react-flow__nodesselection-rect",onContextMenu:j,tabIndex:f?void 0:-1,onKeyDown:f?void 0:F,style:{width:n,height:i}})})}var _W=typeof window<"u"?window:void 0,dD=(u)=>{return{nodesSelectionActive:u.nodesSelectionActive,userSelectionActive:u.userSelectionActive}};function OW({children:u,onPaneClick:l,onPaneMouseEnter:f,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,paneClickDistance:t,deleteKeyCode:_,selectionKeyCode:c,selectionOnDrag:A,selectionMode:j,onSelectionStart:F,onSelectionEnd:J,multiSelectionKeyCode:Q,panActivationKeyCode:w,zoomActivationKeyCode:L,elementsSelectable:U,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:W,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:E,defaultViewport:D,translateExtent:h,minZoom:V,maxZoom:S,preventScrolling:p,onSelectionContextMenu:O,noWheelClassName:m,noPanClassName:X,disableKeyboardA11y:v,onViewportChange:T,isControlledViewport:Y}){let{nodesSelectionActive:k,userSelectionActive:I}=fl(dD,Gl),b=H_(c,{target:_W}),o=H_(w,{target:_W}),g=o||E,x=o||W,lu=A&&g!==!0,_u=b||I||lu;return DD({deleteKeyCode:_,multiSelectionKeyCode:Q}),ru.jsx(YD,{onPaneContextMenu:i,elementsSelectable:U,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:x,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:!b&&g,defaultViewport:D,translateExtent:h,minZoom:V,maxZoom:S,zoomActivationKeyCode:L,preventScrolling:p,noWheelClassName:m,noPanClassName:X,onViewportChange:T,isControlledViewport:Y,paneClickDistance:t,selectionOnDrag:lu,children:ru.jsxs(CD,{onSelectionStart:F,onSelectionEnd:J,onPaneClick:l,onPaneMouseEnter:f,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,panOnDrag:g,isSelecting:!!_u,selectionMode:j,selectionKeyPressed:b,paneClickDistance:t,selectionOnDrag:lu,children:[u,k&&ru.jsx(oD,{onSelectionContextMenu:O,noPanClassName:X,disableKeyboardA11y:v})]})})}OW.displayName="FlowRenderer";var eD=yu.memo(OW),uX=(u)=>(l)=>{return u?kc(l.nodeLookup,{x:0,y:0,width:l.width,height:l.height},l.transform,!0).map((f)=>f.id):Array.from(l.nodeLookup.keys())};function lX(u){return fl(yu.useCallback(uX(u),[u]),Gl)}var fX=(u)=>u.updateNodeInternals;function rX(){let u=fl(fX),[l]=yu.useState(()=>{if(typeof ResizeObserver>"u")return null;return new ResizeObserver((f)=>{let r=new Map;f.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()=>{l?.disconnect()}},[l]),l}function nX({node:u,nodeType:l,hasDimensions:f,resizeObserver:r}){let n=El(),i=yu.useRef(null),y=yu.useRef(null),t=yu.useRef(u.sourcePosition),_=yu.useRef(u.targetPosition),c=yu.useRef(l),A=f&&!!u.internals.handleBounds;return yu.useEffect(()=>{if(i.current&&!u.hidden&&(!A||y.current!==i.current)){if(y.current)r?.unobserve(y.current);r?.observe(i.current),y.current=i.current}},[A,u.hidden]),yu.useEffect(()=>{return()=>{if(y.current)r?.unobserve(y.current),y.current=null}},[]),yu.useEffect(()=>{if(i.current){let j=c.current!==l,F=t.current!==u.sourcePosition,J=_.current!==u.targetPosition;if(j||F||J)c.current=l,t.current=u.sourcePosition,_.current=u.targetPosition,n.getState().updateNodeInternals(new Map([[u.id,{id:u.id,nodeElement:i.current,force:!0}]]))}},[u.id,l,u.sourcePosition,u.targetPosition]),i}function iX({id:u,onClick:l,onMouseEnter:f,onMouseMove:r,onMouseLeave:n,onContextMenu:i,onDoubleClick:y,nodesDraggable:t,elementsSelectable:_,nodesConnectable:c,nodesFocusable:A,resizeObserver:j,noDragClassName:F,noPanClassName:J,disableKeyboardA11y:Q,rfId:w,nodeTypes:L,nodeClickDistance:U,onError:N}){let{node:q,internals:W,isParent:z}=fl(($u)=>{let ju=$u.nodeLookup.get(u),zu=$u.parentLookup.has(u);return{node:ju,internals:ju.internals,isParent:zu}},Gl),Z=q.type||"default",H=L?.[Z]||tW[Z];if(H===void 0)N?.("003",Ur.error003(Z)),Z="default",H=L?.default||tW.default;let E=!!(q.draggable||t&&typeof q.draggable>"u"),D=!!(q.selectable||_&&typeof q.selectable>"u"),h=!!(q.connectable||c&&typeof q.connectable>"u"),V=!!(q.focusable||A&&typeof q.focusable>"u"),S=El(),p=d5(q),O=nX({node:q,nodeType:Z,hasDimensions:p,resizeObserver:j}),m=TW({nodeRef:O,disabled:q.hidden||!E,noDragClassName:F,handleSelector:q.dragHandle,nodeId:u,isSelectable:D,nodeClickDistance:U}),X=EW();if(q.hidden)return null;let v=A0(q),T=sD(q),Y=D||E||l||f||r||n,k=f?($u)=>f($u,{...W.userNode}):void 0,I=r?($u)=>r($u,{...W.userNode}):void 0,b=n?($u)=>n($u,{...W.userNode}):void 0,o=i?($u)=>i($u,{...W.userNode}):void 0,g=y?($u)=>y($u,{...W.userNode}):void 0,x=($u)=>{let{selectNodesOnDrag:ju,nodeDragThreshold:zu}=S.getState();if(D&&(!ju||!E||zu>0))Q9({id:u,store:S,nodeRef:O});if(l)l($u,{...W.userNode})},lu=($u)=>{if(f9($u.nativeEvent)||Q)return;if(R5.includes($u.key)&&D){let ju=$u.key==="Escape";Q9({id:u,store:S,unselect:ju,nodeRef:O})}else if(E&&q.selected&&Object.prototype.hasOwnProperty.call(t6,$u.key)){$u.preventDefault();let{ariaLabelConfig:ju}=S.getState();S.setState({ariaLiveMessage:ju["node.a11yDescription.ariaLiveMessage"]({direction:$u.key.replace("Arrow","").toLowerCase(),x:~~W.positionAbsolute.x,y:~~W.positionAbsolute.y})}),X({direction:t6[$u.key],factor:$u.shiftKey?4:1})}},_u=()=>{if(Q||!O.current?.matches(":focus-visible"))return;let{transform:$u,width:ju,height:zu,autoPanOnNodeFocus:Wu,setCenter:P}=S.getState();if(!Wu)return;if(!(kc(new Map([[u,q]]),{x:0,y:0,width:ju,height:zu},$u,!0).length>0))P(q.position.x+v.width/2,q.position.y+v.height/2,{zoom:$u[2]})};return ru.jsx("div",{className:Sl(["react-flow__node",`react-flow__node-${Z}`,{[J]: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:Y?"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?lu: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:`${WW}-${w}`,"aria-label":q.ariaLabel,...q.domAttributes,children:ru.jsx(RD,{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 yX=yu.memo(iX),tX=(u)=>({nodesDraggable:u.nodesDraggable,nodesConnectable:u.nodesConnectable,nodesFocusable:u.nodesFocusable,elementsSelectable:u.elementsSelectable,onError:u.onError});function HW(u){let{nodesDraggable:l,nodesConnectable:f,nodesFocusable:r,elementsSelectable:n,onError:i}=fl(tX,Gl),y=lX(u.onlyRenderVisibleElements),t=rX();return ru.jsx("div",{className:"react-flow__nodes",style:c6,children:y.map((_)=>{return ru.jsx(yX,{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:t,nodesDraggable:l,nodesConnectable:f,nodesFocusable:r,elementsSelectable:n,nodeClickDistance:u.nodeClickDistance,onError:i},_)})})}HW.displayName="NodeRenderer";var _X=yu.memo(HW);function $X(u){return fl(yu.useCallback((f)=>{if(!u)return f.edges.map((n)=>n.id);let r=[];if(f.width&&f.height)for(let n of f.edges){let i=f.nodeLookup.get(n.source),y=f.nodeLookup.get(n.target);if(i&&y&&Jq({sourceNode:i,targetNode:y,width:f.width,height:f.height,transform:f.transform}))r.push(n.id)}return r},[u]),Gl)}var cX=({color:u="none",strokeWidth:l=1})=>{let f={strokeWidth:l,...u&&{stroke:u}};return ru.jsx("polyline",{className:"arrow",style:f,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},AX=({color:u="none",strokeWidth:l=1})=>{let f={strokeWidth:l,...u&&{stroke:u,fill:u}};return ru.jsx("polyline",{className:"arrowclosed",style:f,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},$W={[pn.Arrow]:cX,[pn.ArrowClosed]:AX};function jX(u){let l=El();return yu.useMemo(()=>{if(!Object.prototype.hasOwnProperty.call($W,u))return l.getState().onError?.("009",Ur.error009(u)),null;return $W[u]},[u])}var FX=({id:u,type:l,color:f,width:r=12.5,height:n=12.5,markerUnits:i="strokeWidth",strokeWidth:y,orient:t="auto-start-reverse"})=>{let _=jX(l);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:t,refX:"0",refY:"0",children:ru.jsx(_,{color:f,strokeWidth:y})})},BW=({defaultColor:u,rfId:l})=>{let f=fl((i)=>i.edges),r=fl((i)=>i.defaultEdgeOptions),n=yu.useMemo(()=>{return Nq(f,{id:l,defaultColor:u,defaultMarkerStart:r?.markerStart,defaultMarkerEnd:r?.markerEnd})},[f,r,l,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))})})};BW.displayName="MarkerDefinitions";var UX=yu.memo(BW);function VW({x:u,y:l,label:f,labelStyle:r,labelShowBg:n=!0,labelBgStyle:i,labelBgPadding:y=[2,4],labelBgBorderRadius:t=2,children:_,className:c,...A}){let[j,F]=yu.useState({x:1,y:0,width:0,height:0}),J=Sl(["react-flow__edge-textwrapper",c]),Q=yu.useRef(null);if(yu.useEffect(()=>{if(Q.current){let w=Q.current.getBBox();F({x:w.x,y:w.y,width:w.width,height:w.height})}},[f]),!f)return null;return ru.jsxs("g",{transform:`translate(${u-j.width/2} ${l-j.height/2})`,className:J,visibility:j.width?"visible":"hidden",...A,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:t,ry:t}),ru.jsx("text",{className:"react-flow__edge-text",y:j.height/2,dy:"0.3em",ref:Q,style:r,children:f}),_]})}VW.displayName="EdgeText";var JX=yu.memo(VW);function jy({path:u,labelX:l,labelY:f,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:t,labelBgBorderRadius:_,interactionWidth:c=20,...A}){return ru.jsxs(ru.Fragment,{children:[ru.jsx("path",{...A,d:u,fill:"none",className:Sl(["react-flow__edge-path",A.className])}),c?ru.jsx("path",{d:u,fill:"none",strokeOpacity:0,strokeWidth:c,className:"react-flow__edge-interaction"}):null,r&&Zr(l)&&Zr(f)?ru.jsx(JX,{x:l,y:f,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:t,labelBgBorderRadius:_}):null]})}function cW({pos:u,x1:l,y1:f,x2:r,y2:n}){if(u===Lu.Left||u===Lu.Right)return[0.5*(l+r),f];return[l,0.5*(f+n)]}function DW({sourceX:u,sourceY:l,sourcePosition:f=Lu.Bottom,targetX:r,targetY:n,targetPosition:i=Lu.Top}){let[y,t]=cW({pos:f,x1:u,y1:l,x2:r,y2:n}),[_,c]=cW({pos:i,x1:r,y1:n,x2:u,y2:l}),[A,j,F,J]=ac({sourceX:u,sourceY:l,targetX:r,targetY:n,sourceControlX:y,sourceControlY:t,targetControlX:_,targetControlY:c});return[`M${u},${l} C${y},${t} ${_},${c} ${r},${n}`,A,j,F,J]}function XW(u){return yu.memo(({id:l,sourceX:f,sourceY:r,targetX:n,targetY:i,sourcePosition:y,targetPosition:t,label:_,labelStyle:c,labelShowBg:A,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:J,style:Q,markerEnd:w,markerStart:L,interactionWidth:U})=>{let[N,q,W]=DW({sourceX:f,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:t}),z=u.isInternal?void 0:l;return ru.jsx(jy,{id:z,path:N,labelX:q,labelY:W,label:_,labelStyle:c,labelShowBg:A,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:J,style:Q,markerEnd:w,markerStart:L,interactionWidth:U})})}var QX=XW({isInternal:!1}),SW=XW({isInternal:!0});QX.displayName="SimpleBezierEdge";SW.displayName="SimpleBezierEdgeInternal";function YW(u){return yu.memo(({id:l,sourceX:f,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:t,labelShowBg:_,labelBgStyle:c,labelBgPadding:A,labelBgBorderRadius:j,style:F,sourcePosition:J=Lu.Bottom,targetPosition:Q=Lu.Top,markerEnd:w,markerStart:L,pathOptions:U,interactionWidth:N})=>{let[q,W,z]=O_({sourceX:f,sourceY:r,sourcePosition:J,targetX:n,targetY:i,targetPosition:Q,borderRadius:U?.borderRadius,offset:U?.offset,stepPosition:U?.stepPosition}),Z=u.isInternal?void 0:l;return ru.jsx(jy,{id:Z,path:q,labelX:W,labelY:z,label:y,labelStyle:t,labelShowBg:_,labelBgStyle:c,labelBgPadding:A,labelBgBorderRadius:j,style:F,markerEnd:w,markerStart:L,interactionWidth:N})})}var pW=YW({isInternal:!1}),mW=YW({isInternal:!0});pW.displayName="SmoothStepEdge";mW.displayName="SmoothStepEdgeInternal";function PW(u){return yu.memo(({id:l,...f})=>{let r=u.isInternal?void 0:l;return ru.jsx(pW,{...f,id:r,pathOptions:yu.useMemo(()=>({borderRadius:0,offset:f.pathOptions?.offset}),[f.pathOptions?.offset])})})}var NX=PW({isInternal:!1}),CW=PW({isInternal:!0});NX.displayName="StepEdge";CW.displayName="StepEdgeInternal";function MW(u){return yu.memo(({id:l,sourceX:f,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:t,labelShowBg:_,labelBgStyle:c,labelBgPadding:A,labelBgBorderRadius:j,style:F,markerEnd:J,markerStart:Q,interactionWidth:w})=>{let[L,U,N]=dc({sourceX:f,sourceY:r,targetX:n,targetY:i}),q=u.isInternal?void 0:l;return ru.jsx(jy,{id:q,path:L,labelX:U,labelY:N,label:y,labelStyle:t,labelShowBg:_,labelBgStyle:c,labelBgPadding:A,labelBgBorderRadius:j,style:F,markerEnd:J,markerStart:Q,interactionWidth:w})})}var qX=MW({isInternal:!1}),RW=MW({isInternal:!0});qX.displayName="StraightEdge";RW.displayName="StraightEdgeInternal";function xW(u){return yu.memo(({id:l,sourceX:f,sourceY:r,targetX:n,targetY:i,sourcePosition:y=Lu.Bottom,targetPosition:t=Lu.Top,label:_,labelStyle:c,labelShowBg:A,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:J,style:Q,markerEnd:w,markerStart:L,pathOptions:U,interactionWidth:N})=>{let[q,W,z]=oc({sourceX:f,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:t,curvature:U?.curvature}),Z=u.isInternal?void 0:l;return ru.jsx(jy,{id:Z,path:q,labelX:W,labelY:z,label:_,labelStyle:c,labelShowBg:A,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:J,style:Q,markerEnd:w,markerStart:L,interactionWidth:N})})}var WX=xW({isInternal:!1}),hW=xW({isInternal:!0});WX.displayName="BezierEdge";hW.displayName="BezierEdgeInternal";var AW={default:hW,straight:RW,step:CW,smoothstep:mW,simplebezier:SW},jW={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null},wX=(u,l,f)=>{if(f===Lu.Left)return u-l;if(f===Lu.Right)return u+l;return u},LX=(u,l,f)=>{if(f===Lu.Top)return u-l;if(f===Lu.Bottom)return u+l;return u},FW="react-flow__edgeupdater";function UW({position:u,centerX:l,centerY:f,radius:r=10,onMouseDown:n,onMouseEnter:i,onMouseOut:y,type:t}){return ru.jsx("circle",{onMouseDown:n,onMouseEnter:i,onMouseOut:y,className:Sl([FW,`${FW}-${t}`]),cx:wX(l,r,u),cy:LX(f,r,u),r,stroke:"transparent",fill:"transparent"})}function KX({isReconnectable:u,reconnectRadius:l,edge:f,sourceX:r,sourceY:n,targetX:i,targetY:y,sourcePosition:t,targetPosition:_,onReconnect:c,onReconnectStart:A,onReconnectEnd:j,setReconnecting:F,setUpdateHover:J}){let Q=El(),w=(W,z)=>{if(W.button!==0)return;let{autoPanOnConnect:Z,domNode:H,connectionMode:E,connectionRadius:D,lib:h,onConnectStart:V,cancelConnection:S,nodeLookup:p,rfId:O,panBy:m,updateConnection:X}=Q.getState(),v=z.type==="target",T=(I,b)=>{F(!1),j?.(I,f,z.type,b)},Y=(I)=>c?.(f,I),k=(I,b)=>{F(!0),A?.(W,f,z.type),V?.(I,b)};f6.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:S,panBy:m,isValidConnection:(...I)=>Q.getState().isValidConnection?.(...I)??!0,onConnect:Y,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})},L=(W)=>w(W,{nodeId:f.target,id:f.targetHandle??null,type:"target"}),U=(W)=>w(W,{nodeId:f.source,id:f.sourceHandle??null,type:"source"}),N=()=>J(!0),q=()=>J(!1);return ru.jsxs(ru.Fragment,{children:[(u===!0||u==="source")&&ru.jsx(UW,{position:t,centerX:r,centerY:n,radius:l,onMouseDown:L,onMouseEnter:N,onMouseOut:q,type:"source"}),(u===!0||u==="target")&&ru.jsx(UW,{position:_,centerX:i,centerY:y,radius:l,onMouseDown:U,onMouseEnter:N,onMouseOut:q,type:"target"})]})}function GX({id:u,edgesFocusable:l,edgesReconnectable:f,elementsSelectable:r,onClick:n,onDoubleClick:i,onContextMenu:y,onMouseEnter:t,onMouseMove:_,onMouseLeave:c,reconnectRadius:A,onReconnect:j,onReconnectStart:F,onReconnectEnd:J,rfId:Q,edgeTypes:w,noPanClassName:L,onError:U,disableKeyboardA11y:N}){let q=fl((P)=>P.edgeLookup.get(u)),W=fl((P)=>P.defaultEdgeOptions);q=W?{...W,...q}:q;let z=q.type||"default",Z=w?.[z]||AW[z];if(Z===void 0)U?.("011",Ur.error011(z)),z="default",Z=w?.default||AW.default;let H=!!(q.focusable||l&&typeof q.focusable>"u"),E=typeof j<"u"&&(q.reconnectable||f&&typeof q.reconnectable>"u"),D=!!(q.selectable||r&&typeof q.selectable>"u"),h=yu.useRef(null),[V,S]=yu.useState(!1),[p,O]=yu.useState(!1),m=El(),{zIndex:X,sourceX:v,sourceY:T,targetX:Y,targetY:k,sourcePosition:I,targetPosition:b}=fl(yu.useCallback((P)=>{let e=P.nodeLookup.get(q.source),uu=P.nodeLookup.get(q.target);if(!e||!uu)return{zIndex:q.zIndex,...jW};let Ku=Qq({id:u,sourceNode:e,targetNode:uu,sourceHandle:q.sourceHandle||null,targetHandle:q.targetHandle||null,connectionMode:P.connectionMode,onError:U});return{zIndex:Uq({selected:q.selected,zIndex:q.zIndex,sourceNode:e,targetNode:uu,elevateOnSelect:P.elevateEdgesOnSelect,zIndexMode:P.zIndexMode}),...Ku||jW}},[q.source,q.target,q.sourceHandle,q.targetHandle,q.selected,q.zIndex]),Gl),o=yu.useMemo(()=>q.markerStart?`url('#${ec(q.markerStart,Q)}')`:void 0,[q.markerStart,Q]),g=yu.useMemo(()=>q.markerEnd?`url('#${ec(q.markerEnd,Q)}')`:void 0,[q.markerEnd,Q]);if(q.hidden||v===null||T===null||Y===null||k===null)return null;let x=(P)=>{let{addSelectedEdges:e,unselectNodesAndEdges:uu,multiSelectionActive:Ku}=m.getState();if(D)if(m.setState({nodesSelectionActive:!1}),q.selected&&Ku)uu({nodes:[],edges:[q]}),h.current?.blur();else e([u]);if(n)n(P,q)},lu=i?(P)=>{i(P,{...q})}:void 0,_u=y?(P)=>{y(P,{...q})}:void 0,$u=t?(P)=>{t(P,{...q})}:void 0,ju=_?(P)=>{_(P,{...q})}:void 0,zu=c?(P)=>{c(P,{...q})}:void 0,Wu=(P)=>{if(!N&&R5.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:Sl(["react-flow__edge",`react-flow__edge-${z}`,q.className,L,{selected:q.selected,animated:q.animated,inactive:!D&&!n,updating:V,selectable:D}]),onClick:x,onDoubleClick:lu,onContextMenu:_u,onMouseEnter:$u,onMouseMove:ju,onMouseLeave:zu,onKeyDown:H?Wu: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?`${wW}-${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:Y,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(KX,{edge:q,isReconnectable:E,reconnectRadius:A,onReconnect:j,onReconnectStart:F,onReconnectEnd:J,sourceX:v,sourceY:T,targetX:Y,targetY:k,sourcePosition:I,targetPosition:b,setUpdateHover:S,setReconnecting:O})]})})}var zX=yu.memo(GX),TX=(u)=>({edgesFocusable:u.edgesFocusable,edgesReconnectable:u.edgesReconnectable,elementsSelectable:u.elementsSelectable,connectionMode:u.connectionMode,onError:u.onError});function bW({defaultMarkerColor:u,onlyRenderVisibleElements:l,rfId:f,edgeTypes:r,noPanClassName:n,onReconnect:i,onEdgeContextMenu:y,onEdgeMouseEnter:t,onEdgeMouseMove:_,onEdgeMouseLeave:c,onEdgeClick:A,reconnectRadius:j,onEdgeDoubleClick:F,onReconnectStart:J,onReconnectEnd:Q,disableKeyboardA11y:w}){let{edgesFocusable:L,edgesReconnectable:U,elementsSelectable:N,onError:q}=fl(TX,Gl),W=$X(l);return ru.jsxs("div",{className:"react-flow__edges",children:[ru.jsx(UX,{defaultColor:u,rfId:f}),W.map((z)=>{return ru.jsx(zX,{id:z,edgesFocusable:L,edgesReconnectable:U,elementsSelectable:N,noPanClassName:n,onReconnect:i,onContextMenu:y,onMouseEnter:t,onMouseMove:_,onMouseLeave:c,onClick:A,reconnectRadius:j,onDoubleClick:F,onReconnectStart:J,onReconnectEnd:Q,rfId:f,onError:q,edgeTypes:r,disableKeyboardA11y:w},z)})]})}bW.displayName="EdgeRenderer";var EX=yu.memo(bW),ZX=(u)=>`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]})`;function OX({children:u}){let l=fl(ZX);return ru.jsx("div",{className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:l},children:u})}function HX(u){let l=N9(),f=yu.useRef(!1);yu.useEffect(()=>{if(!f.current&&l.viewportInitialized&&u)setTimeout(()=>u(l),1),f.current=!0},[u,l.viewportInitialized])}var BX=(u)=>u.panZoom?.syncViewport;function VX(u){let l=fl(BX),f=El();return yu.useEffect(()=>{if(u)l?.(u),f.setState({transform:[u.x,u.y,u.zoom]})},[u,l]),null}function JW(u){return u.connection.inProgress?{...u.connection,to:_y(u.connection.to,u.transform)}:{...u.connection}}function DX(u){if(u)return(f)=>{let r=JW(f);return u(r)};return JW}function XX(u){let l=DX(u);return fl(l,Gl)}var SX=(u)=>({nodesConnectable:u.nodesConnectable,isValid:u.connection.isValid,inProgress:u.connection.inProgress,width:u.width,height:u.height});function YX({containerStyle:u,style:l,type:f,component:r}){let{nodesConnectable:n,width:i,height:y,isValid:t,inProgress:_}=fl(SX,Gl);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:Sl(["react-flow__connection",b5(t)]),children:ru.jsx(vW,{style:l,type:f,CustomComponent:r,isValid:t})})})}var vW=({style:u,type:l=c0.Bezier,CustomComponent:f,isValid:r})=>{let{inProgress:n,from:i,fromNode:y,fromHandle:t,fromPosition:_,to:c,toNode:A,toHandle:j,toPosition:F,pointer:J}=XX();if(!n)return;if(f)return ru.jsx(f,{connectionLineType:l,connectionLineStyle:u,fromNode:y,fromHandle:t,fromX:i.x,fromY:i.y,toX:c.x,toY:c.y,fromPosition:_,toPosition:F,connectionStatus:b5(r),toNode:A,toHandle:j,pointer:J});let Q="",w={sourceX:i.x,sourceY:i.y,sourcePosition:_,targetX:c.x,targetY:c.y,targetPosition:F};switch(l){case c0.Bezier:[Q]=oc(w);break;case c0.SimpleBezier:[Q]=DW(w);break;case c0.Step:[Q]=O_({...w,borderRadius:0});break;case c0.SmoothStep:[Q]=O_(w);break;default:[Q]=dc(w)}return ru.jsx("path",{d:Q,fill:"none",className:"react-flow__connection-path",style:u})};vW.displayName="ConnectionLine";var pX={};function QW(u=pX){let l=yu.useRef(u),f=El();yu.useEffect(()=>{},[u])}function mX(){let u=El(),l=yu.useRef(!1);yu.useEffect(()=>{},[])}function kW({nodeTypes:u,edgeTypes:l,onInit:f,onNodeClick:r,onEdgeClick:n,onNodeDoubleClick:i,onEdgeDoubleClick:y,onNodeMouseEnter:t,onNodeMouseMove:_,onNodeMouseLeave:c,onNodeContextMenu:A,onSelectionContextMenu:j,onSelectionStart:F,onSelectionEnd:J,connectionLineType:Q,connectionLineStyle:w,connectionLineComponent:L,connectionLineContainerStyle:U,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,deleteKeyCode:E,onlyRenderVisibleElements:D,elementsSelectable:h,defaultViewport:V,translateExtent:S,minZoom:p,maxZoom:O,preventScrolling:m,defaultMarkerColor:X,zoomOnScroll:v,zoomOnPinch:T,panOnScroll:Y,panOnScrollSpeed:k,panOnScrollMode:I,zoomOnDoubleClick:b,panOnDrag:o,onPaneClick:g,onPaneMouseEnter:x,onPaneMouseMove:lu,onPaneMouseLeave:_u,onPaneScroll:$u,onPaneContextMenu:ju,paneClickDistance:zu,nodeClickDistance:Wu,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:Ku,reconnectRadius:s,onReconnect:Nu,onReconnectStart:Eu,onReconnectEnd:Hu,noDragClassName:vu,noWheelClassName:ul,noPanClassName:mu,disableKeyboardA11y:Fl,nodeExtent:Uf,rfId:Ef,viewport:lf,onViewportChange:ol}){return QW(u),QW(l),mX(),HX(f),VX(lf),ru.jsx(eD,{onPaneClick:g,onPaneMouseEnter:x,onPaneMouseMove:lu,onPaneMouseLeave:_u,onPaneContextMenu:ju,onPaneScroll:$u,paneClickDistance:zu,deleteKeyCode:E,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,onSelectionStart:F,onSelectionEnd:J,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,elementsSelectable:h,zoomOnScroll:v,zoomOnPinch:T,zoomOnDoubleClick:b,panOnScroll:Y,panOnScrollSpeed:k,panOnScrollMode:I,panOnDrag:o,defaultViewport:V,translateExtent:S,minZoom:p,maxZoom:O,onSelectionContextMenu:j,preventScrolling:m,noDragClassName:vu,noWheelClassName:ul,noPanClassName:mu,disableKeyboardA11y:Fl,onViewportChange:ol,isControlledViewport:!!lf,children:ru.jsxs(OX,{children:[ru.jsx(EX,{edgeTypes:l,onEdgeClick:n,onEdgeDoubleClick:y,onReconnect:Nu,onReconnectStart:Eu,onReconnectEnd:Hu,onlyRenderVisibleElements:D,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:Ku,reconnectRadius:s,defaultMarkerColor:X,noPanClassName:mu,disableKeyboardA11y:Fl,rfId:Ef}),ru.jsx(YX,{style:w,type:Q,component:L,containerStyle:U}),ru.jsx("div",{className:"react-flow__edgelabel-renderer"}),ru.jsx(_X,{nodeTypes:u,onNodeClick:r,onNodeDoubleClick:i,onNodeMouseEnter:t,onNodeMouseMove:_,onNodeMouseLeave:c,onNodeContextMenu:A,nodeClickDistance:Wu,onlyRenderVisibleElements:D,noPanClassName:mu,noDragClassName:vu,disableKeyboardA11y:Fl,nodeExtent:Uf,rfId:Ef}),ru.jsx("div",{className:"react-flow__viewport-portal"})]})})}kW.displayName="GraphView";var PX=yu.memo(kW),NW=({nodes:u,edges:l,defaultNodes:f,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:t,minZoom:_=0.5,maxZoom:c=2,nodeOrigin:A,nodeExtent:j,zIndexMode:F="basic"}={})=>{let J=new Map,Q=new Map,w=new Map,L=new Map,U=r??l??[],N=f??u??[],q=A??[0,0],W=j??ny;c9(w,L,U);let{nodesInitialized:z}=u6(N,J,Q,{nodeOrigin:q,nodeExtent:W,zIndexMode:F}),Z=[0,0,1];if(y&&n&&i){let H=iy(J,{filter:(V)=>!!((V.width||V.initialWidth)&&(V.height||V.initialHeight))}),{x:E,y:D,zoom:h}=Z_(H,n,i,_,c,t?.padding??0.1);Z=[E,D,h]}return{rfId:"1",width:n??0,height:i??0,transform:Z,nodes:N,nodesInitialized:z,nodeLookup:J,parentLookup:Q,edges:U,edgeLookup:L,connectionLookup:w,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:f!==void 0,hasDefaultEdges:r!==void 0,panZoom:null,minZoom:_,maxZoom:c,translateExtent:ny,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:t,fitViewResolver:null,connection:{...h5},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:o5,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:x5,zIndexMode:F,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},CX=({nodes:u,edges:l,defaultNodes:f,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:t,minZoom:_,maxZoom:c,nodeOrigin:A,nodeExtent:j,zIndexMode:F})=>gq((J,Q)=>{async function w(){let{nodeLookup:L,panZoom:U,fitViewOptions:N,fitViewResolver:q,width:W,height:z,minZoom:Z,maxZoom:H}=Q();if(!U)return;await _q({nodes:L,width:W,height:z,panZoom:U,minZoom:Z,maxZoom:H},N),q?.resolve(!0),J({fitViewResolver:null})}return{...NW({nodes:u,edges:l,width:n,height:i,fitView:y,fitViewOptions:t,minZoom:_,maxZoom:c,nodeOrigin:A,nodeExtent:j,defaultNodes:f,defaultEdges:r,zIndexMode:F}),setNodes:(L)=>{let{nodeLookup:U,parentLookup:N,nodeOrigin:q,elevateNodesOnSelect:W,fitViewQueued:z,zIndexMode:Z,nodesSelectionActive:H}=Q(),{nodesInitialized:E,hasSelectedNodes:D}=u6(L,U,N,{nodeOrigin:q,nodeExtent:j,elevateNodesOnSelect:W,checkEquality:!0,zIndexMode:Z}),h=H&&D;if(z&&E)w(),J({nodes:L,nodesInitialized:E,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:h});else J({nodes:L,nodesInitialized:E,nodesSelectionActive:h})},setEdges:(L)=>{let{connectionLookup:U,edgeLookup:N}=Q();c9(U,N,L),J({edges:L})},setDefaultNodesAndEdges:(L,U)=>{if(L){let{setNodes:N}=Q();N(L),J({hasDefaultNodes:!0})}if(U){let{setEdges:N}=Q();N(U),J({hasDefaultEdges:!0})}},updateNodeInternals:(L)=>{let{triggerNodeChanges:U,nodeLookup:N,parentLookup:q,domNode:W,nodeOrigin:z,nodeExtent:Z,debug:H,fitViewQueued:E,zIndexMode:D}=Q(),{changes:h,updatedInternals:V}=Lq(L,N,q,W,z,Z,D);if(!V)return;if(Wq(N,q,{nodeOrigin:z,nodeExtent:Z,zIndexMode:D}),E)w(),J({fitViewQueued:!1,fitViewOptions:void 0});else J({});if(h?.length>0){if(H)console.log("React Flow: trigger node changes",h);U?.(h)}},updateNodePositions:(L,U=!1)=>{let N=[],q=[],{nodeLookup:W,triggerNodeChanges:z,connection:Z,updateConnection:H,onNodesChangeMiddlewareMap:E}=Q();for(let[D,h]of L){let V=W.get(D),S=!!(V?.expandParent&&V?.parentId&&h?.position),p={id:D,type:"position",position:S?{x:Math.max(0,h.position.x),y:Math.max(0,h.position.y)}:h.position,dragging:U};if(V&&Z.inProgress&&Z.fromNode.id===V.id){let O=mn(V,Z.fromHandle,Lu.Left,!0);H({...Z,from:O})}if(S&&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=l6(N,W,D,h);q.push(...V)}for(let D of E.values())q=D(q);z(q)},triggerNodeChanges:(L)=>{let{onNodesChange:U,setNodes:N,nodes:q,hasDefaultNodes:W,debug:z}=Q();if(L?.length){if(W){let Z=zD(L,q);N(Z)}if(z)console.log("React Flow: trigger node changes",L);U?.(L)}},triggerEdgeChanges:(L)=>{let{onEdgesChange:U,setEdges:N,edges:q,hasDefaultEdges:W,debug:z}=Q();if(L?.length){if(W){let Z=TD(L,q);N(Z)}if(z)console.log("React Flow: trigger edge changes",L);U?.(L)}},addSelectedNodes:(L)=>{let{multiSelectionActive:U,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(U){let Z=L.map((H)=>Mi(H,!0));W(Z);return}W(Ay(q,new Set([...L]),!0)),z(Ay(N))},addSelectedEdges:(L)=>{let{multiSelectionActive:U,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(U){let Z=L.map((H)=>Mi(H,!0));z(Z);return}z(Ay(N,new Set([...L]))),W(Ay(q,new Set,!0))},unselectNodesAndEdges:({nodes:L,edges:U}={})=>{let{edges:N,nodes:q,nodeLookup:W,triggerNodeChanges:z,triggerEdgeChanges:Z}=Q(),H=L?L:q,E=U?U:N,D=[];for(let V of H){if(!V.selected)continue;let S=W.get(V.id);if(S)S.selected=!1;D.push(Mi(V.id,!1))}let h=[];for(let V of E){if(!V.selected)continue;h.push(Mi(V.id,!1))}z(D),Z(h)},setMinZoom:(L)=>{let{panZoom:U,maxZoom:N}=Q();U?.setScaleExtent([L,N]),J({minZoom:L})},setMaxZoom:(L)=>{let{panZoom:U,minZoom:N}=Q();U?.setScaleExtent([N,L]),J({maxZoom:L})},setTranslateExtent:(L)=>{Q().panZoom?.setTranslateExtent(L),J({translateExtent:L})},resetSelectedElements:()=>{let{edges:L,nodes:U,triggerNodeChanges:N,triggerEdgeChanges:q,elementsSelectable:W}=Q();if(!W)return;let z=U.reduce((H,E)=>E.selected?[...H,Mi(E.id,!1)]:H,[]),Z=L.reduce((H,E)=>E.selected?[...H,Mi(E.id,!1)]:H,[]);N(z),q(Z)},setNodeExtent:(L)=>{let{nodes:U,nodeLookup:N,parentLookup:q,nodeOrigin:W,elevateNodesOnSelect:z,nodeExtent:Z,zIndexMode:H}=Q();if(L[0][0]===Z[0][0]&&L[0][1]===Z[0][1]&&L[1][0]===Z[1][0]&&L[1][1]===Z[1][1])return;u6(U,N,q,{nodeOrigin:W,nodeExtent:L,elevateNodesOnSelect:z,checkEquality:!1,zIndexMode:H}),J({nodeExtent:L})},panBy:(L)=>{let{transform:U,width:N,height:q,panZoom:W,translateExtent:z}=Q();return Kq({delta:L,panZoom:W,transform:U,translateExtent:z,width:N,height:q})},setCenter:async(L,U,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-L*H,y:W/2-U*H,zoom:H},{duration:N?.duration,ease:N?.ease,interpolate:N?.interpolate}),Promise.resolve(!0)},cancelConnection:()=>{J({connection:{...h5}})},updateConnection:(L)=>{J({connection:L})},reset:()=>J({...NW()})}},Object.is);function MX({initialNodes:u,initialEdges:l,defaultNodes:f,defaultEdges:r,initialWidth:n,initialHeight:i,initialMinZoom:y,initialMaxZoom:t,initialFitViewOptions:_,fitView:c,nodeOrigin:A,nodeExtent:j,zIndexMode:F,children:J}){let[Q]=yu.useState(()=>CX({nodes:u,edges:l,defaultNodes:f,defaultEdges:r,width:n,height:i,fitView:c,minZoom:y,maxZoom:t,fitViewOptions:_,nodeOrigin:A,nodeExtent:j,zIndexMode:F}));return ru.jsx(nD,{value:Q,children:ru.jsx(OD,{children:J})})}function RX({children:u,nodes:l,edges:f,defaultNodes:r,defaultEdges:n,width:i,height:y,fitView:t,fitViewOptions:_,minZoom:c,maxZoom:A,nodeOrigin:j,nodeExtent:F,zIndexMode:J}){if(yu.useContext(_6))return ru.jsx(ru.Fragment,{children:u});return ru.jsx(MX,{initialNodes:l,initialEdges:f,defaultNodes:r,defaultEdges:n,initialWidth:i,initialHeight:y,fitView:t,initialFitViewOptions:_,initialMinZoom:c,initialMaxZoom:A,nodeOrigin:j,nodeExtent:F,zIndexMode:J,children:u})}var xX={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function hX({nodes:u,edges:l,defaultNodes:f,defaultEdges:r,className:n,nodeTypes:i,edgeTypes:y,onNodeClick:t,onEdgeClick:_,onInit:c,onMove:A,onMoveStart:j,onMoveEnd:F,onConnect:J,onConnectStart:Q,onConnectEnd:w,onClickConnectStart:L,onClickConnectEnd:U,onNodeMouseEnter:N,onNodeMouseMove:q,onNodeMouseLeave:W,onNodeContextMenu:z,onNodeDoubleClick:Z,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onNodesDelete:h,onEdgesDelete:V,onDelete:S,onSelectionChange:p,onSelectionDragStart:O,onSelectionDrag:m,onSelectionDragStop:X,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:Y,onBeforeDelete:k,connectionMode:I,connectionLineType:b=c0.Bezier,connectionLineStyle:o,connectionLineComponent:g,connectionLineContainerStyle:x,deleteKeyCode:lu="Backspace",selectionKeyCode:_u="Shift",selectionOnDrag:$u=!1,selectionMode:ju=mi.Full,panActivationKeyCode:zu="Space",multiSelectionKeyCode:Wu=$y()?"Meta":"Control",zoomActivationKeyCode:P=$y()?"Meta":"Control",snapToGrid:e,snapGrid:uu,onlyRenderVisibleElements:Ku=!1,selectNodesOnDrag:s,nodesDraggable:Nu,autoPanOnNodeFocus:Eu,nodesConnectable:Hu,nodesFocusable:vu,nodeOrigin:ul=LW,edgesFocusable:mu,edgesReconnectable:Fl,elementsSelectable:Uf=!0,defaultViewport:Ef=ND,minZoom:lf=0.5,maxZoom:ol=2,translateExtent:Zf=ny,preventScrolling:mf=!0,nodeExtent:Au,defaultMarkerColor:su="#b1b1b7",zoomOnScroll:Jf=!0,zoomOnPinch:pu=!0,panOnScroll:ff=!1,panOnScrollSpeed:rf=0.5,panOnScrollMode:ur=x0.Free,zoomOnDoubleClick:nf=!0,panOnDrag:Of=!0,onPaneClick:N0,onPaneMouseEnter:lr,onPaneMouseMove:k0,onPaneMouseLeave:Ul,onPaneScroll:bi,onPaneContextMenu:fu,paneClickDistance:Bu=1,nodeClickDistance:Yu=0,children:au,onReconnect:_l,onReconnectStart:Pl,onReconnectEnd:yl,onEdgeContextMenu:Qf,onEdgeDoubleClick:Xr,onEdgeMouseEnter:Ky,onEdgeMouseMove:Zl,onEdgeMouseLeave:k_,reconnectRadius:m6=10,onNodesChange:zl,onEdgesChange:$7,noDragClassName:vl="nodrag",noWheelClassName:fr="nowheel",noPanClassName:vi="nopan",fitView:Gy,fitViewOptions:ki,connectOnClick:I_,attributionPosition:zy,proOptions:g_,defaultEdgeOptions:Pf,elevateNodesOnSelect:ar=!0,elevateEdgesOnSelect:s_=!1,disableKeyboardA11y:Ty=!1,autoPanOnConnect:Ey,autoPanOnNodeDrag:a_,autoPanSpeed:or,connectionRadius:o_,isValidConnection:pl,onError:P6,style:d_,id:qr,nodeDragThreshold:an,connectionDragThreshold:on,viewport:Ii,onViewportChange:dn,width:Zy,height:c7,colorMode:gi="light",debug:A7,onScroll:Oy,ariaLabelConfig:C6,zIndexMode:e_="basic",...M6},I0){let g0=qr||"1",en=LD(gi),Cf=yu.useCallback((Hy)=>{Hy.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),Oy?.(Hy)},[Oy]);return ru.jsx("div",{"data-testid":"rf__wrapper",...M6,onScroll:Cf,style:{...d_,...xX},ref:I0,className:Sl(["react-flow",n,en]),id:qr,role:"application",children:ru.jsxs(RX,{nodes:u,edges:l,width:Zy,height:c7,fitView:Gy,fitViewOptions:ki,minZoom:lf,maxZoom:ol,nodeOrigin:ul,nodeExtent:Au,zIndexMode:e_,children:[ru.jsx(wD,{nodes:u,edges:l,defaultNodes:f,defaultEdges:r,onConnect:J,onConnectStart:Q,onConnectEnd:w,onClickConnectStart:L,onClickConnectEnd:U,nodesDraggable:Nu,autoPanOnNodeFocus:Eu,nodesConnectable:Hu,nodesFocusable:vu,edgesFocusable:mu,edgesReconnectable:Fl,elementsSelectable:Uf,elevateNodesOnSelect:ar,elevateEdgesOnSelect:s_,minZoom:lf,maxZoom:ol,nodeExtent:Au,onNodesChange:zl,onEdgesChange:$7,snapToGrid:e,snapGrid:uu,connectionMode:I,translateExtent:Zf,connectOnClick:I_,defaultEdgeOptions:Pf,fitView:Gy,fitViewOptions:ki,onNodesDelete:h,onEdgesDelete:V,onDelete:S,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onSelectionDrag:m,onSelectionDragStart:O,onSelectionDragStop:X,onMove:A,onMoveStart:j,onMoveEnd:F,noPanClassName:vi,nodeOrigin:ul,rfId:g0,autoPanOnConnect:Ey,autoPanOnNodeDrag:a_,autoPanSpeed:or,onError:P6,connectionRadius:o_,isValidConnection:pl,selectNodesOnDrag:s,nodeDragThreshold:an,connectionDragThreshold:on,onBeforeDelete:k,debug:A7,ariaLabelConfig:C6,zIndexMode:e_}),ru.jsx(PX,{onInit:c,onNodeClick:t,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:$u,selectionMode:ju,deleteKeyCode:lu,multiSelectionKeyCode:Wu,panActivationKeyCode:zu,zoomActivationKeyCode:P,onlyRenderVisibleElements:Ku,defaultViewport:Ef,translateExtent:Zf,minZoom:lf,maxZoom:ol,preventScrolling:mf,zoomOnScroll:Jf,zoomOnPinch:pu,zoomOnDoubleClick:nf,panOnScroll:ff,panOnScrollSpeed:rf,panOnScrollMode:ur,panOnDrag:Of,onPaneClick:N0,onPaneMouseEnter:lr,onPaneMouseMove:k0,onPaneMouseLeave:Ul,onPaneScroll:bi,onPaneContextMenu:fu,paneClickDistance:Bu,nodeClickDistance:Yu,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:Y,onReconnect:_l,onReconnectStart:Pl,onReconnectEnd:yl,onEdgeContextMenu:Qf,onEdgeDoubleClick:Xr,onEdgeMouseEnter:Ky,onEdgeMouseMove:Zl,onEdgeMouseLeave:k_,reconnectRadius:m6,defaultMarkerColor:su,noDragClassName:vl,noWheelClassName:fr,noPanClassName:vi,rfId:g0,disableKeyboardA11y:Ty,nodeExtent:Au,viewport:Ii,onViewportChange:dn}),ru.jsx(QD,{onSelectionChange:p}),au,ru.jsx(AD,{proOptions:g_,position:zy}),ru.jsx(cD,{rfId:g0,disableKeyboardA11y:Ty})]})})}var IW=GW(hX);var pb=Ur.error014();function bX({dimensions:u,lineWidth:l,variant:f,className:r}){return ru.jsx("path",{strokeWidth:l,d:`M${u[0]/2} 0 V${u[1]} M0 ${u[1]/2} H${u[0]}`,className:Sl(["react-flow__background-pattern",f,r])})}function vX({radius:u,className:l}){return ru.jsx("circle",{cx:u,cy:u,r:u,className:Sl(["react-flow__background-pattern","dots",l])})}var Cn;(function(u){u.Lines="lines",u.Dots="dots",u.Cross="cross"})(Cn||(Cn={}));var kX={[Cn.Dots]:1,[Cn.Lines]:1,[Cn.Cross]:6},IX=(u)=>({transform:u.transform,patternId:`pattern-${u.rfId}`});function gW({id:u,variant:l=Cn.Dots,gap:f=20,size:r,lineWidth:n=1,offset:i=0,color:y,bgColor:t,style:_,className:c,patternClassName:A}){let j=yu.useRef(null),{transform:F,patternId:J}=fl(IX,Gl),Q=r||kX[l],w=l===Cn.Dots,L=l===Cn.Cross,U=Array.isArray(f)?f:[f,f],N=[U[0]*F[2]||1,U[1]*F[2]||1],q=Q*F[2],W=Array.isArray(i)?i:[i,i],z=L?[q,q]:N,Z=[W[0]*F[2]||1+z[0]/2,W[1]*F[2]||1+z[1]/2],H=`${J}${u?u:""}`;return ru.jsxs("svg",{className:Sl(["react-flow__background",c]),style:{..._,...c6,"--xy-background-color-props":t,"--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:w?ru.jsx(vX,{radius:q/2,className:A}):ru.jsx(bX,{dimensions:z,lineWidth:n,variant:l,className:A})}),ru.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${H})`})]})}gW.displayName="Background";var sW=yu.memo(gW);function gX(){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 sX(){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 aX(){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 oX(){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 dX(){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 y6({children:u,className:l,...f}){return ru.jsx("button",{type:"button",className:Sl(["react-flow__controls-button",l]),...f,children:u})}var eX=(u)=>({isInteractive:u.nodesDraggable||u.nodesConnectable||u.elementsSelectable,minZoomReached:u.transform[2]<=u.minZoom,maxZoomReached:u.transform[2]>=u.maxZoom,ariaLabelConfig:u.ariaLabelConfig});function aW({style:u,showZoom:l=!0,showFitView:f=!0,showInteractive:r=!0,fitViewOptions:n,onZoomIn:i,onZoomOut:y,onFitView:t,onInteractiveChange:_,className:c,children:A,position:j="bottom-left",orientation:F="vertical","aria-label":J}){let Q=El(),{isInteractive:w,minZoomReached:L,maxZoomReached:U,ariaLabelConfig:N}=fl(eX,Gl),{zoomIn:q,zoomOut:W,fitView:z}=N9(),Z=()=>{q(),i?.()},H=()=>{W(),y?.()},E=()=>{z(n),t?.()},D=()=>{Q.setState({nodesDraggable:!w,nodesConnectable:!w,elementsSelectable:!w}),_?.(!w)};return ru.jsxs($6,{className:Sl(["react-flow__controls",F==="horizontal"?"horizontal":"vertical",c]),position:j,style:u,"data-testid":"rf__controls","aria-label":J??N["controls.ariaLabel"],children:[l&&ru.jsxs(ru.Fragment,{children:[ru.jsx(y6,{onClick:Z,className:"react-flow__controls-zoomin",title:N["controls.zoomIn.ariaLabel"],"aria-label":N["controls.zoomIn.ariaLabel"],disabled:U,children:ru.jsx(gX,{})}),ru.jsx(y6,{onClick:H,className:"react-flow__controls-zoomout",title:N["controls.zoomOut.ariaLabel"],"aria-label":N["controls.zoomOut.ariaLabel"],disabled:L,children:ru.jsx(sX,{})})]}),f&&ru.jsx(y6,{className:"react-flow__controls-fitview",onClick:E,title:N["controls.fitView.ariaLabel"],"aria-label":N["controls.fitView.ariaLabel"],children:ru.jsx(aX,{})}),r&&ru.jsx(y6,{className:"react-flow__controls-interactive",onClick:D,title:N["controls.interactive.ariaLabel"],"aria-label":N["controls.interactive.ariaLabel"],children:w?ru.jsx(dX,{}):ru.jsx(oX,{})}),A]})}aW.displayName="Controls";var oW=yu.memo(aW);function uS({id:u,x:l,y:f,width:r,height:n,style:i,color:y,strokeColor:t,strokeWidth:_,className:c,borderRadius:A,shapeRendering:j,selected:F,onClick:J}){let{background:Q,backgroundColor:w}=i||{},L=y||Q||w;return ru.jsx("rect",{className:Sl(["react-flow__minimap-node",{selected:F},c]),x:l,y:f,rx:A,ry:A,width:r,height:n,style:{fill:L,stroke:t,strokeWidth:_},shapeRendering:j,onClick:J?(U)=>J(U,u):void 0})}var lS=yu.memo(uS),fS=(u)=>u.nodes.map((l)=>l.id),U9=(u)=>u instanceof Function?u:()=>u;function rS({nodeStrokeColor:u,nodeColor:l,nodeClassName:f="",nodeBorderRadius:r=5,nodeStrokeWidth:n,nodeComponent:i=lS,onClick:y}){let t=fl(fS,Gl),_=U9(l),c=U9(u),A=U9(f),j=typeof window>"u"||!!window.chrome?"crispEdges":"geometricPrecision";return ru.jsx(ru.Fragment,{children:t.map((F)=>ru.jsx(iS,{id:F,nodeColorFunc:_,nodeStrokeColorFunc:c,nodeClassNameFunc:A,nodeBorderRadius:r,nodeStrokeWidth:n,NodeComponent:i,onClick:y,shapeRendering:j},F))})}function nS({id:u,nodeColorFunc:l,nodeStrokeColorFunc:f,nodeClassNameFunc:r,nodeBorderRadius:n,nodeStrokeWidth:i,shapeRendering:y,NodeComponent:t,onClick:_}){let{node:c,x:A,y:j,width:F,height:J}=fl((Q)=>{let w=Q.nodeLookup.get(u);if(!w)return{node:void 0,x:0,y:0,width:0,height:0};let L=w.internals.userNode,{x:U,y:N}=w.internals.positionAbsolute,{width:q,height:W}=A0(L);return{node:L,x:U,y:N,width:q,height:W}},Gl);if(!c||c.hidden||!d5(c))return null;return ru.jsx(t,{x:A,y:j,width:F,height:J,style:c.style,selected:!!c.selected,className:r(c),color:l(c),borderRadius:n,strokeColor:f(c),strokeWidth:i,shapeRendering:y,onClick:_,id:c.id})}var iS=yu.memo(nS),yS=yu.memo(rS),tS=200,_S=150,$S=(u)=>!u.hidden,cS=(u)=>{let l={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:l,boundingRect:u.nodeLookup.size>0?s5(iy(u.nodeLookup,{filter:$S}),l):l,rfId:u.rfId,panZoom:u.panZoom,translateExtent:u.translateExtent,flowWidth:u.width,flowHeight:u.height,ariaLabelConfig:u.ariaLabelConfig}},AS="react-flow__minimap-desc";function dW({style:u,className:l,nodeStrokeColor:f,nodeColor:r,nodeClassName:n="",nodeBorderRadius:i=5,nodeStrokeWidth:y,nodeComponent:t,bgColor:_,maskColor:c,maskStrokeColor:A,maskStrokeWidth:j,position:F="bottom-right",onClick:J,onNodeClick:Q,pannable:w=!1,zoomable:L=!1,ariaLabel:U,inversePan:N,zoomStep:q=1,offsetScale:W=5}){let z=El(),Z=yu.useRef(null),{boundingRect:H,viewBB:E,rfId:D,panZoom:h,translateExtent:V,flowWidth:S,flowHeight:p,ariaLabelConfig:O}=fl(cS,Gl),m=u?.width??tS,X=u?.height??_S,v=H.width/m,T=H.height/X,Y=Math.max(v,T),k=Y*m,I=Y*X,b=W*Y,o=H.x-(k-H.width)/2-b,g=H.y-(I-H.height)/2-b,x=k+b*2,lu=I+b*2,_u=`${AS}-${D}`,$u=yu.useRef(0),ju=yu.useRef();$u.current=Y,yu.useEffect(()=>{if(Z.current&&h)return ju.current=Hq({domNode:Z.current,panZoom:h,getTransform:()=>z.getState().transform,getViewScale:()=>$u.current}),()=>{ju.current?.destroy()}},[h]),yu.useEffect(()=>{ju.current?.update({translateExtent:V,width:S,height:p,inversePan:N,pannable:w,zoomStep:q,zoomable:L})},[w,L,N,q,V,S,p]);let zu=J?(e)=>{let[uu,Ku]=ju.current?.pointer(e)||[0,0];J(e,{x:uu,y:Ku})}:void 0,Wu=Q?yu.useCallback((e,uu)=>{let Ku=z.getState().nodeLookup.get(uu).internals.userNode;Q(e,Ku)},[]):void 0,P=U??O["minimap.ariaLabel"];return ru.jsx($6,{position:F,style:{...u,"--xy-minimap-background-color-props":typeof _==="string"?_:void 0,"--xy-minimap-mask-background-color-props":typeof c==="string"?c:void 0,"--xy-minimap-mask-stroke-color-props":typeof A==="string"?A:void 0,"--xy-minimap-mask-stroke-width-props":typeof j==="number"?j*Y:void 0,"--xy-minimap-node-background-color-props":typeof r==="string"?r:void 0,"--xy-minimap-node-stroke-color-props":typeof f==="string"?f:void 0,"--xy-minimap-node-stroke-width-props":typeof y==="number"?y:void 0},className:Sl(["react-flow__minimap",l]),"data-testid":"rf__minimap",children:ru.jsxs("svg",{width:m,height:X,viewBox:`${o} ${g} ${x} ${lu}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":_u,ref:Z,onClick:zu,children:[P&&ru.jsx("title",{id:_u,children:P}),ru.jsx(yS,{onClick:Wu,nodeColor:r,nodeStrokeColor:f,nodeBorderRadius:i,nodeClassName:n,nodeStrokeWidth:y,nodeComponent:t}),ru.jsx("path",{className:"react-flow__minimap-mask",d:`M${o-b},${g-b}h${x+b*2}v${lu+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"})]})})}dW.displayName="MiniMap";var mb=yu.memo(dW),jS=(u)=>(l)=>u?`${Math.max(1/l.transform[2],1)}`:void 0,FS={[Pn.Line]:"right",[Pn.Handle]:"bottom-right"};function US({nodeId:u,position:l,variant:f=Pn.Handle,className:r,style:n=void 0,children:i,color:y,minWidth:t=10,minHeight:_=10,maxWidth:c=Number.MAX_VALUE,maxHeight:A=Number.MAX_VALUE,keepAspectRatio:j=!1,resizeDirection:F,autoScale:J=!0,shouldResize:Q,onResizeStart:w,onResize:L,onResizeEnd:U}){let N=ZW(),q=typeof u==="string"?u:N,W=El(),z=yu.useRef(null),Z=f===Pn.Handle,H=fl(yu.useCallback(jS(Z&&J),[Z,J]),Gl),E=yu.useRef(null),D=l??FS[f];yu.useEffect(()=>{if(!z.current||!q)return;if(!E.current)E.current=Sq({domNode:z.current,nodeId:q,getStoreItems:()=>{let{nodeLookup:V,transform:S,snapGrid:p,snapToGrid:O,nodeOrigin:m,domNode:X}=W.getState();return{nodeLookup:V,transform:S,snapGrid:p,snapToGrid:O,nodeOrigin:m,paneDomNode:X}},onChange:(V,S)=>{let{triggerNodeChanges:p,nodeLookup:O,parentLookup:m,nodeOrigin:X}=W.getState(),v=[],T={x:V.x,y:V.y},Y=O.get(q);if(Y&&Y.expandParent&&Y.parentId){let k=Y.origin??X,I=V.width??Y.measured.width??0,b=V.height??Y.measured.height??0,o={id:Y.id,parentId:Y.parentId,rect:{width:I,height:b,...e5({x:V.x??Y.position.x,y:V.y??Y.position.y},{width:I,height:b},Y.parentId,O,k)}},g=l6([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 S){let I={...k,type:"position"};v.push(I)}p(v)},onEnd:({width:V,height:S})=>{let p={id:q,type:"dimensions",resizing:!1,dimensions:{width:V,height:S}};W.getState().triggerNodeChanges([p])}});return E.current.update({controlPosition:D,boundaries:{minWidth:t,minHeight:_,maxWidth:c,maxHeight:A},keepAspectRatio:j,resizeDirection:F,onResizeStart:w,onResize:L,onResizeEnd:U,shouldResize:Q}),()=>{E.current?.destroy()}},[D,t,_,c,A,j,w,L,U,Q]);let h=D.split("-");return ru.jsx("div",{className:Sl(["react-flow__resize-control","nodrag",...h,f,r]),ref:z,style:{...n,scale:H,...y&&{[Z?"backgroundColor":"borderColor"]:y}},children:i})}var Pb=yu.memo(US);var G=hn.default.createElement,{useEffect:U0}=hn.default,af=hn.default.useState,xn=hn.default.useRef,Y_=[{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%"}}],D_=[{id:"out-right",position:Lu.Right,style:{top:"50%"}}],eW=["#4eb7a8","#d7a13a","#69aee8","#e0835f","#b7d86b","#d98bd2","#5fc6bf"],Uy=236,Jy=88,uw=15000,JS=10,W9=96,j0=72,w9=64,lw=12;function A6(){return typeof document>"u"||document.visibilityState!=="hidden"}function fw(u,l){let f=Number.parseFloat(String(u||""));return Number.isFinite(f)?f/100:l}function QS(u,l,f){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=l.get(u.id)||0,t=l.get(i)||0;if(n===0)return t===0?-26:28+y*74;let _=f===0?Math.abs(n)*2:Math.sign(f)===Math.sign(n)?-3:3;if(t>0&&y===0)return-14+_;return 8+y*74+_}function j6(u){let l=u.filter((i,y)=>{let t=u[y-1];return!t||Math.abs(t.x-i.x)>0.5||Math.abs(t.y-i.y)>0.5});if(l.length<2)return"";let f=`M ${l[0].x},${l[0].y}`,r=l[0];for(let i=1;i0.5||Math.abs(F.y-r.y)>0.5)f+=` L ${F.x},${F.y}`;f+=` Q ${t.x},${t.y} ${J.x},${J.y}`,r=J}let n=l[l.length-1];return`${f} L ${n.x},${n.y}`}function ww(u,l,f,r,n,i,y=""){let t=f>=u,_=Math.max(1,Math.abs(f-u)),c=Math.abs(r-l),A=Math.max(34,Math.min(118,_*0.26)),j=Math.min(280,Math.abs(i));if(t&&n===Lu.Left&&j<4&&c<28&&_<420)return`M ${u},${l} C ${u+A},${l} ${f-A},${r} ${f},${r}`;if(t&&n===Lu.Left&&(y==="direct-forward-left"||_<=260&&c<=210)){let U=Math.max(42,Math.min(140,_*0.48)),N=Math.max(-28,Math.min(28,i*0.18));return`M ${u},${l} C ${u+U},${l+N} ${f-U},${r} ${f},${r}`}if(t){let U=u+A;if(n===Lu.Top||n===Lu.Bottom){let W=n===Lu.Top?-1:1,z=r+W*(54+j*0.42);return j6([{x:u,y:l},{x:U,y:l},{x:U+Math.min(120,_*0.18),y:z},{x:f,y:z},{x:f,y:r+W*34},{x:f,y:r}])}let N=f-A,q=(l+r)/2+i;return j6([{x:u,y:l},{x:U,y:l},{x:U+Math.min(110,_*0.16),y:q},{x:N-Math.min(90,_*0.12),y:q},{x:N,y:r},{x:f,y:r}])}let Q=n===Lu.Bottom?1:n===Lu.Top?-1:i>=0?1:-1,w=Math.max(u,f)+92+Math.min(180,j*0.52),L=Q<0?Math.min(l,r)-84-j*0.62:Math.max(l,r)+84+j*0.62;if(n===Lu.Top||n===Lu.Bottom)return j6([{x:u,y:l},{x:u+A,y:l},{x:w,y:L},{x:f,y:L},{x:f,y:r+Q*38},{x:f,y:r}]);return j6([{x:u,y:l},{x:u+A,y:l},{x:w,y:L},{x:f-A,y:L},{x:f-A,y:r},{x:f,y:r}])}function NS({data:u}){return G("div",{className:"pipeline-flow-node-body"},Y_.map((l)=>G(Ri,{key:l.id,id:l.id,type:"target",position:l.position,isConnectable:!1,className:`pipeline-flow-handle input ${l.side} slot-${l.slot||"mid"}`,style:l.style})),D_.map((l)=>G(Ri,{key:l.id,id:l.id,type:"source",position:l.position,isConnectable:!1,className:"pipeline-flow-handle output right",style:l.style})),u?.label)}function qS({id:u,sourceX:l,sourceY:f,targetX:r,targetY:n,targetPosition:i,markerEnd:y,markerStart:t,style:_,data:c}){let A=Number(c?.laneOffset||0),j=ww(l,f,r,n,i,A,String(c?.routeMode||""));return G(jy,{id:u,path:j,markerEnd:y,markerStart:t,style:_,interactionWidth:28})}var WS={pipelineCurve:qS},wS={pipelineNode:NS};function Q6(u){if(!u)return"--";let l=new Date(u);if(Number.isNaN(l.getTime()))return"--";return tl(l)}function Br(u){let l=Number(u);if(!Number.isFinite(l)||l<0)return"--";let f=Math.round(l/1000);if(f<60)return`${f}s`;if(f<3600)return`${Math.floor(f/60)}m ${f%60}s`;return`${Math.floor(f/3600)}h ${Math.floor(f%3600/60)}m`}function L9(u){let l=Number(u);if(!Number.isFinite(l))return"--";return l.toLocaleString("zh-CN")}function rw(u){let l=Number(u);if(!Number.isFinite(l))return"--";return`${Math.round(Math.max(0,Math.min(1,l))*100)}%`}function Xu(u){return typeof u==="object"&&u!==null&&!Array.isArray(u)}function Du(u){return Array.isArray(u)?u:[]}function Iu(u){if(!u)return null;let l=new Date(u);return Number.isNaN(l.getTime())?null:l.getTime()}function p_(u){return Number.isFinite(Number(u))?new Date(Number(u)).toISOString():""}function C_(...u){for(let l of u){let f=Iu(l);if(f!==null)return new Date(f).toISOString()}return""}function p9(...u){let l=u.map(Iu).filter((f)=>f!==null);return l.length>0?new Date(Math.max(...l)).toISOString():""}function m9(u){return["succeeded","failed","skipped","cancelled","canceled","completed"].includes(String(u||"").toLowerCase())}function Lw(u){let l=zw(u).toLowerCase();return["running","active","in-progress","in_progress"].includes(l)}function nw(u,l="status"){return u.reduce((f,r)=>{let n=String(r?.[l]||"unknown").toLowerCase();return f[n]=(f[n]||0)+1,f},{})}function Kw(u){if(!u||typeof u!=="string")return null;try{let l=JSON.parse(u);return Xu(l)?l:null}catch{return null}}function K9(u){let l=u.map(Kw).filter((i)=>Boolean(i)),f=l.flatMap((i)=>[i.timestamp,i.createdAt,i.updatedAt]).filter(Boolean),r=p9(...f),n=Array.from(new Set(l.map((i)=>String(i.event||i.action||i.type||"")).filter(Boolean))).slice(0,3);return{total:u.length,parsed:l.length,lastAt:r,eventKinds:n}}function N6(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 Gw(u,l=280){if(u===null||u===void 0)return"";let r=(typeof u==="string"?u:String(u)).replace(/\r\n/gu,` +`).trim();return r.length>l?`${r.slice(0,Math.max(0,l-1))}...`:r}function zw(u){if(typeof u==="string")return u;if(Xu(u))return String(u.status||u.state||u.phase||"unknown");return"unknown"}function LS(u){return u.filter((l)=>l&&l.value!==void 0&&l.value!==null&&String(l.value)!=="")}function O9({items:u}){let l=LS(Du(u));return G("div",{className:"pipeline-kv-grid"},l.map((f)=>G("span",{key:f.label},G("b",null,f.label),G("span",null,f.value))))}function P9({items:u}){let l=Du(u).map((f)=>String(f||"")).filter(Boolean);if(l.length===0)return null;return G("div",{className:"pipeline-chip-row"},l.map((f,r)=>G("span",{key:`${r}-${f}`},f)))}function H9(u,l){let f=String(l?.procedureRunId||""),r=Du(u?.procedureRuns);return r.find((n)=>String(Vr(n))===f)||r.at(-1)||null}function KS(u,l){let f=String(l||"");if(!f)return null;return Du(u?.procedureRuns).find((r)=>Vr(r)===f)||null}function G9(u){return Du(u?.attempts).length}function iw(u){return Du(u?.attempts).reduce((l,f)=>l+z6(f).length,0)}function z6(u){return Du(u?.opencodeMessages?.steps).filter(Xu)}function Tw(u){let l=String(u?.status||"").toLowerCase();if(["error","failed","failure"].includes(l))return"failed";if(["completed","succeeded","success"].includes(l))return"succeeded";if(["running","started","in_progress"].includes(l))return"running";return"unknown"}function GS(u,l){let f=V9(u.map((i)=>i?.agent)).slice(0,3),r=V9(u.map((i)=>i?.model)).slice(0,3),n=l.length<=2?l.map((i)=>`session ${i}`):[`sessions ${l.length}`,...l.slice(0,2).map((i)=>`session ${i}`)];return[...f.map((i)=>`agent ${i}`),...r.map((i)=>`model ${i}`),...n]}function X_(u,l=0){return String(u?.messageId||u?.index||"")||`step-${l}`}function zS({steps:u,sessionIds:l,sessionFacts:f,matchedStepKey:r}){let n=Du(u),i=n.findIndex((L,U)=>X_(L,U)===r),y=i>=0?n[i]:null,t=n.flatMap((L)=>[Iu(L?.createdAt),Iu(L?.completedAt)]).filter((L)=>L!==null),_=t.length>0?Math.min(...t):null,c=t.length>0?Math.max(...t):null,A=_!==null&&c!==null?Math.max(0,c-_):null,j=n.reduce((L,U)=>L+Du(U?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool").length,0),F=n.reduce((L,U)=>L+Du(U?.parts).filter((N)=>["text","reasoning"].includes(String(N?.type||"").toLowerCase())).length,0),J=n.reduce((L,U)=>L+Du(U?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool"&&Tw(N)==="failed").length,0),Q=[`${n.length} steps`,`${l.length} sessions`,`${F} messages`,`${j} tools`,A!==null?`duration ${Br(A)}`:"",J>0?`${J} failed tools`:""].filter(Boolean),w=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 ${Br(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"),f.length>0?G(P9,{items:f}):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 -> ${w.join(" / ")}`),G("time",null,`${Q6(y?.createdAt)} -> ${Q6(y?.completedAt)}`)):null,G(C3,{port:kJ,input:n,className:"codex-transcript pipeline-trace",testId:"pipeline-opencode-step-trace",emptyText:"暂无 OpenCode Trace 输出",keepRecentToolCalls:3}))}function B9(u){return Du(u).flatMap((l)=>{if(Xu(l))return[l];let f=Kw(l);return f?[f]:[]})}function gr(u){return String(u?.event||u?.action||u?.requestedAction||u?.type||"").toLowerCase()}function Fy(u){return C_(u?.timestamp,u?.createdAt,u?.updatedAt,u?.startedAt,u?.finishedAt)}function TS(u){return Iu(Fy(u))}function T6(u){return String(u?.attempt||u?.id||"")}function V9(u){let l=new Set,f=[];for(let r of u){let n=String(r||"");if(!n||l.has(n))continue;l.add(n),f.push(n)}return f}function yw(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 xi(u){return String(u?.requestedAction||u?.action||"").toLowerCase()}function S_(u){switch(xi(u)){case"guide":return"引导";case"modify":return"修改";case"approve":return"审核通过";case"restart":return"重启";case"redo":return"重做";default:return String(u?.requestedAction||u?.action||"控制")}}function tw(u){switch(gr(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`${S_(u)} 已发起`;case"control-command-applied":return`${S_(u)} 已生效`;case"control-command-ignored":return`${S_(u)} 已忽略`;default:return String(u?.event||u?.action||u?.requestedAction||"event")}}function _w(u){return Gw(u?.promptPreview||u?.reasonPreview||u?.prompt||u?.reason||"",240)}function ES(u){let l=String(u?.prompt||""),f=String(u?.reason||u?.restartReason||""),r=l?"":String(u?.promptPreview||""),n=f?"":String(u?.reasonPreview||"");return[l||r?{label:l?"prompt":"prompt preview",value:l||r}:null,f||n?{label:f?"reason":"reason preview",value:f||n}:null,Du(u?.resetNodeIds).length>0?{label:"reset nodes",value:Du(u.resetNodeIds).join(", ")}:null,Du(u?.runningResetNodeIds).length>0?{label:"interrupted running nodes",value:Du(u.runningResetNodeIds).join(", ")}:null,Du(u?.interruptedProcedureRunIds).length>0?{label:"interrupted procedures",value:Du(u.interruptedProcedureRunIds).join(", ")}:null,u?.interruptedProcedureRunId?{label:"interrupted procedure",value:String(u.interruptedProcedureRunId)}:null].filter(Boolean)}function z9(u){let l=z6(u),f=l.map((_)=>Iu(_?.createdAt)).filter((_)=>_!==null),r=l.map((_)=>Iu(_?.completedAt)??Iu(_?.createdAt)).filter((_)=>_!==null),n=B9(u?.controlEventRecords).map((_)=>TS(_)).filter((_)=>_!==null),i=Du(u?.assistantOutputs).map((_)=>Iu(_?.updatedAt)).filter((_)=>_!==null),y=f[0]??n[0]??i[0]??null,t=r.at(-1)??n.at(-1)??i.at(-1)??y;return{startMs:y,endMs:t}}function ZS(u,l,f,r,n=""){let i=Du(u?.procedureRuns).filter((t)=>E6(t,l)===f);if(i.length===0)return null;if(n){let t=i.find((_)=>Vr(_)===n);if(t)return t}if(r===null)return i.at(-1)||null;let y=i.find((t)=>{let _=Iu(F6(t,u)),c=Iu(U6(t,u))??_;return _!==null&&c!==null&&r>=_-1000&&r<=c+1000});if(y)return y;return i.slice().sort((t,_)=>{let c=Iu(F6(t,u))??r,A=Iu(U6(t,u))??c,j=Iu(F6(_,u))??r,F=Iu(U6(_,u))??j,J=Math.min(Math.abs(c-r),Math.abs(A-r)),Q=Math.min(Math.abs(j-r),Math.abs(F-r));return J-Q})[0]||null}function Ew(u,l){let f=Du(u?.attempts).filter(Xu);if(f.length===0)return null;let r=String(l?.attempt||"");if(r){let y=f.find((t)=>T6(t)===r);if(y)return y}let n=Number.isFinite(Number(l?.ms))?Number(l.ms):null;if(n===null)return f.at(-1)||null;let i=f.find((y)=>{let t=z9(y);return Number.isFinite(t.startMs)&&Number.isFinite(t.endMs)&&n>=Number(t.startMs)-1000&&n<=Number(t.endMs)+1000});if(i)return i;return f.slice().sort((y,t)=>{let _=z9(y),c=z9(t),A=Math.min(Math.abs(Number(_.startMs??n)-n),Math.abs(Number(_.endMs??n)-n)),j=Math.min(Math.abs(Number(c.startMs??n)-n),Math.abs(Number(c.endMs??n)-n));return A-j})[0]||f.at(-1)||null}function Zw(u,l){let f=z6(u);if(f.length===0)return{step:null,stepIndex:-1,stepKey:""};if(l===null){let i=f[0];return{step:i,stepIndex:0,stepKey:X_(i,0)}}for(let i=0;i=t-1000&&l<=_+1000)return{step:y,stepIndex:i,stepKey:X_(y,i)}}let r=f.findIndex((i)=>{let y=Iu(i?.createdAt)??Iu(i?.completedAt);return y!==null&&y>=l});if(r>=0){let i=f[r];return{step:i,stepIndex:r,stepKey:X_(i,r)}}let n=Math.max(0,f.length-1);return{step:f[n],stepIndex:n,stepKey:X_(f[n],n)}}function OS(u,l){let f=String(l?.runId||u?.runId||"");if(String(l?.mode||"")==="interval"){let c=l?.interval||{},A=H9(u,c)||c.raw||{};return{mode:"interval",runId:f,interval:c,marker:null,nodeId:String(c?.nodeId||E6(A,f)||""),procedure:A,attempt:null,matchedStep:null,matchedStepIndex:-1,matchedStepKey:""}}let r=Xu(l?.marker)?l.marker:{},n=Number.isFinite(Number(r?.ms))?Number(r.ms):null,i=String(r?.nodeId||""),y=i?ZS(u,f,i,n,String(r?.procedureRunId||"")):null,t=y?Ew(y,r):null,_=t?Zw(t,n):{step:null,stepIndex:-1,stepKey:""};return{mode:"event",runId:f,interval:null,marker:r,nodeId:i,procedure:y,attempt:t,matchedStep:_.step,matchedStepIndex:_.stepIndex,matchedStepKey:_.stepKey}}function HS({procedure:u,matchedStepKey:l="",matchedAttemptId:f=""}){let r=Du(u?.attempts);if(r.length===0)return G(Qr,{title:"暂无 attempt 详情",text:"当前 procedure 还没有可展示的 attempt / OpenCode Trace;若刚点击甘特线,请等待 node 详情抓取完成。"});return r.map((n,i)=>{let y=n?.opencodeMessages||{},t=z6(n),_=Du(y.sessionIds).map((F)=>String(F)).filter(Boolean),c=GS(t,_),A=T6(n)||`attempt-${i+1}`,j=t.reduce((F,J)=>F+Du(J?.parts).filter((Q)=>String(Q?.type||"").toLowerCase()==="tool"&&Tw(Q)==="failed").length,0);return G("article",{key:A,className:`pipeline-attempt-card ${f===A?"matched":""}`},G("div",{className:"pipeline-attempt-head"},G("div",null,G("strong",null,A),G("span",null,y.source||"opencode")),G("div",{className:"pipeline-attempt-badges"},G("span",null,`${t.length} steps`),G("span",null,`${y.toolCallCount??"--"} tools`),j>0?G("span",{className:"danger"},`${j} failed`):null)),G(O9,{items:[{label:"messages",value:y.messageCount??"--"},{label:"steps",value:y.stepCount??"--"},{label:"tools",value:y.toolCallCount??"--"},{label:"updated",value:qu(y.updatedAt)},{label:"sessions",value:_.join(", ")||"--"}]}),t.length===0?G("p",{className:"muted paragraph"},"当前 attempt 尚未返回 OpenCode Trace;请确认 D601 pipeline-control 已重建并重新抓取。"):G(zS,{steps:t,sessionIds:_,sessionFacts:c,matchedStepKey:l}))})}function T9(u,l){return`${u}::${l}`}function q6(u,l,f){if(!Xu(u))return null;return String(u.runId||"")===l&&String(u.nodeId||"")===f?u:null}function BS(u,l){let f=Xu(u)?u:{};if(!Xu(l))return f;let r=Du(l.attempts),n=Du(f.attempts);return{...f,...l,attempts:r.length>0?r:n}}function VS(u,l,f,r){if(!q6(l,f,r))return u;let n=Du(l.procedureRuns),i=Xu(u)?u:{};return{...i,...l,controlEvents:Du(l.controlEvents).length>0?l.controlEvents:i.controlEvents,procedureRuns:n.length>0?n:i.procedureRuns}}function DS({selection:u,runDetails:l,nodeDetails:f,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(nl,{title:"未选择元素",level:3})),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起")),G(Qr,{title:"选择一条执行线或一个控制点",text:"点击甘特图中的 node 执行线、prompt 点或控制点,在这里查看结构化过程和 OpenCode step。"}));let y=String(u?.runId||""),t=String(u?.interval?.nodeId||u?.marker?.nodeId||""),_=l?.runId===y?l.details:null,c=q6(f,y,t),A=String(r?.runId||"")===y&&String(r?.nodeId||"")===t,j=VS(_,c,y,t),F=(String(l?.runId||"")!==y||Boolean(l?.loading))&&!j,J=String(l?.runId||"")===y?String(l?.error||""):"",Q=A?String(r?.error||""):"",w=j?OS(j,u):null,L=w?.interval||u?.interval||null,U=w?.marker||u?.marker||null,N=String(L?.procedureRunId||U?.procedureRunId||""),q=c?KS(c,N)||H9(c,L||{procedureRunId:N}):null,W=w?.procedure||(j?H9(j,L||{procedureRunId:N}):null)||L?.raw||{};if(q&&(G9(W)===0||iw(q)>=iw(W)))W=BS(W,q);let z=w?.attempt||null,Z=String(w?.matchedStepKey||"");if(!z&&U&&G9(W)>0)z=Ew(W,U),Z=String(Zw(z,Number.isFinite(Number(U?.ms))?Number(U.ms):null).stepKey||"");let H=T6(z),E=G9(W)>0,D=A&&Boolean(r?.loading)&&!E,h=Boolean(F||D),V=[E?"":J,Q].filter(Boolean).join(" / "),S=A&&r?.fetchedAt?r.fetchedAt:l?.fetchedAt,p=zw(W?.status||L?.status||U?.status||U?.event),O=u?.mode==="event"?U?.label||tw(U?.raw||U)||"event":w?.nodeId||L?.nodeId||"node",m=U?ES(U?.raw||U):[],X=U?[gr(U?.raw||U)?`event ${gr(U?.raw||U)}`:"",U?.promptEvent?`prompt ${U.promptEvent}`:"",U?.action?`action ${U.action}`:"",U?.sourceKind?`source ${yw(U.sourceKind)}`:"",U?.sourceNodeId?`from ${U.sourceNodeId}`:"",U?.targetNodeId?`to ${U.targetNodeId}`:"",U?.snapReason?`draw ${U.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(nl,{title:O,level:3,loading:h})),G("div",{className:"pipeline-gantt-detail-head-actions"},G(bn,{status:p},p),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起"))),U?G("article",{className:"pipeline-event-card"},G("div",{className:"pipeline-event-card-head"},G("strong",null,U?.label||tw(U?.raw||U)),G(P9,{items:X})),G(O9,{items:[{label:"event time",value:qu(U?.timestampIso||U?.timestamp||"--")},U?.snapped?{label:"drawn time",value:qu(U?.renderedTimestampIso||U?.ms)}:null,{label:"node",value:U?.nodeId||"--"},{label:"procedure",value:U?.procedureRunId||Vr(W)||"--"},{label:"attempt",value:U?.attempt||H||"--"},{label:"source kind",value:U?.sourceKind?yw(U.sourceKind):"--"},{label:"source node",value:U?.sourceNodeId||"--"},{label:"target node",value:U?.targetNodeId||"--"},{label:"command",value:U?.commandId||U?.eventId||"--"},U?.snapReason?{label:"placement",value:U.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,_w(U?.raw||U)?G("p",{className:"pipeline-text-preview"},_w(U?.raw||U)):null):null,G(O9,{items:[{label:"epoch",value:y||L?.runId||"--"},{label:"node",value:w?.nodeId||L?.nodeId||U?.nodeId||"--"},{label:"procedure",value:L?.procedureRunId||U?.procedureRunId||Vr(W)||"--"},{label:"started",value:qu(L?.startedAt||W?.startedAt)},{label:"finished",value:qu(L?.finishedAt||W?.finishedAt)},{label:"duration",value:Br(L?.durationMs||W?.durationMs)},{label:"fetched",value:S?tl(S):"--"},w?.matchedStep?{label:"matched step",value:`Step ${w.matchedStep.index??w.matchedStepIndex+1}`}:null]}),G(il,{error:V}),G("div",{className:"pipeline-gantt-detail-actions"},G(sr,{title:`Procedure ${L?.procedureRunId||U?.procedureRunId||w?.nodeId||"node"}`,data:W,onOpen:n,testId:"raw-pipeline-gantt-procedure"}),U?G(sr,{title:`Pipeline event ${U?.id||U?.commandId||U?.eventId||w?.nodeId||"event"}`,data:U?.raw||U,onOpen:n,testId:"raw-pipeline-gantt-event"}):null,j?G(sr,{title:`Pipeline run ${y||"--"}`,data:j,onOpen:n,testId:"raw-pipeline-gantt-node-details"}):null),!h&&!Vr(W)&&!U?G(Qr,{title:"暂无过程详情",text:"当前选择还没有可匹配的 procedure 运行记录。"}):null,!h&&Vr(W)?G(HS,{procedure:W,matchedStepKey:Z,matchedAttemptId:H}):null)}function XS({value:u}){let f=String(u||"--").split(/([_-])/u);return G(hn.default.Fragment,null,f.map((r,n)=>r==="-"||r==="_"?G(hn.default.Fragment,{key:n},r,G("wbr",null)):G(hn.default.Fragment,{key:n},r)))}async function Mn(u,l={}){return Tu(u,{invalidJsonPrefix:"Pipeline 返回了无效 JSON",...l})}function bn({status:u,children:l}){let f=String(u||"unknown").toLowerCase();return G("span",{className:`status-badge ${f}`},l||u||"unknown")}function pf({label:u,value:l,hint:f,tone:r}){return G("article",{className:`metric-card ${r||""}`},G("div",{className:"metric-label"},u),G("div",{className:"metric-value"},l),G("div",{className:"metric-hint"},f))}function F0({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){return G("section",{className:`panel ${n||""}`},G("div",{className:"panel-head"},G("div",null,l?G("p",{className:"panel-eyebrow"},l):null,G(nl,{title:u,loading:i})),f?G("div",{className:"panel-actions"},f):null),G("div",{className:"panel-body"},r))}function sr({title:u,data:l,onOpen:f,testId:r}){return G("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>f(u,l)},"查看原始JSON")}function Hr({title:u,subtitle:l,facts:f,data:r,onRaw:n,testId:i}){let y=Du(f).map((t)=>String(t||"")).filter(Boolean);return G("article",{className:"pipeline-evidence-row"},G("div",{className:"pipeline-evidence-main"},G("strong",null,u),l?G("span",null,l):null),G("div",{className:"pipeline-evidence-facts"},y.map((t,_)=>G("span",{key:`${_}-${t.slice(0,16)}`},t))),r!==void 0?G(sr,{title:u,data:r,onOpen:n,testId:i}):null)}function Qr({title:u,text:l}){return G("div",{className:"empty-state"},G("strong",null,u),G("span",null,l))}function SS(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 pS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function mS(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 $w(u,l,f){let r=u?._unidesk?.arrayLimits?.[l],n=Number(r?.originalLength);return Number.isFinite(n)?n:f}function Ow(u){if(!u||typeof u!=="object"||Array.isArray(u))return"--";return`${u.componentClass||"--"}/${u.id||"--"}`}function W6(u){if(!u||typeof u!=="object"||Array.isArray(u))return"";let l=String(u.componentClass||"").trim(),f=String(u.id||"").trim();return l&&f?`${l}/${f}`:""}function C9(u){return u?.config&&typeof u.config==="object"&&!Array.isArray(u.config)?u.config:{}}function Hw(u){let l=C9(u),f=Array.isArray(l.nodes)?l.nodes:Array.isArray(u?.nodes)?u.nodes:[],r=new Map;for(let y of f){let t=String(y?.id||y?.nodeId||"");if(t)r.set(t,{...y,id:t})}let n=M9(u),i=(y)=>{if(y&&!r.has(y))r.set(y,{id:y})};for(let y of R9(u))m_(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 M9(u){let l=C9(u);return Array.isArray(l.edges)?l.edges:Array.isArray(u?.edges)?u.edges:[]}function R9(u){let l=C9(u);return Array.isArray(l.topologicalBatches)?l.topologicalBatches:Array.isArray(u?.topologicalBatches)?u.topologicalBatches:[]}function PS(u){let l=new Map;for(let f of u){let r=W6(f);if(r)l.set(r,f);let n=Array.isArray(f?.refs)?f.refs:[];for(let i of n){let y=W6(i);if(y)l.set(y,f)}}return l}function cw(u,l){let f=l.get(W6(u?.componentRef));if(f)return f;let r=W6({componentClass:u?.kind,id:u?.id});return r?l.get(r)||null:null}function Aw(u,l){let f=Bw(u,l);return String(f?.status||"pending")}function Bw(u,l){return(Array.isArray(u?.nodes)?u.nodes:[]).find((r)=>r?.nodeId===l||r?.id===l)||null}function CS(u){return u.reduce((l,f)=>{let r=String(f?.status||"unknown").toLowerCase();return l[r]=(l[r]||0)+1,l},{})}function MS(u){if(Array.isArray(u?.scorers))return u.scorers.filter(Xu);if(Array.isArray(u?.summary?.scorers))return u.summary.scorers.filter(Xu);if(Array.isArray(u?.artifact?.summary?.scorers))return u.artifact.summary.scorers.filter(Xu);return[]}function RS(u){if(Xu(u?.run))return u.run;if(Xu(u?.runSummary))return u.runSummary;return null}function xS(u,l){if(!Xu(u)&&!Xu(l))return null;if(!Xu(u))return l;if(!Xu(l))return u;return{...u,...l,request:Xu(u.request)||Xu(l.request)?{...Xu(u.request)?u.request:{},...Xu(l.request)?l.request:{}}:l.request??u.request,artifact:Xu(u.artifact)||Xu(l.artifact)?{...Xu(u.artifact)?u.artifact:{},...Xu(l.artifact)?l.artifact:{}}:l.artifact??u.artifact,summary:Xu(u.summary)||Xu(l.summary)?{...Xu(u.summary)?u.summary:{},...Xu(l.summary)?l.summary:{}}:l.summary??u.summary}}function w6(u){let l=MS(u),f=l.find((A)=>Xu(A?.score))||l[0]||null,r=Xu(f?.score)?f.score:{},n=Number(r.passed),i=Number(r.total),y=Number(r.ratio),t=Number.isFinite(y)?y:Number.isFinite(n)&&Number.isFinite(i)&&i>0?n/i:null,_=t===null?null:Math.round(Math.max(0,Math.min(100,t<=1?t*100:t))),c=String(r.text||(Number.isFinite(n)&&Number.isFinite(i)?`${n}/${i}`:""));return{scorer:f,scorers:l,score:r,passed:Number.isFinite(n)?n:null,total:Number.isFinite(i)?i:null,percent:_,text:c}}function D9(u){let l=w6(u);return l.text||(l.scorers.length>0?String(l.scorer?.status||"pending"):"--")}function x9(u){let l=w6(u);if(l.total>0&&l.passed===l.total)return"succeeded";if(l.total>0&&l.passed>0)return"running";if(l.scorers.length>0)return"failed";return"pending"}function hS(u){return Array.isArray(u?.items)?u.items.filter(Xu):[]}function bS({run:u}){let l=D9(u);return G("span",{className:`pipeline-score-badge ${x9(u)}`},`score ${l}`)}function vS({run:u,onRaw:l}){let r=w6(u).scorers;if(!u)return G(Qr,{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=w6({scorers:[n]}),t=hS(n),_=y.percent??0;return G("article",{key:`${n.scorerId||n.component||i}`,className:`pipeline-score-card ${x9({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(bn,{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||"--")),t.length>0?G("div",{className:"pipeline-score-items"},t.map((c)=>G("span",{key:`${c.id||c.filter}`,className:`pipeline-score-item ${String(c.status||"").toLowerCase()}`,title:`${c.filter||"--"} / ran=${c.ran??"?"}`},G("b",null,c.id||"--"),G("small",null,c.status||"--")))):G("p",{className:"muted paragraph"},"当前 scorer 尚未返回 item 级结果。"),n.error?G("p",{className:"pipeline-score-error"},Gw(n.error,360)):null,G("div",{className:"panel-actions inline-actions"},G(sr,{title:`Scorer ${n.scorerId||i}`,data:n,onOpen:l,testId:"raw-pipeline-score"})))}))}function kS(u){let l=u.reduce((f,r)=>{let n=String(r?.componentClass||"unknown");return f[n]=(f[n]||0)+1,f},{});return Object.entries(l).map(([f,r])=>({name:f,count:Number(r)})).sort((f,r)=>r.count-f.count||f.name.localeCompare(r.name))}function m_(u){if(Array.isArray(u))return u.map((l)=>typeof l==="string"?l:String(l?.id||l?.nodeId||"")).filter(Boolean);if(Array.isArray(u?.nodes))return m_(u.nodes);if(Array.isArray(u?.nodeIds))return m_(u.nodeIds);return[]}function IS(u){return Xu(u?.instanceInputs?.monitor)?u.instanceInputs.monitor:{}}function Vw(u,l){if(String(u?.kind||"").toLowerCase()!=="procedure")return!1;let f=IS(u);if(u?.instanceInputs?.monitorMode===!0||f.enabled===!0)return!0;let r=Ow(u?.componentRef);return String(l?.id||l?.config?.id||r||"").toLowerCase().includes("monitor")}function gS(u){return u.filter((l)=>Vw(l)).map((l)=>String(l?.id||"")).filter(Boolean)}function sS(u,l){if(l.length===0)return u;let f=new Set(l),r=l.filter((n)=>u.includes(n));if(r.length===0)return u;return[...r,...u.filter((n)=>!f.has(n))]}function aS(u,l){if(l.length===0)return u;let f=new Set(l),r=l.filter((i)=>u.some((y)=>y.includes(i)));if(r.length===0)return u;let n=u.map((i)=>i.filter((y)=>!f.has(y))).filter((i)=>i.length>0);return[r,...n]}function oS(u,l,f){let n=R9(u).map(m_).filter((F)=>F.length>0);if(n.length>0)return n;let i=l.map((F)=>String(F?.id||"")).filter(Boolean),y=new Set(i),t=new Map(i.map((F)=>[F,0])),_=new Map(i.map((F)=>[F,[]]));for(let F of f){let J=String(F?.from||F?.source||""),Q=String(F?.to||F?.target||"");if(!y.has(J)||!y.has(Q))continue;_.get(J)?.push(Q),t.set(Q,(t.get(Q)||0)+1)}let c=new Map,A=i.filter((F)=>(t.get(F)||0)===0);for(let F of A)c.set(F,0);while(A.length>0){let F=A.shift(),J=(c.get(F)||0)+1;for(let Q of _.get(F)||[])if(t.set(Q,Math.max(0,(t.get(Q)||0)-1)),c.set(Q,Math.max(c.get(Q)||0,J)),(t.get(Q)||0)===0)A.push(Q)}i.forEach((F)=>{if(!c.has(F))c.set(F,0)});let j=Math.max(0,...Array.from(c.values()));return Array.from({length:j+1},(F,J)=>i.filter((Q)=>c.get(Q)===J)).filter((F)=>F.length>0)}function dS(u,l,f){let n=R9(u).map(m_).filter((t)=>t.length>0),i=n.length>0?n.flatMap((t)=>t):(()=>{let t=l.map((w)=>String(w?.id||"")).filter(Boolean),_=new Set(t),c=f.filter((w)=>String(w?.edgeType||"").toLowerCase()!=="rework"),A=new Map(t.map((w)=>[w,0])),j=new Map(t.map((w)=>[w,[]]));for(let w of c){let L=String(w?.from||w?.source||""),U=String(w?.to||w?.target||"");if(!_.has(L)||!_.has(U))continue;j.get(L)?.push(U),A.set(U,(A.get(U)||0)+1)}let F=new Map,J=t.filter((w)=>(A.get(w)||0)===0);for(let w of J)F.set(w,0);while(J.length>0){let w=J.shift(),L=(F.get(w)||0)+1;for(let U of j.get(w)||[])if(A.set(U,Math.max(0,(A.get(U)||0)-1)),F.set(U,Math.max(F.get(U)||0,L)),(A.get(U)||0)===0)J.push(U)}t.forEach((w)=>{if(!F.has(w))F.set(w,0)});let Q=Math.max(0,...Array.from(F.values()));return Array.from({length:Q+1},(w,L)=>t.filter((U)=>F.get(U)===L)).flatMap((w)=>w)})(),y=new Set(i);for(let t of l){let _=String(t?.id||"");if(!_||y.has(_))continue;i.push(_),y.add(_)}return sS(i,gS(l))}function B_(u){return`${u.source}->${u.target}-${u.index}`}function jw(u,l,f){let r=Hw(u),n=M9(u),i=PS(f),y=new Map(r.map((p)=>[String(p?.id||""),p])),t=r.filter((p)=>Vw(p,cw(p,i))).map((p)=>String(p?.id||"")).filter(Boolean),_=aS(oS(u,r,n),t),c=[],A=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},Y=cw(T,i),k=Aw(l,X).toLowerCase(),I=String(T.kind||Y?.componentClass||"node").toLowerCase(),b=Ow(T.componentRef||Y),o=String(Y?.config?.version||Y?.version||""),g=String(Y?.config?.description||Y?.description||""),x=v*122-Math.floor(m/2);A.set(X,{column:O,row:v,y:x}),c.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(bn,{status:k},k))},className:`pipeline-flow-node ${I} ${k}`})})});let J=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=J.reduce((p,O)=>p.set(O.source,(p.get(O.source)||0)+1),new Map),w=J.reduce((p,O)=>p.set(O.target,(p.get(O.target)||0)+1),new Map),L=J.reduce((p,O)=>{let m=`${O.source}->${O.target}`;return p.set(m,(p.get(m)||0)+1)},new Map),U=new Map,N=new Map,q=new Map,W=new Map,z=new Map,Z=new Map,H=J.reduce((p,O)=>{let m=A.get(O.source),X=A.get(O.target),v=(X?.column||0)-(m?.column||0);if(v<=0||String(O.edgeType||"").toLowerCase()==="rework"||v!==1)return p;let Y=`${O.source}->column:${X?.column??""}`,k=p.get(Y)||[];return k.push(O),p.set(Y,k),p},new Map);for(let p of H.values()){if(p.length<2)continue;p.slice().sort((O,m)=>{let X=A.get(O.target),v=A.get(m.target);return(X?.y||0)-(v?.y||0)||O.index-m.index}).forEach((O,m,X)=>{Z.set(B_(O),{slot:m-(X.length-1)/2,count:X.length})})}[...J].sort((p,O)=>{let m=A.get(p.source),X=A.get(p.target),v=A.get(O.source),T=A.get(O.target),Y=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 Y-k||p.index-O.index}).forEach((p)=>{let O=A.get(p.source)||{column:0,row:0,y:0},m=A.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",Y=O.y-m.y,k=w.get(p.target)||1,I=Z.has(B_(p)),b=!T&&v<=1&&(I||k===1),o=z.get(p.target)||new Map;z.set(p.target,o);let g=Y_.slice().sort((x,lu)=>{let _u=(Wu)=>{let P=String(Wu.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(Y)*0.02}if(P==="left")e+=v<=1?0:24;if(P==="top")e+=Y<-36?-18:42;if(P==="bottom")e+=Y>36?-18:42;if(v<=1&&Math.abs(Y)<=82&&P!=="left")e+=38;if(v>1&&P!=="left")e-=10;return e},$u=O.y-m.y,ju=$u!==0?$u:p.index%2===0?-1:1,zu=(Wu)=>{let P=o.get(Wu.id)||0;return _u(Wu)+P*64+QS(Wu,o,ju)};return zu(x)-zu(lu)||String(x.id).localeCompare(String(lu.id))})[0];o.set(g.id,(o.get(g.id)||0)+1),W.set(B_(p),g)});let D=J.map((p)=>{let O=Aw(l,p.target).toLowerCase(),m=`${p.source}->${p.target}`,X=U.get(p.source)||0,v=N.get(p.target)||0,T=q.get(m)||0;U.set(p.source,X+1),N.set(p.target,v+1),q.set(m,T+1);let Y=X-((Q.get(p.source)||1)-1)/2,k=v-((w.get(p.target)||1)-1)/2,I=T-((L.get(m)||1)-1)/2,b=A.get(p.source),o=A.get(p.target),g=(o?.column||0)-(b?.column||0),x=Math.max(1,Math.abs(g)),lu=g<=0||String(p.edgeType||"").toLowerCase()==="rework",_u=Math.abs((o?.y||0)-(b?.y||0)),$u=Z.get(B_(p)),ju=!lu&&g===1&&(w.get(p.target)||0)>1,zu=$u?$u.slot:I*2+Y+k*0.45,Wu=zu===0?p.index%2===0?-1:1:Math.sign(zu),P=W.get(B_(p))||Y_[1],e=P.side==="top"?-1:P.side==="bottom"?1:Wu,uu=lu||x>1||_u>96||Math.abs(zu)>0.2||P.side!=="left",Ku=lu?118+x*18:22+x*16,s=P.side==="left"?0:28,Nu=uu?Math.max(-280,Math.min(280,e*Math.min(180,Ku+s+_u*0.22)+zu*28)):0,Eu=Math.max(0,Math.min(D_.length-1,Math.round(Y+(D_.length-1)/2))),Hu=D_[Eu]||D_[1],vu=O==="succeeded"?"var(--accent-2)":O==="running"?"var(--accent)":O==="failed"?"var(--danger)":"rgba(129, 147, 159, 0.78)",ul=b?.column||0,mu=o?.column||0,Fl=Nu===0?0:Math.sign(Nu),Uf=lu?`feedback:${ul}->${mu}:${Fl}`:$u?`fanout:${ul}->${mu}:${p.source}`:ju?`fanin:${ul}->${mu}:${p.target}`:P.side!=="left"||x>1?`corridor:${ul}->${mu}:${P.side}:${Fl}:${Math.round(Math.abs(Nu)/56)}`:"";return{id:`${p.source}->${p.target}-${p.index}`,source:p.source,target:p.target,sourceHandle:Hu.id,targetHandle:P.id,type:"pipelineCurve",zIndex:12,animated:O==="running",data:{baseEdgeColor:vu,laneOffset:Nu,routeMode:$u&&P.side==="left"?"direct-forward-left":"",targetSide:P.side,isFeedback:lu,overlapGroup:Uf},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,S=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 Y=T>=0?eW[T%eW.length]:String(p.data.baseEdgeColor),k={stroke:Y};if(p.data.isFeedback)k.strokeDasharray="9 7";return{...m,data:{...p.data,edgeColor:Y,overlapSlot:T,overlapCount:v},style:k,markerEnd:{type:pn.ArrowClosed,color:Y},className:`pipeline-flow-edge ${O} ${p.data.isFeedback?"feedback":""} ${T>=0?"overlap-colored":""}`}});return{nodes:c,edges:S}}function of(u){return String(u??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function Fw(u){let l=String(u||"");if(l.includes("--accent-2"))return"#4eb7a8";if(l.includes("--accent"))return"#d7a13a";if(l.includes("--danger"))return"#cf6a54";return l.startsWith("#")?l:"#81939f"}function L6(u){return`arrow-${u.replace(/[^a-zA-Z0-9_-]+/g,"")}`}function Dw(u,l="pipeline"){return String(u||l).replace(/[^a-zA-Z0-9_-]+/g,"-").replace(/^-|-$/g,"")||l}function Uw(u,l){let f=u.position.x,r=u.position.y,n=Y_.find((i)=>i.id===l);if(n?.side==="top")return{x:f+Uy*fw(n.style?.left,0.5),y:r,position:Lu.Top};if(n?.side==="bottom")return{x:f+Uy*fw(n.style?.left,0.5),y:r+Jy,position:Lu.Bottom};return{x:f,y:r+Jy/2,position:Lu.Left}}function eS(u){return{x:u.position.x+Uy,y:u.position.y+Jy/2}}function uY(u,l){let f=Math.min(...u.nodes.map((w)=>w.position.x),0)-220,r=Math.min(...u.nodes.map((w)=>w.position.y),0)-220,n=Math.max(...u.nodes.map((w)=>w.position.x+Uy),1)+220,i=Math.max(...u.nodes.map((w)=>w.position.y+Jy),1)+220,y=Math.ceil(n-f),t=Math.ceil(i-r),_=new Map(u.nodes.map((w)=>[w.id,w])),c=u.edges.map((w)=>Fw(w.data?.edgeColor||w.style?.stroke)),j=Array.from(new Set(["#4eb7a8","#d7a13a","#cf6a54","#81939f",...c])).map((w)=>``).join(""),F=u.edges.flatMap((w)=>{let L=_.get(w.source),U=_.get(w.target);if(!L||!U)return[];let N=eS(L),q=Uw(U,String(w.targetHandle||"in-left")),W=ww(N.x,N.y,q.x,q.y,q.position,Number(w.data?.laneOffset||0),String(w.data?.routeMode||"")),z=Fw(w.data?.edgeColor||w.style?.stroke),Z=w.data?.isFeedback?' stroke-dasharray="9 7"':"";return``}).join(` +`),J=u.nodes.map((w)=>{let L=w.data?.exportLabel||{},U=String(L.status||"pending").toLowerCase(),N=U==="succeeded"?"#4eb7a8":U==="running"?"#d7a13a":U==="failed"?"#cf6a54":"#81939f",q=w.position.x,W=w.position.y,z=Y_.map((Z)=>{let H=Uw(w,Z.id);if(Z.side==="top"||Z.side==="bottom")return``;return``}).join(` `);return` - + ${z} - - ${al(w.id||L.id)} - ${al(w.kind||"node")} - ${al(w.componentRef||"--")} - ${al(J)} + + ${of(L.id||w.id)} + ${of(L.kind||"node")} + ${of(L.componentRef||"--")} + ${of(U)} `}).join(` -`);return{svg:` +`);return{svg:` ${j} - ${al(f)} - ${U}${F} - `,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` - - ${al(Nu(T.ms))} - +${al(Hr(Number(T.offsetMs??Number(T.ms)-Number(y.startMs))))} + ${of(l)} + ${J}${F} + `,width:y,height:t}}function lY(u){let l=String(u||"").toLowerCase();if(l==="succeeded"||l==="completed")return"#4eb7a8";if(l==="failed")return"#cf6a54";if(Lw(l))return"#69aee8";return"#d7a13a"}function fY(u){let l=String(u?.kind||""),f=String(u?.tone||u?.status||"").toLowerCase();if(l==="prompt"&&f==="initial")return"#d7a13a";if(l==="prompt"&&f==="monitor")return"#69aee8";if(l==="prompt")return"#4eb7a8";if(f==="modify")return"#e0b95a";if(f==="approve"||f==="guide"||f==="monitor")return"#4eb7a8";if(f==="restart"||f==="redo")return"#d7a13a";if(f==="ignored")return"#81939f";if(f==="webui")return"#69aee8";if(f==="cli")return"#d7a13a";return"#a7bac5"}function Jw(u){let l=String(u?.sourceKind||"").toLowerCase(),f=String(u?.action||"").toLowerCase(),r=String(u?.status||"").toLowerCase();if(f==="observe"||r==="observation"||l==="monitor")return"#4eb7a8";if(l==="webui")return"#69aee8";if(l==="cli")return"#d7a13a";if(r.includes("ignored"))return"#81939f";return"#8aa0ad"}function rY(u,l,f){let r=fY(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 nY(u){let l=Du(u.visibleNodeIds).map((T)=>String(T||"")).filter(Boolean),f=Du(u.intervals).filter(Xu),r=Du(u.markers).filter(Xu),n=Du(u.arrows).filter(Xu),i=Du(u.ticks).filter(Xu),y=Xu(u.bounds)?u.bounds:{},t=Xu(u.backendLayout)?u.backendLayout:null,_=Math.max(240,Math.round(Number(u.chartHeight||360))),c=Math.max(j0,108),A=128,j=24,F=58,J=56,Q=128+Math.max(1,l.length)*c,w=Math.max(760,Q+48),L=114+_+24,U=24,N=58,q=114,W=(T)=>152+T*c,z=(T)=>W(T)+c/2,Z=Du(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(Jw)])).map((T)=>``).join(""),h=i.map((T)=>{let Y=114+Mw(T,y,_,t);return` + + ${of(qu(T.ms))} + +${of(Br(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` - - ${al(I)} - node ${S+1} +`),V=['','TIME',...l.map((T,Y)=>{let k=W(Y),I=T.length>18?`${T.slice(0,16)}…`:T;return` + + ${of(I)} + node ${Y+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+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=l.map((T,Y)=>{return``}).join(` +`),p=f.map((T)=>{let Y=l.indexOf(String(T.nodeId||""));if(Y<0)return"";let k=114+G6(T,y,_,t),I=Math.max(2,Cw(T,y,_,t)),b=lY(T.status),o=z(Y)-3.5,g=T.live?``:"",x=I>=28?`${of(String(T.status||"working"))} + ${of(Br(T.durationMs))}`:"";return` ${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 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:` +`),O=r.map((T)=>{let Y=l.indexOf(String(T.nodeId||""));if(Y<0)return"";let k=114+Jr(T,y,_,t);return rY(T,z(Y),k)}).join(` +`),m=n.map((T)=>{let Y=H.get(String(T.targetMarkerId||""));if(!Y)return"";let k=H.get(String(T.sourceMarkerId||"")),I=String(k?.nodeId||T.sourceNodeId||""),b=String(Y.nodeId||T.targetNodeId||""),o=l.indexOf(I),g=l.indexOf(b);if(o<0||g<0)return"";let x=z(o)-24-128,lu=z(g)-24-128,_u=Qy(t)?Vl(T.sourceY??T.y1)??(k?Jr(k,y,_,t):Jr(Y,y,_,t)):k?Jr(k,y,_,t):Jr(Y,y,_,t),$u=Qy(t)?Vl(T.targetY??T.y2)??Jr(Y,y,_,t):Jr(Y,y,_,t),ju=Jw(T),zu=String(T.action||"").toLowerCase()==="observe"?"3 4":"6 5",Wu=of(Rw(x,_u,lu,$u));return` + `}).join(` +`),X=l.length===0?'No visible Gantt nodes':"";return{svg:` ${D} - - ${al(u.title||"Pipeline Epoch Gantt")} - ${al(Z)} + + ${of(u.title||"Pipeline Epoch Gantt")} + ${of(Z)} ${V} - - ${Y} + + ${S} ${h} ${p} ${m} ${O} ${X} - `,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));})(); + `,width:w,height:L}}function K6(u,l){let f=URL.createObjectURL(u),r=document.createElement("a");r.href=f,r.download=l,r.click(),setTimeout(()=>URL.revokeObjectURL(f),1000)}async function Xw(u,l){let f=Dw(l,"pipeline"),{svg:r,width:n,height:i}=uY(u,l),y=new Blob([r],{type:"image/svg+xml;charset=utf-8"}),t=URL.createObjectURL(y);try{let _=new Image;await new Promise((F,J)=>{_.onload=()=>F(),_.onerror=()=>J(Error("svg image load failed")),_.src=t});let c=document.createElement("canvas");c.width=n,c.height=i;let A=c.getContext("2d");if(!A)throw Error("canvas unavailable");A.drawImage(_,0,0);let j=await new Promise((F)=>c.toBlob(F,"image/png"));if(!j)throw Error("png export failed");K6(j,`${f}.png`)}catch{K6(y,`${f}.svg`)}finally{URL.revokeObjectURL(t)}}async function iY(u){let l=Dw(String(u?.title||"pipeline-gantt"),"pipeline-gantt"),{svg:f,width:r,height:n}=nY(u),i=new Blob([f],{type:"image/svg+xml;charset=utf-8"}),y=URL.createObjectURL(i);try{let t=new Image;await new Promise((j,F)=>{t.onload=()=>j(),t.onerror=()=>F(Error("gantt svg image load failed")),t.src=y});let _=document.createElement("canvas");_.width=r,_.height=n;let c=_.getContext("2d");if(!c)throw Error("canvas unavailable");c.drawImage(t,0,0);let A=await new Promise((j)=>_.toBlob(j,"image/png"));if(!A)throw Error("gantt png export failed");K6(A,`${l}.png`)}catch{K6(i,`${l}.svg`)}finally{URL.revokeObjectURL(y)}}async function yY(u){for(let l of u){if(l.flow.nodes.length===0)continue;await Xw(l.flow,l.title),await new Promise((f)=>setTimeout(f,750))}}function Qw(u,l){return u.find((f)=>String(f?.pipelineId||"")===l)||null}function Nw(u){return Iu(u?.startedAt)??Iu(u?.artifact?.startedAt)??Iu(u?.request?.createdAt)??Iu(u?.updatedAt)??0}function tY(u,l){return u.filter((f)=>String(f?.pipelineId||"")===l).slice().sort((f,r)=>Nw(f)-Nw(r)||String(f?.runId||"").localeCompare(String(r?.runId||"")))}function X9(u,l){let f=String(l?.runId||""),r=u.findIndex((y)=>String(y?.runId||"")===f),n=r>=0?r+1:u.length,i=String(l?.status||"--");return`Epoch ${n} / ${f||"--"} / ${i}`}function Vr(u){return String(u?.procedureRunId||u?.runId||"")}function E6(u,l){let f=String(u?.nodeId||u?.request?.nodeId||"");if(f)return f;let r=Vr(u),n=`${l}__`;if(r.startsWith(n))return r.slice(n.length).replace(/__\d+$/u,"");return""}function F6(u,l){let f=Xu(u?.artifact)?u.artifact:{},r=Xu(u?.request)?u.request:{};return C_(u?.startedAt,f.startedAt,r.createdAt,r.startedAt,u?.createdAt,u?.updatedAt,l?.startedAt,l?.request?.createdAt)}function U6(u,l){let f=String(u?.status?.status||u?.artifact?.status||u?.status||"").toLowerCase(),r=Xu(u?.artifact)?u.artifact:{},n=m9(f);return C_(u?.finishedAt,r.finishedAt,u?.completedAt,n?u?.updatedAt:void 0,n?r.updatedAt:void 0,n?l?.updatedAt:void 0)}function Sw(u,l,f=Date.now()){let r=String(u?.runId||""),n=new Set(l.map((i)=>String(i?.id||"")).filter(Boolean));return Du(u?.procedureRuns).flatMap((i)=>{let y=E6(i,r);if(!y)return[];let t=String(i?.status?.status||i?.artifact?.status||i?.status||"unknown").toLowerCase(),_=F6(i,u),c=Iu(_);if(c===null)return[];let A=U6(i,u),j=Iu(A)??(m9(t)?Iu(i?.updatedAt)??c+1000:f),F=Math.max(c+1000,j);return[{nodeId:y,knownNode:n.has(y),procedureRunId:Vr(i),status:t,startMs:c,endMs:F,startedAt:p_(c),finishedAt:p_(F),durationMs:F-c,runId:r,raw:i}]}).sort((i,y)=>i.startMs-y.startMs||i.endMs-y.endMs||i.nodeId.localeCompare(y.nodeId))}function _Y(u,l,f=[]){let r=l.map((A)=>Number(A.startMs)).filter(Number.isFinite),n=l.map((A)=>Number(A.endMs)).filter(Number.isFinite);for(let A of f){let j=Vl(A?.eventMs??A?.ms);if(j!==null)r.push(j),n.push(j)}let i=Iu(u?.startedAt)??Iu(u?.artifact?.startedAt)??Iu(u?.request?.createdAt),y=Iu(u?.finishedAt)??Iu(u?.artifact?.finishedAt)??Iu(u?.updatedAt);if(i!==null)r.push(i);if(y!==null)n.push(y);let t=Date.now(),_=r.length>0?Math.min(...r):t-60000,c=Math.max(_+60000,n.length>0?Math.max(...n):t);return{startMs:_,endMs:c,durationMs:c-_}}var J6=12,Yw=20,S9=100,$Y=!1;function vn(u){let l=Number(u);if(!Number.isFinite(l))return 0;return Math.max(0,Math.min(100,Math.round(l*100)/100))}function cY(u){let l=Math.max(J6,Number(u||J6)),f=Math.log(l/J6)/Math.log(Yw);return vn(f*100)}var P_=cY(S9);function h9(u){let l=vn(u)/100,f=J6*Math.pow(Yw,l),r=l<0.24?"全局":l<0.64?"均衡":"细节";return{value:vn(l*100),pxPerMinute:f,label:r}}function E9(u){let l=Math.round(Number(u));return Math.abs(l-S9)<=1?S9:l}function AY(u,l=P_){let f=Math.max(1,Number(u.durationMs||0)/60000),r=h9(l);return Math.round(Math.max(360,Math.min(7200,f*Number(r.pxPerMinute||48))))}function jY(u,l=7){let f=Math.max(1,Number(u.endMs||0)-Number(u.startMs||0));return Array.from({length:l},(r,n)=>{let i=l===1?0:n/(l-1);return{ms:Number(u.startMs)+f*i,percent:i*100}})}function FY(u,l){let f=Math.max(1,Number(l.endMs)-Number(l.startMs));return Math.max(0,Math.min(100,(u-Number(l.startMs))/f*100))}function Vl(u){let l=Number(u);return Number.isFinite(l)?l:null}function b9(u){return Lw(u?.status)&&!m9(u?.status)}function pw(u,l,f,r){let n=Math.max(1,f-l),i=Math.max(0,Math.min(1,(u-l)/n));return Number((i*r).toFixed(3))}function qw(u,l){if(!l)return null;let f=Vl(l?.startMs),r=Vl(l?.endMs),n=Vl(l?.chartHeight);if(f===null||r===null||n===null)return null;return pw(u,f,r,n)}function mw(u,l){let f=Vl(u?.rawStartMs??u?.startMs)??Vl(u?.startMs)??l,r=Vl(u?.endMs)??f+1000;if(!b9(u))return Math.max(f+1000,r);return Math.max(f+1000,r,l)}function UY(u,l,f,r){let n=Vl(u?.startMs)??r-60000,i=Vl(u?.endMs)??r,y=f.reduce((Q,w)=>Math.max(Q,mw(w,r)),i),t=Math.max(n+60000,i,y),_=Math.max(1,t-n),c={startMs:n,endMs:t,durationMs:_},A=AY(c,l),j=h9(l),F=Math.max(5,Math.min(18,Math.round(A/150))),J=jY(c,F).map((Q)=>{let w=Number(Q.ms),L=pw(w,n,t,A);return{...Q,y:L,timestamp:p_(w),offsetMs:w-n}});return{source:"frontend-y",startMs:n,endMs:t,durationMs:_,chartHeight:A,scale:vn(l),normalizedScale:Number((vn(l)/100).toFixed(3)),pxPerMinute:Number(Number(j.pxPerMinute||0).toFixed(3)),ticks:J}}function JY(u,l,f){if(!b9(u))return u;let r=Vl(u?.rawStartMs??u?.startMs)??Vl(u?.startMs)??f,n=mw(u,f),i=qw(r,l),y=qw(n,l),t=Vl(i??u?.y1??u?.startY)??0,_=Vl(y??u?.y2??u?.endY)??t+10,c=Math.max(24,_-t);return{...u,live:!0,startMs:r,endMs:n,durationMs:Math.max(1000,n-r),finishedAt:p_(n),y1:t,y2:_,startY:t,endY:_,height:c}}function v9(u,l,f){return FY(u,l)/100*f}function Qy(u){return Boolean(u&&String(u?.source||"")!=="frontend-y")}function Pw(u,l,f,r,n){if(Qy(r))for(let y of n){let t=Vl(u?.[y]);if(t!==null)return t}let i=Vl(u?.ms??u?.eventMs??u?.startMs);return v9(i??Number(l.startMs),l,f)}function G6(u,l,f,r){return Pw(u,l,f,r,["y1","startY"])}function Y9(u,l,f,r){if(Qy(r)){let i=Vl(u?.y2??u?.endY);if(i!==null)return i}let n=Vl(u?.endMs)??Number(l.endMs);return v9(n,l,f)}function Cw(u,l,f,r){if(Qy(r)){let i=Vl(u?.height);if(i!==null)return Math.max(1,i)}let n=u?.live?24:10;return Math.max(n,Y9(u,l,f,r)-G6(u,l,f,r))}function Jr(u,l,f,r){return Pw(u,l,f,r,["y","timeAxisY"])}function Mw(u,l,f,r){if(Qy(r)||String(r?.source||"")==="frontend-y"){let y=Vl(u?.y);if(y!==null)return y}let n=Vl(u?.percent);if(n!==null)return n/100*f;let i=Vl(u?.ms)??Number(l.startMs);return v9(i,l,f)}function QY(u){let l=String(u?.promptEvent||u?.raw?.promptEvent||u?.event||"").toLowerCase();if(!["node-long-running-observation","node-finished"].includes(l))return"";let f=String(u?.sourceNodeId||u?.raw?.sourceNodeId||u?.raw?.detail?.nodeId||""),r=String(u?.nodeId||u?.targetNodeId||"");return f&&f!==r?f:""}function NY(u,l){let f=new Set(l.map((n)=>[String(n.sourceNodeId||""),String(n.targetNodeId||""),String(n.targetMarkerId||""),String(n.action||"")].join(":"))),r=[...l];for(let n of u){let i=QY(n),y=String(n?.nodeId||""),t=String(n?.id||"");if(!i||!y||!t)continue;let _=[i,y,t,"observe"].join(":");if(f.has(_))continue;f.add(_),r.push({id:`observation-arrow:${t}:${i}:${y}`,commandId:String(n?.commandId||n?.eventId||t),sourceNodeId:i,targetNodeId:y,sourceMarkerId:"",targetMarkerId:t,sourceKind:"monitor",action:"observe",status:"observation"})}return{markers:u,arrows:r}}function qY(u){let l=gr(u),f=String(u?.promptEvent||"");if(l==="initial-prompt-delivered")return"initial";if(f==="node-finished"||f==="node-long-running-observation"||f.startsWith("monitor-"))return"monitor";if(l==="monitor-prompt-delivered"||String(u?.sourceKind||"").toLowerCase()==="monitor")return"monitor";return"append"}function WY(u){return Du(u?.tags||u?.raw?.tags).map((l)=>String(l||"")).filter(Boolean)}function wY(u){let l=gr(u),f=String(u?.promptEvent||"");if(l==="initial-prompt-delivered")return"初始 prompt";if(f==="node-long-running-observation")return"长任务观察";if(f==="node-finished")return WY(u).includes("monitor.audit")?"节点完成 / OA 审核":"节点完成";if(f==="monitor-interval")return"Monitor observation";if(f==="monitor-start")return"Monitor start";if(f==="monitor-stop")return"Monitor stop";if(l==="monitor-prompt-delivered")return"Monitor prompt";if(l==="append-prompt-queued")return"追加 prompt 已排队";return"追加 prompt"}function Ww(u){let l=gr(u);if(l==="control-command-applied")return 3;if(l==="control-command-ignored")return 2;if(l==="control-command-queued")return 1;return 0}function LY(u,l){let f=String(u?.commandId||"");if(f)return`command:${f}`;return["control-event",Fy(u)||C_(u?.createdAt,u?.timestamp)||`index-${l}`,String(u?.sourceKind||""),String(u?.sourceNodeId||""),String(u?.targetNodeId||""),xi(u)].join(":")}function KY(u){return V9([u?.targetNodeId,...Du(u?.resetNodeIds)])}function GY(u,l){let f=S_(u),r=gr(u),n=String(u?.targetNodeId||""),i=Boolean(n)&&l!==n;if(r==="control-command-applied")return i?`${f} 波及`:`${f} 生效`;if(r==="control-command-ignored")return`${f} 忽略`;if(r==="control-command-queued")return`${f} 已发起`;return i?`${f} 波及`:f}function zY(u){if(gr(u)==="control-command-ignored")return"ignored";let f=xi(u);if(f==="restart"||f==="redo")return"restart";if(f==="modify")return"modify";if(f==="approve")return"approve";if(f==="guide")return"guide";return"pending"}function TY(u){let l=String(u?.sourceKind||"").toLowerCase();if(l==="monitor")return"monitor";if(l==="webui")return"webui";if(l==="cli")return"cli";return"system"}function EY(u,l,f,r){let n=u.filter((c)=>String(c.nodeId||"")===l).sort((c,A)=>Number(c.startMs)-Number(A.startMs)),i=n.find((c)=>f>=Number(c.startMs)-1000&&f<=Number(c.endMs)+1000);if(i)return{ms:f,onInterval:!0,snapReason:"inside-interval",procedureRunId:String(i.procedureRunId||"")};let y=xi(r),t=n.slice().reverse().find((c)=>Number(c.endMs)<=f+1000);if(t&&y==="approve")return{ms:Number(t.endMs),onInterval:!0,snapReason:"previous-interval-end",procedureRunId:String(t.procedureRunId||"")};let _=n.find((c)=>Number(c.startMs)>=f-1000);if(_&&["guide","modify","restart","redo"].includes(y))return{ms:Number(_.startMs),onInterval:!0,snapReason:"next-interval-start",procedureRunId:String(_.procedureRunId||"")};return{ms:f,onInterval:!1,snapReason:"event-time",procedureRunId:String(r?.procedureRunId||"")}}function Rw(u,l,f,r){let n=Math.hypot(f-u,r-l),i=n>lw?lw:0,y=i>0?f-(f-u)/n*i:f,t=i>0?r-(r-l)/n*i:r,_=y-u,c=Math.max(16,Math.min(42,Math.abs(_)*0.45+12)),A=_===0?1:Math.sign(_);return`M ${u},${l} C ${u+A*c},${l} ${y-A*c},${t} ${y},${t}`}function ZY(u,l){let f=String(u?.runId||l?.runId||""),r=Sw({...Xu(l)?l:{},...Xu(u)?u:{},runId:f,procedureRuns:Du(u?.procedureRuns).length>0?u.procedureRuns:l?.procedureRuns},[]),n=[],i=[],y=[],t=new Set,_=new Map,c=(F,J)=>{if(!F.nodeId||!Number.isFinite(Number(F.ms)))return;if(t.has(F.id))return;t.add(F.id),J.push(F)};for(let F of Du(u?.procedureRuns)){let J=E6(F,f),Q=Vr(F);if(!J)continue;for(let w of Du(F?.attempts)){let L=T6(w);for(let U of B9(w?.controlEventRecords)){let N=gr(U);if(!["initial-prompt-delivered","append-prompt-delivered","monitor-prompt-delivered"].includes(N))continue;let q=Fy(U),W=Iu(q);if(W===null)continue;let z=String(U?.eventId||"");c({id:`prompt:${z||`${Q}:${L}:${N}:${W}`}`,runId:f,nodeId:J,procedureRunId:Q,attempt:L,kind:"prompt",tone:qY(U),status:"delivered",label:wY(U),ms:W,timestampIso:q,sourceKind:String(U?.sourceKind||""),sourceNodeId:String(U?.sourceNodeId||""),targetNodeId:J,action:"",eventId:z,commandId:String(U?.commandId||""),raw:U},n)}}}let A=new Map;B9(u?.controlEvents).forEach((F,J)=>{let Q=LY(F,J),w=A.get(Q)||{key:Q,events:[]};w.events.push(F),A.set(Q,w)});for(let F of A.values()){let J=Du(F.events).slice().sort((V,S)=>Ww(S)-Ww(V)),Q=Du(F.events).find((V)=>gr(V)==="control-command-queued")||null,w=J[0]||Q;if(!Q&&!w)continue;let L=String(Q?.sourceNodeId||w?.sourceNodeId||""),U=String(Q?.sourceKind||w?.sourceKind||""),N=Fy(Q)||Fy(w)||C_(Q?.createdAt,w?.createdAt),q=Iu(N),W=String(w?.commandId||Q?.commandId||F.key),z=(gr(w)||"control-command-queued").replace(/^control-command-/u,""),Z="";if(L&&q!==null)Z=`control-source:${W}:${L}`,_.set(W,Z),c({id:Z,runId:f,nodeId:L,procedureRunId:String(Q?.procedureRunId||w?.procedureRunId||""),attempt:"",kind:"control-source",tone:TY(Q||w),status:z,label:`${S_(Q||w)} 发起`,ms:q,timestampIso:N,action:xi(Q||w),sourceKind:U,sourceNodeId:L,targetNodeId:String(w?.targetNodeId||Q?.targetNodeId||""),commandId:W,raw:Q||w},i);let H=w||Q,E=Fy(H)||N,D=Iu(E);if(D===null)continue;let h=KY(H);for(let V of h){let S=EY(r,V,D,H),p=`control-target:${W}:${V}`;if(c({id:p,runId:f,nodeId:V,procedureRunId:S.procedureRunId,attempt:"",kind:"control-target",tone:zY(H),status:z,label:GY(H,V),ms:S.ms,eventMs:D,onInterval:S.onInterval,snapReason:S.snapReason,snapped:Number(S.ms)!==D,timestampIso:E,renderedTimestampIso:p_(Number(S.ms)),action:xi(H),sourceKind:U,sourceNodeId:L,targetNodeId:V,commandId:W,raw:H},i),Z&&L&&L!==V)y.push({id:`control-arrow:${W}:${L}:${V}`,commandId:W,sourceNodeId:L,targetNodeId:V,sourceMarkerId:Z,targetMarkerId:p,sourceKind:U,action:xi(H),status:z})}}let j=[...n,...i].sort((F,J)=>Number(F.ms)-Number(J.ms)||String(F.nodeId).localeCompare(String(J.nodeId))||String(F.id).localeCompare(String(J.id)));return{...NY(j,y),sourceMarkerByCommand:_}}function OY({details:u,selectedNodeId:l,selectedNodeRuntime:f,control:r,onRaw:n}){if(!u)return G("span",{className:"muted"},"点击“抓取过程”读取 node 运行材料;主界面只显示结构化摘要,完整内容需点开原始 JSON。");let i=Du(u.procedureRuns),y=i.at(-1)||{},t=Du(y.attempts),_=t.at(-1)||{},c=Du(y.workerLogTail),A=Du(_.controlEventsTail),j=Du(_.controlPromptsTail),F=Du(_.monitorPromptsTail),J=K9(A),Q=K9(j),w=K9(F),L=_.opencodeMessages||{};return G("div",{className:"pipeline-evidence-list compact"},G(Hr,{title:"Node runtime",subtitle:l||"--",facts:[`status ${f?.status||"pending"}`,`attempts ${f?.attempts??t.length}`,`procedure ${f?.currentProcedureRunId||Vr(y)||"--"}`,r.fetchedAt?`fetched ${tl(r.fetchedAt)}`:"not fetched"],data:u.node||u,onRaw:n,testId:"raw-pipeline-node-runtime"}),G(Hr,{title:"Procedure runs",subtitle:`${i.length} groups`,facts:[`latest ${y.status?.status||y.status||"--"}`,`steps ${Du(y.recentSteps).length}`,`duration ${Br(Iu(y.finishedAt)&&Iu(y.startedAt)?Number(Iu(y.finishedAt))-Number(Iu(y.startedAt)):y.durationMs)}`],data:i,onRaw:n,testId:"raw-pipeline-node-procedures"}),G(Hr,{title:"OpenCode messages",subtitle:String(L.exists?"available":"not indexed"),facts:[`messages ${N6(L.messageCount)}`,`size ${N6(L.size)}`,`updated ${qu(L.updatedAt)}`],data:L,onRaw:n,testId:"raw-pipeline-node-messages"}),G(Hr,{title:"Control prompts",subtitle:"manual / monitor append queues",facts:[`manual tail ${Q.total}`,`monitor tail ${w.total}`,`last ${qu(p9(Q.lastAt,w.lastAt))}`],data:{controlPromptsTail:j,monitorPromptsTail:F},onRaw:n,testId:"raw-pipeline-node-prompts"}),G(Hr,{title:"Control events",subtitle:J.eventKinds.length>0?J.eventKinds.join(", "):"event tail",facts:[`tail ${J.total}`,`parsed ${J.parsed}`,`last ${qu(J.lastAt)}`],data:A,onRaw:n,testId:"raw-pipeline-node-events"}),G(Hr,{title:"Worker log",subtitle:"tail is hidden on main canvas",facts:[`tail ${c.length} lines`,"raw only via button",`procedure ${Vr(y)||"--"}`],data:c,onRaw:n,testId:"raw-pipeline-node-worker-log"}))}function HY({activeRun:u,onRaw:l}){if(!u)return G(Qr,{title:"暂无运行材料",text:"没有 Pipeline epoch 时不会展示运行材料索引。"});let f=Du(u.nodes),r=Du(u.procedureRuns),n=Du(u.submissions),i=Du(u.workerLogTail),y=nw(f),t=nw(r),_=r.filter((A)=>String(A?.status||"").toLowerCase()==="failed"),c=p9(...r.flatMap((A)=>[A.updatedAt,A.finishedAt,A.startedAt]));return G("div",{className:"pipeline-evidence-list"},G(Hr,{title:"Epoch overview",subtitle:u.runId||"--",facts:[`pipeline ${u.pipelineId||"--"}`,`status ${u.status||"--"}`,`started ${qu(u.startedAt)}`,`updated ${qu(u.updatedAt)}`],data:u,onRaw:l,testId:"raw-pipeline-run"}),G(Hr,{title:"Node states",subtitle:`${f.length} nodes`,facts:[`running ${y.running||0}`,`succeeded ${y.succeeded||0}`,`failed ${y.failed||0}`,`pending ${y.pending||0}`],data:f,onRaw:l,testId:"raw-pipeline-run-nodes"}),G(Hr,{title:"Procedure run index",subtitle:`${r.length} procedure records`,facts:[`succeeded ${t.succeeded||0}`,`failed ${t.failed||0}`,`latest ${qu(c)}`,`errors ${_.length}`],data:r,onRaw:l,testId:"raw-pipeline-run-procedures"}),G(Hr,{title:"OA submissions",subtitle:`${n.length} submission files`,facts:[`records ${n.length}`,`task ${N6(u.task)}`,"raw grouped by run"],data:n,onRaw:l,testId:"raw-pipeline-run-submissions"}),G(Hr,{title:"Worker log tail",subtitle:"hidden from main interface",facts:[`tail ${i.length} lines`,"display raw only after click",`updated ${qu(u.updatedAt)}`],data:i,onRaw:l,testId:"raw-pipeline-run-worker-log"}))}function BY({diagnostics:u,onRaw:l}){let f=Du(u?.runs).filter(Xu),r=Du(u?.forbiddenResiduals),n=Xu(u?.guarantees)?u.guarantees:{},i=u?.hasNeutralNodeFinishedEvidence===!0&&u?.hasNoAuditPolicyEvidence===!0&&u?.hasAuditPolicyEvidence===!0,y=u?.ok===!0&&i&&r.length===0,t=f[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(pf,{label:"OA Flow",value:y?"100%":"--",hint:String(u?.mode||"waiting diagnostics"),tone:y?"ok":"warn"}),G(pf,{label:"禁止残留",value:r.length,hint:r.length===0?"source scan clean":"needs cleanup",tone:r.length===0?"ok":"warn"}),G(pf,{label:"No-audit",value:u?.hasNoAuditPolicyEvidence?"OK":"--",hint:"OA 下游策略证据",tone:u?.hasNoAuditPolicyEvidence?"ok":"warn"}),G(pf,{label:"Monitor 审核",value:u?.hasAuditPolicyEvidence?"OK":"--",hint:"OA 控制事件闭环",tone:u?.hasAuditPolicyEvidence?"ok":"warn"})),G("div",{className:"pipeline-oa-guarantees"},_.map((c)=>G("article",{key:c.label,className:`pipeline-oa-guarantee ${c.ok?"ok":"warn"}`},G(bn,{status:c.ok?"online":"warn"},c.ok?"OK":"MISS"),G("div",null,G("strong",null,c.label),G("span",null,c.hint))))),G("div",{className:"pipeline-evidence-list compact"},f.slice(0,6).map((c)=>G(Hr,{key:c.runId,title:String(c.runId||"--"),subtitle:[Number(c.monitorAuditNodeFinishedCount||0)>0?"monitor audit":"",Number(c.noAuditPolicyCount||0)>0?"no-audit policy":""].filter(Boolean).join(" / ")||"event evidence",facts:[`events ${c.eventCount||0}`,`node-finished ${c.nodeFinishedCount||0}`,`policy-in-detail ${c.nodeFinishedWithPolicyCount||0}`,`queued ${c.controlQueuedCount||0}`,`applied ${c.controlAppliedCount||0}`],data:c,onRaw:l,testId:`raw-pipeline-oa-run-${String(c.runId||"run").replace(/[^a-zA-Z0-9_.-]+/g,"-")}`}))),t?G("p",{className:"muted paragraph"},`最新证据 ${t.runId}: ${t.nodeFinishedCount||0} 个 node-finished,${t.controlAppliedCount||0} 个控制结果。`):G(Qr,{title:"暂无 OA 事件流证据",text:"等待 Pipeline backend 暴露 diagnostics。"}),u?G("div",{className:"panel-actions inline-actions"},G(sr,{title:"Pipeline OA Event Flow Diagnostics",data:u,onOpen:l,testId:"raw-pipeline-oa-event-flow"})):null)}function VY({quota:u,onRaw:l}){let f=Xu(u?.summary)?u.summary:{},r=Xu(u?.target)?u.target:{},n=Xu(u?.cache)?u.cache:{},i=u?.ok===!0,y=String(u?.modelId||f.modelName||r.modelName||"MiniMax-M2.7"),t=f.totalCount??r.currentIntervalTotalCount,_=f.usageCount??r.currentIntervalUsageCount,c=f.remainingCount??r.currentIntervalRemainingCount,A=f.remainingRatio??(Number.isFinite(Number(t))&&Number(t)>0&&Number.isFinite(Number(c))?Number(c)/Number(t):void 0),j=f.usageRatio??(Number.isFinite(Number(t))&&Number(t)>0&&Number.isFinite(Number(_))?Number(_)/Number(t):void 0),F=f.resetAt||r.endAt,J=f.remainsMs??r.remainsMs,Q=Number(c),w=!i||Number.isFinite(Q)&&Q<=0?"warn":"ok",L=[i?`endpoint ${u?.endpoint||"--"}`:"quota unavailable",`fetched ${Q6(u?.fetchedAt)}`,n.hit?`cache ${Br(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(pf,{label:"MiniMax",value:i?y:"--",hint:u?.modelComponent||u?.error||"model/minimax-m27",tone:w}),G(pf,{label:"当前窗口",value:`${L9(_)}/${L9(t)}`,hint:`已用 ${rw(j)}`,tone:w}),G(pf,{label:"剩余额度",value:L9(c),hint:`剩余 ${rw(A)}`,tone:w}),G(pf,{label:"重置时间",value:Q6(F),hint:J!==void 0?`约 ${Br(J)}`:qu(F),tone:w})),G(P9,{items:L}),i?G("p",{className:"muted paragraph"},`MiniMax 限额来自 D601 Pipeline 后端实时查询;当前模型匹配 ${f.modelName||r.modelName||y}。`):G(il,{error:u?.error||"MiniMax 限额查询失败"}),u?G("div",{className:"panel-actions inline-actions"},G(sr,{title:"Pipeline MiniMax Quota",data:u,onOpen:l,testId:"raw-pipeline-minimax-quota"})):null)}function DY({epochs:u,activeRun:l,activePipeline:f,pipelineNodes:r,pipelineEdges:n,runDetails:i,nodeDetails:y,nodeDetailsState:t,ganttScale:_=P_,onGanttScaleChange:c,onRunChange:A,onIntervalSelect:j,onMarkerSelect:F,selection:J,detailOpen:Q,onDetailOpenChange:w,onRaw:L}){let[U,N]=af($Y),[q,W]=af({startY:0,endY:0,startMs:0,endMs:0}),[z,Z]=af(Date.now()),H=xn(null),E=String(l?.runId||""),D=Boolean(Q),h=(Au)=>{if(typeof w==="function")w(Au)},V=vn(_??P_),S=String(i?.runId||"")===E?i?.details:null,p=S?{...Xu(l)?l:{},...Xu(S)?S:{},runId:E,procedureRuns:Du(S?.procedureRuns).length>0?S.procedureRuns:l?.procedureRuns}:l,O=Sw(p,r,z),m=S?ZY(S,p):{markers:[],arrows:[]},X=Du(m.markers),v=_Y(p,O,X),T=UY(v,V,O,z),Y=String(T.source||"frontend-y"),k=O.map((Au)=>JY(Au,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=h9(V),o={...b,pxPerMinute:Number(T.pxPerMinute??b.pxPerMinute)},g=Math.round(Number(T.chartHeight||360)),x=O.some(b9);U0(()=>{if(!E||!x)return;let Au=window.setInterval(()=>Z(Date.now()),1000);return()=>window.clearInterval(Au)},[E,x]);let lu=dS(f,r,Array.isArray(n)?n:[]),_u=r.map((Au)=>String(Au?.id||"")).filter(Boolean),$u=k.map((Au)=>String(Au.nodeId||"")).filter(Boolean),ju=X.map((Au)=>String(Au.nodeId||"")).filter(Boolean),zu=Array.from(new Set([...lu,..._u,...$u,...ju])),Wu={startY:0,endY:g,startMs:Number(I.startMs),endMs:Number(I.endMs)},P=Number(q?.endY||0)>0?q:Wu,e=(Au)=>{return G6(Au,I,g,T)<=Number(P.endY)&&Y9(Au,I,g,T)>=Number(P.startY)},uu=(Au)=>{let su=Jr(Au,I,g,T);return su>=Number(P.startY)&&su<=Number(P.endY)},Ku=new Set(zu.filter((Au)=>k.some((su)=>su.nodeId===Au&&e(su))||X.some((su)=>su.nodeId===Au&&uu(su)))),s=U?zu.filter((Au)=>Ku.has(Au)):zu,Nu=`${W9}px ${s.length>0?s.map(()=>`${j0}px`).join(" "):"minmax(160px, 1fr)"}`,Eu=Du(T.ticks).filter(Xu),Hu=String(J?.mode==="interval"?J?.interval?.procedureRunId||"":""),vu=String(J?.mode==="event"?J?.marker?.id||"":""),ul=()=>{let Au=H.current;if(!Au){W(Wu);return}let su=Math.max(0,Au.scrollTop-w9),Jf=Math.max(120,Au.clientHeight-w9),pu=Math.min(g,su+Jf),ff={startY:su,endY:pu,startMs:Number(I.startMs),endMs:Number(I.endMs)},rf=Math.max(0,Math.min(1,su/g)),ur=Math.max(rf,Math.min(1,pu/g)),nf=Math.max(1,Number(I.endMs)-Number(I.startMs));ff.startMs=Number(I.startMs)+nf*rf,ff.endMs=Number(I.startMs)+nf*ur,W(ff)};U0(()=>{let Au=H.current,su=window.setTimeout(ul,0);return Au?.addEventListener("scroll",ul),window.addEventListener("resize",ul),()=>{window.clearTimeout(su),Au?.removeEventListener("scroll",ul),window.removeEventListener("resize",ul)}},[E,I.startMs,I.endMs,g]);let mu=Math.max(0,zu.length-s.length),Fl=new Set(X.filter((Au)=>s.includes(String(Au.nodeId||""))&&uu(Au)).map((Au)=>String(Au.id))),Uf=new Map(X.map((Au)=>[String(Au.id),Au])),Ef=Du(m.arrows).filter((Au)=>{if(!Fl.has(String(Au.targetMarkerId||"")))return!1;if(String(Au.action||"")==="observe")return s.includes(String(Au.sourceNodeId||""));return Fl.has(String(Au.sourceMarkerId||""))}),lf=W9+Math.max(1,s.length)*j0,ol=(Au)=>{let su=vn(Au.target.value);if(typeof c==="function")c(su);window.setTimeout(ul,0)},Zf=()=>iY({title:`${f?.id||"pipeline"}-${E||"epoch"}-gantt`,meta:[`run ${E||"--"}`,`${qu(I.startMs)} -> ${qu(I.endMs)}`,`duration ${Br(I.durationMs)}`,`${o.label} / ${E9(o.pxPerMinute)} px/min`,`${s.length}/${zu.length} nodes`,`${X.length} markers`],visibleNodeIds:s,intervals:k,markers:X.filter((Au)=>s.includes(String(Au.nodeId||""))),arrows:Ef,ticks:Eu,bounds:I,chartHeight:g,backendLayout:T}),mf=Xu(S?.gantt?.diagnostics)?S.gantt.diagnostics:null;return G(F0,{title:"Epoch 甘特图",eyebrow:`${f?.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:(Au)=>A(Au.target.value),"data-testid":"pipeline-epoch-select"},u.map((Au)=>G("option",{key:Au.runId,value:Au.runId},X9(u,Au)))),G("label",{className:"pipeline-gantt-toggle"},G("input",{type:"checkbox","data-testid":"pipeline-gantt-auto-hide-idle",checked:U,onChange:(Au)=>{N(Boolean(Au.target.checked)),window.setTimeout(ul,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} · ${E9(o.pxPerMinute)} px/min`)),G("input",{type:"range",min:0,max:100,step:0.01,value:V,onChange:ol,"aria-label":"调整甘特图时间尺度","data-testid":"pipeline-gantt-time-scale"}),G("small",null,G("span",null,"全局"),G("span",null,"细节"))),l?G("button",{type:"button",className:"ghost-btn",onClick:Zf,disabled:s.length===0,"data-testid":"pipeline-export-gantt"},"导出甘特图"):null,l?G(sr,{title:`Pipeline Epoch ${l.runId}`,data:l,onOpen:L,testId:"raw-pipeline-epoch-gantt"}):null)},!l?G(Qr,{title:"暂无 Epoch",text:"当前 pipeline 还没有完整运行记录。"}):k.length===0?G(Qr,{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 ${qu(I.startMs)} -> ${qu(I.endMs)}`),G("span",null,`duration ${Br(I.durationMs)}`),G("span",null,`scale ${o.label} / ${E9(o.pxPerMinute)} px/min`),G("span",null,`layout ${Y}`),mf?G("span",null,`align ${mf.timeAxisAlignmentOk===!1?"check":"ok"}`):null,G("span",null,`visible ${s.length}/${zu.length} nodes`),S?G("span",null,`markers ${X.length}`):null,U&&mu>0?G("span",null,`hidden idle ${mu}`):null),!D?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!J?.mode,onClick:()=>h(!0),"data-testid":"pipeline-gantt-sidebar-toggle"},J?.mode?"展开详情":"点击甘特图元素展开详情"):null),G("div",{className:"pipeline-gantt-viewport",ref:H,"data-testid":"pipeline-epoch-gantt","data-pipeline-id":f?.id||"","data-run-id":E,"data-layout-source":Y,"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:Nu,minWidth:`${lf}px`}},G("div",{className:"pipeline-gantt-head time"},"Time"),s.length===0?G("div",{className:"pipeline-gantt-head empty"},"当前时间窗无工作节点"):s.map((Au)=>G("div",{key:`head-${Au}`,className:"pipeline-gantt-head node",title:Au,"data-testid":"pipeline-gantt-head-node","data-node-id":Au},G(XS,{value:Au}))),G("div",{className:"pipeline-gantt-time-axis",style:{height:`${g}px`}},Eu.map((Au)=>{let su=Mw(Au,I,g,T);return G("div",{key:`tick-${Au.ms}-${su}`,className:"pipeline-gantt-tick",style:{top:`${su}px`},"data-testid":"pipeline-gantt-tick","data-ms":String(Au.ms),"data-y":String(su)},G("b",null,qu(Au.ms)),G("span",null,`+${Br(Number(Au.offsetMs??Number(Au.ms)-Number(I.startMs)))}`))})),s.length>0?G("svg",{className:"pipeline-gantt-arrow-layer",width:s.length*j0,height:g,viewBox:`0 0 ${s.length*j0} ${g}`,style:{left:`${W9}px`,top:`${w9}px`,width:`${s.length*j0}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"}))),Ef.map((Au)=>{let su=Uf.get(String(Au.targetMarkerId||""));if(!su)return null;let Jf=Uf.get(String(Au.sourceMarkerId||"")),pu=String(Jf?.nodeId||Au.sourceNodeId||""),ff=s.indexOf(pu),rf=s.indexOf(String(su.nodeId||""));if(ff<0||rf<0)return null;let ur=ff*j0+j0/2,nf=rf*j0+j0/2,Of=Jf?Jr(Jf,I,g,T):Jr(su,I,g,T),N0=Jr(su,I,g,T);return G("path",{key:Au.id,className:`pipeline-gantt-arrow ${String(Au.sourceKind||"").toLowerCase()} ${String(Au.status||"").toLowerCase()} ${String(Au.action||"").toLowerCase()}`,d:Rw(ur,Of,nf,N0),markerEnd:"url(#pipeline-gantt-arrowhead)","data-testid":String(Au.action||"")==="observe"?"pipeline-gantt-observation-arrow":"pipeline-gantt-arrow","data-source-node-id":String(Au.sourceNodeId||""),"data-target-node-id":String(Au.targetNodeId||""),"data-target-marker-id":String(Au.targetMarkerId||""),"data-action":String(Au.action||""),"data-source-y":String(Of),"data-target-y":String(N0)})})):null,s.length===0?G("div",{className:"pipeline-gantt-empty-col",style:{height:`${g}px`}},"滚动到有活动的时间段后,相关 node 列会自动出现。"):s.map((Au)=>{let su=k.filter((pu)=>pu.nodeId===Au),Jf=X.filter((pu)=>String(pu.nodeId||"")===Au);return G("div",{key:`col-${Au}`,className:"pipeline-gantt-node-col",style:{height:`${g}px`}},su.map((pu)=>{let ff=G6(pu,I,g,T),rf=Y9(pu,I,g,T),ur=Cw(pu,I,g,T),nf=String(pu.procedureRunId||`${Au}-${pu.startMs}`);return G("button",{key:nf,type:"button",className:`pipeline-gantt-bar ${pu.status} ${pu.live?"live":""} ${Hu===nf?"selected":""}`,style:{top:`${ff}px`,height:`${ur}px`},title:`${Au} ${pu.status} ${qu(pu.startedAt||pu.startMs)} -> ${qu(pu.finishedAt||pu.endMs)}`,onClick:()=>j(pu),"data-testid":"pipeline-gantt-line","data-node-id":Au,"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(ff),"data-y2":String(rf),"data-natural-height":String(Math.max(0,rf-ff))},G("strong",null,pu.status||"working"),G("span",null,Br(pu.durationMs)))}),Jf.map((pu)=>G("button",{key:pu.id,type:"button",className:`pipeline-gantt-marker ${pu.kind} ${pu.tone||""} ${pu.status||""} ${vu===String(pu.id)?"selected":""}`,style:{top:`${Jr(pu,I,g,T)}px`},title:`${pu.label||"event"} / ${qu(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,g,T))})))})))),D?G(DS,{selection:J,runDetails:i,nodeDetails:y,nodeDetailsState:t,onRaw:L,onCollapse:()=>h(!1)}):null)))}function h0(){return{loading:!1,actionLoading:"",error:"",message:"",details:null,fetchedAt:null,appendPrompt:"",guidePrompt:"",modifyPrompt:"",approveReason:"",redoReason:""}}function Rn(){return{mode:"",runId:"",interval:null,marker:null}}function Z9(){return{runId:"",loading:!1,error:"",details:null,fetchedAt:null}}function V_(u,l){return`${u}/microservices/pipeline/proxy${l}`}function XY({activeRun:u,pipelineRuns:l,selectedRunId:f,onRunChange:r,selectedNodeId:n,selectedNodeConfig:i,selectedNodeRuntime:y,control:t,onControlChange:_,onFetch:c,onAction:A,onRaw:j,onCollapse:F}){let J=String(u?.runId||""),Q=String(y?.status||"pending"),w=!J||!n||t.loading||Boolean(t.actionLoading),L=(N)=>(q)=>_({[N]:q.target.value,error:"",message:""}),U=l.length>0?l: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(nl,{title:n||"点击控制图中的 node",level:3,loading:t.loading||Boolean(t.actionLoading)})),G("div",{className:"pipeline-node-control-head-actions"},n?G(bn,{status:Q},Q):G(bn,{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:J||f,disabled:U.length===0,onChange:(N)=>r(N.target.value),"data-testid":"pipeline-node-run-select"},U.map((N)=>G("option",{key:N.runId,value:N.runId},`${N.runId||"--"} / ${N.status||"--"}`)))),G("button",{type:"button",className:"ghost-btn",disabled:w,onClick:c,"data-testid":"pipeline-node-fetch"},t.loading?"抓取中":"抓取过程"),t.details?G(sr,{title:`Pipeline Node ${n}`,data:t.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"),qu(u?.updatedAt))),!n?G(Qr,{title:"未选择 node",text:"点击 React Flow 控制图中的任意 node 后,可抓取执行过程、追加 prompt、下发引导、增量修改、审核通过或重做。"}):null,G(il,{error:t.error,wide:!0}),G("div",{className:"pipeline-control-actions"},G("label",null,G("span",null,"实时追加 prompt(仅 running node)"),G("textarea",{value:t.appendPrompt,onChange:L("appendPrompt"),placeholder:"让当前执行中的 agent 继续、补充检查或调整当前步骤...",rows:4,disabled:!n,"data-testid":"pipeline-node-append-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:w||!String(t.appendPrompt||"").trim(),onClick:()=>A("append"),"data-testid":"pipeline-node-append-button"},t.actionLoading==="append"?"追加中":"追加到运行中 node")),G("label",null,G("span",null,"下次尝试引导 prompt"),G("textarea",{value:t.guidePrompt,onChange:L("guidePrompt"),placeholder:"给该 node 下一次 attempt 的执行提示;不会立即打断当前 session。",rows:4,disabled:!n,"data-testid":"pipeline-node-guide-input"}),G("button",{type:"button",className:"ghost-btn compact",disabled:w||!String(t.guidePrompt||"").trim(),onClick:()=>A("guide"),"data-testid":"pipeline-node-guide-button"},t.actionLoading==="guide"?"下发中":"下发 guide")),G("label",null,G("span",null,"完成后增量修改 prompt"),G("textarea",{value:t.modifyPrompt,onChange:L("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:w||!String(t.modifyPrompt||"").trim(),onClick:()=>A("modify"),"data-testid":"pipeline-node-modify-button"},t.actionLoading==="modify"?"排队中":"增量修改 node")),G("label",null,G("span",null,"Monitor 审核通过原因"),G("textarea",{value:t.approveReason,onChange:L("approveReason"),placeholder:"当流程配置开启 monitor 审核时,记录审核通过原因并释放后续 node。",rows:3,disabled:!n,"data-testid":"pipeline-node-approve-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:w||!String(t.approveReason||"").trim(),onClick:()=>A("approve"),"data-testid":"pipeline-node-approve-button"},t.actionLoading==="approve"?"提交中":"审核通过")),G("label",null,G("span",null,"重做 / restart 原因"),G("textarea",{value:t.redoReason,onChange:L("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:w||!String(t.redoReason||"").trim(),onClick:()=>A("redo"),"data-testid":"pipeline-node-redo-button"},t.actionLoading==="redo"?"排队中":"重做 node"))),G("div",{className:"pipeline-control-evidence"},G("strong",null,"Node 过程索引"),G(OY,{details:t.details,selectedNodeId:n,selectedNodeRuntime:y,control:t,onRaw:j})))}function xw({microservices:u,onRaw:l,apiBaseUrl:f="/api"}){let r=u.find((fu)=>fu.id==="pipeline")||null,[n,i]=af({loading:!1,error:"",health:null,snapshot:null,oaDiagnostics:null,minimaxQuota:null,refreshedAt:null}),[y,t]=af(""),[_,c]=af(""),[A,j]=af(""),[F,J]=af(h0()),[Q,w]=af({}),[L,U]=af(Rn()),[N,q]=af(Z9()),[W,z]=af(P_),[Z,H]=af(!1),[E,D]=af(!1),h=xn(0),{addNotification:V}=Xf(),S=xn(!1),p=xn(0),O=xn(""),m=xn({}),X=xn(""),v=xn("");async function T(fu={}){let Bu=fu.silent===!0;if(!r)return;if(S.current)return;S.current=!0;let Yu=h.current+1;if(h.current=Yu,!Bu)i((au)=>({...au,loading:!0,error:""}));try{let au=`__unideskArrayLimit=registry.components:80,runs:${JS}`,[_l,Pl,yl]=await Promise.all([Mn(`${f}/microservices/pipeline/proxy/api/snapshot?${au}`,{cache:"no-store"}),Mn(`${f}/microservices/pipeline/proxy/api/oa-event-flow/diagnostics`,{cache:"no-store"}).catch((Xr)=>({ok:!1,error:Ou(Xr,"OA event flow diagnostics failed")})),Mn(`${f}/microservices/pipeline/proxy/api/model-quota/minimax`,{cache:"no-store"}).catch((Xr)=>({ok:!1,error:Ou(Xr,"MiniMax quota failed")}))]);if(Yu!==h.current)return;let Qf={ok:_l?.ok!==!1,service:"pipeline-v2-control snapshot"};i({loading:!1,error:"",health:Qf,snapshot:_l,oaDiagnostics:Pl,minimaxQuota:yl,refreshedAt:new Date})}catch(au){if(Yu!==h.current)return;i((_l)=>({..._l,loading:!1,error:Ou(au,"Pipeline 加载失败")}))}finally{S.current=!1}}U0(()=>{if(T(),!r)return;let fu=()=>{if(A6())T({silent:!0})},Bu=window.setInterval(()=>{fu()},uw),Yu=()=>{if(A6())fu()};return document.addEventListener("visibilitychange",Yu),()=>{window.clearInterval(Bu),document.removeEventListener("visibilitychange",Yu)}},[r?.id,r?.runtime?.providerStatus,f]);let Y=SS(r),k=pS(r),I=YS(r),b=n.snapshot||{},o=n.oaDiagnostics||null,g=n.minimaxQuota||null,{components:x,pipelines:lu,runs:_u}=mS(b),$u=String(_u[0]?.pipelineId||""),ju=($u?lu.find((fu)=>String(fu.id||"")===$u):null)||lu[0]||{},zu=lu.find((fu)=>String(fu.id||"")===y)||ju,Wu=String(zu.id||""),P=Hw(zu),e=M9(zu),uu=Qw(_u,Wu),Ku=tY(_u,Wu),s=Ku.find((fu)=>String(fu?.runId||"")===_)||uu,Nu=String(N.runId||"")===String(s?.runId||"")?RS(N.details):null,Eu=xS(s,Nu),Hu=String(Eu?.runId||""),vu=P.find((fu)=>String(fu?.id||"")===A)||null,ul=A?Bw(Eu,A):null,mu=CS(_u),Fl=kS(x),Uf=Number(n.health?.components)||$w(b,"registry.components",x.length),Ef=$w(b,"runs",_u.length),lf=jw(zu,Eu,x),ol={nodes:lf.nodes.map((fu)=>fu.id===A?{...fu,selected:!0,className:`${fu.className||""} selected-control-node`}:fu),edges:lf.edges},Zf=lu.map((fu)=>{let Bu=String(fu.id||"pipeline"),Yu=Qw(_u,Bu);return{title:`${Bu}-${Yu?.runId||"snapshot"}`,flow:jw(fu,Yu,x)}}),mf=String(L?.runId||Hu||""),Au=String(L?.interval?.nodeId||L?.marker?.nodeId||""),su=mf&&Au?Q[T9(mf,Au)]||null:null,Jf=q6(F.details,mf,Au),pu=q6(su?.details,mf,Au)||Jf,ff=mf&&Au?{...Xu(su)?su:{},runId:mf,nodeId:Au,details:pu,loading:Boolean(su?.loading)||!pu&&Boolean(F.loading)&&A===Au,error:String(su?.error||""),fetchedAt:su?.fetchedAt||(Jf?F.fetchedAt:null)}:null,rf=Ku.map((fu)=>String(fu?.runId||"")).filter(Boolean).join("|"),ur=P.map((fu)=>String(fu?.id||"")).filter(Boolean).join("|");U0(()=>{X.current=A},[A]),U0(()=>{v.current=Hu},[Hu]),U0(()=>{if(!_||rf.split("|").includes(_))return;c("")},[_,rf]),U0(()=>{if(!A||ur.split("|").includes(A))return;j(""),J(h0()),U(Rn()),H(!1),D(!1)},[A,ur]),U0(()=>{if(!A)H(!1)},[A]),U0(()=>{if(!L.mode)D(!1)},[L.mode]);async function nf(fu=Hu,Bu={}){if(!fu){q(Z9());return}let Yu=vn(Bu.scale??W??P_),au=`${fu}:timeline`;if(O.current===au)return;O.current=au;let _l=Bu.silent===!0,Pl=p.current+1;p.current=Pl,q((yl)=>({runId:fu,scale:Yu,loading:!_l||String(yl.runId||"")!==fu||!yl.details,error:"",details:_l&&yl.runId===fu?yl.details:yl.runId===fu?yl.details:null,fetchedAt:yl.runId===fu?yl.fetchedAt:null}));try{let[yl,Qf]=await Promise.all([Mn(V_(f,`/api/node-control/runs/${encodeURIComponent(fu)}?tail=160&view=timeline`),{cache:"no-store",strictJson:!0}),Mn(V_(f,`/api/runs/${encodeURIComponent(fu)}`),{cache:"no-store"}).catch((Xr)=>({ok:!1,runSummaryError:Ou(Xr,"抓取评分失败")}))]);if(Pl!==p.current)return;q({runId:fu,scale:Yu,loading:!1,error:"",details:{...yl,run:Xu(Qf?.run)?Qf.run:void 0,runSummaryError:Qf?.runSummaryError},fetchedAt:new Date})}catch(yl){if(Pl!==p.current)return;q((Qf)=>({runId:fu,scale:Yu,loading:!1,error:Ou(yl,"抓取 epoch 执行过程失败"),details:Qf.runId===fu?Qf.details:null,fetchedAt:Qf.runId===fu?Qf.fetchedAt:null}))}finally{if(O.current===au)O.current=""}}function Of(fu,Bu,Yu){let au=T9(fu,Bu);w((_l)=>{let Pl={..._l,[au]:{...Xu(_l?.[au])?_l[au]:{},runId:fu,nodeId:Bu,...Yu}},yl=Object.keys(Pl);if(yl.length>32)for(let Qf of yl.slice(0,yl.length-32))delete Pl[Qf];return Pl})}async function N0(fu,Bu){if(!fu||!Bu)return;let Yu=T9(fu,Bu),au=Number(m.current?.[Yu]||0)+1;m.current={...m.current,[Yu]:au},Of(fu,Bu,{loading:!0,error:""});try{let _l=await Mn(V_(f,`/api/node-control/runs/${encodeURIComponent(fu)}/nodes/${encodeURIComponent(Bu)}?tail=160`),{cache:"no-store",strictJson:!0});if(Number(m.current?.[Yu]||0)!==au)return;let Pl=new Date;if(Of(fu,Bu,{loading:!1,details:_l,fetchedAt:Pl,error:""}),X.current===Bu&&v.current===fu)J((yl)=>({...yl,loading:!1,details:_l,fetchedAt:Pl,error:""}))}catch(_l){if(Number(m.current?.[Yu]||0)!==au)return;Of(fu,Bu,{loading:!1,error:Ou(_l,"抓取 Gantt node 详情失败")})}}U0(()=>{if(!Hu){q(Z9());return}nf(Hu);let fu=()=>{if(A6())nf(Hu,{silent:!0})},Bu=window.setInterval(()=>{fu()},uw),Yu=()=>{if(A6())fu()};return document.addEventListener("visibilitychange",Yu),()=>{window.clearInterval(Bu),document.removeEventListener("visibilitychange",Yu)}},[Hu,f]);async function lr(fu=Hu,Bu=A){if(!fu||!Bu){J((Yu)=>({...Yu,error:"请先选择 run 和 node",message:""}));return}J((Yu)=>({...Yu,loading:!0,error:"",message:""}));try{let Yu=await Mn(V_(f,`/api/node-control/runs/${encodeURIComponent(fu)}/nodes/${encodeURIComponent(Bu)}?tail=160`),{cache:"no-store",strictJson:!0}),au=new Date;J((_l)=>({..._l,loading:!1,details:Yu,fetchedAt:au,error:""})),Of(fu,Bu,{loading:!1,details:Yu,fetchedAt:au,error:""})}catch(Yu){J((au)=>({...au,loading:!1,error:Ou(Yu,"抓取 node 执行过程失败")}))}}async function k0(fu){let Bu=String(fu?.runId||Hu||""),Yu=String(fu?.nodeId||"");if(U({mode:"interval",runId:Bu,interval:fu,marker:null}),D(!0),!Bu||!Yu)return;if(Bu!==Hu)c(Bu);j(Yu),J(h0()),nf(Bu,{silent:!0}),N0(Bu,Yu)}async function Ul(fu){let Bu=String(fu?.runId||Hu||""),Yu=String(fu?.nodeId||"");if(U({mode:"event",runId:Bu,interval:null,marker:fu}),D(!0),!Bu)return;if(Bu!==Hu)c(Bu);if(nf(Bu,{silent:!0}),!Yu)return;j(Yu),J(h0()),N0(Bu,Yu)}async function bi(fu){if(!Hu||!A){J((au)=>({...au,error:"请先选择 run 和 node",message:""}));return}let Bu=fu==="append"?"prompts":fu,Yu=fu==="append"?F.appendPrompt:fu==="guide"?F.guidePrompt:fu==="modify"?F.modifyPrompt:fu==="approve"?F.approveReason:F.redoReason;if(!String(Yu||"").trim()){J((au)=>({...au,error:"操作内容不能为空",message:""}));return}J((au)=>({...au,actionLoading:fu,error:"",message:""}));try{let au=fu==="redo"||fu==="approve"?{reason:Yu,source:"unidesk-frontend",sourceKind:"webui"}:{prompt:Yu,source:"unidesk-frontend",sourceKind:"webui"},_l=await Mn(V_(f,`/api/node-control/runs/${encodeURIComponent(Hu)}/nodes/${encodeURIComponent(A)}/${Bu}`),{method:"POST",body:JSON.stringify(au)});if(J((yl)=>({...yl,actionLoading:"",details:_l,fetchedAt:new Date,appendPrompt:fu==="append"?"":yl.appendPrompt,guidePrompt:fu==="guide"?"":yl.guidePrompt,modifyPrompt:fu==="modify"?"":yl.modifyPrompt,approveReason:fu==="approve"?"":yl.approveReason,redoReason:fu==="redo"?"":yl.redoReason,message:fu==="append"?"已追加到运行中 node":fu==="guide"?"已下发 guide,等待 runner 处理":fu==="modify"?"已排队增量修改命令":fu==="approve"?"已提交审核通过决策":"已排队重做命令"})),V("success",fu==="append"?"已追加到运行中 node":fu==="guide"?"已下发 guide,等待 runner 处理":fu==="modify"?"已排队增量修改命令":fu==="approve"?"已提交审核通过决策":"已排队重做命令"),await lr(Hu,A),await nf(Hu,{silent:!0}),fu!=="append")await T()}catch(au){J((_l)=>({..._l,actionLoading:"",error:Ou(au,"node 控制操作失败")}))}}if(!r)return G(Qr,{title:"Pipeline 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=pipeline"});return G("div",{className:"pipeline-page","data-testid":"pipeline-page"},G(F0,{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(sr,{title:"Pipeline 用户服务",data:r,onOpen:l,testId:"raw-pipeline-service"}))},G("div",{className:"pipeline-hero"},G("div",null,G("div",{className:"node-version-line"},G(bn,{status:Y.providerStatus==="online"?"online":"warn"},Y.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(il,{error:n.error,wide:!0})),G("div",{className:"pipeline-grid"},G(F0,{title:"控制图",eyebrow:`${zu.id||"pipeline"} / run ${Eu?.status||"--"}`,className:"pipeline-wide-panel",loading:n.loading,actions:G("div",{className:"pipeline-toolbar"},G("select",{value:Wu,disabled:lu.length===0,onChange:(fu)=>{t(fu.target.value),c(""),j(""),J(h0()),U(Rn()),H(!1),D(!1)},"data-testid":"pipeline-select"},lu.map((fu)=>G("option",{key:fu.id,value:fu.id},fu.id||fu.key))),G("select",{value:Hu,disabled:Ku.length===0,onChange:(fu)=>{if(c(fu.target.value),J(h0()),U(Rn()),H(!1),D(!1),A)lr(fu.target.value,A)},"data-testid":"pipeline-run-select"},Ku.map((fu)=>G("option",{key:fu.runId,value:fu.runId},X9(Ku,fu)))),G("button",{type:"button",className:"ghost-btn",disabled:ol.nodes.length===0,onClick:()=>Xw(ol,`${zu.id||"pipeline"}-${Eu?.runId||"snapshot"}`),"data-testid":"pipeline-export-graph"},"导出渲染图"),G("button",{type:"button",className:"ghost-btn",disabled:Zf.every((fu)=>fu.flow.nodes.length===0),onClick:()=>yY(Zf),"data-testid":"pipeline-export-all-graphs"},"批量导出"))},P.length===0?G(Qr,{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(IW,{nodes:ol.nodes,edges:ol.edges,nodeTypes:wS,edgeTypes:WS,fitView:!0,fitViewOptions:{padding:0.18},nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,minZoom:0.25,maxZoom:1.4,proOptions:{hideAttribution:!0},onNodeClick:(fu,Bu)=>{let Yu=String(Bu.id);if(j(Yu),J(h0()),H(!0),Hu)lr(Hu,Yu)}},G(sW,{gap:22,size:1,color:"rgba(215, 161, 58, 0.24)"}),G(oW,{showInteractive:!1})),!Z?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!A,onClick:()=>H(!0),"data-testid":"pipeline-node-sidebar-toggle"},A?"展开 node 控制":"点击 node 展开控制"):null),Z?G(XY,{activeRun:Eu,pipelineRuns:Ku,selectedRunId:_,onRunChange:(fu)=>{if(c(fu),J(h0()),U(Rn()),A)lr(fu,A)},selectedNodeId:A,selectedNodeConfig:vu,selectedNodeRuntime:ul,control:F,onControlChange:(fu)=>J((Bu)=>({...Bu,...fu})),onFetch:()=>lr(),onAction:bi,onRaw:l,onCollapse:()=>H(!1)}):null),G("div",{className:"pipeline-flow-summary"},G("span",null,`${ol.nodes.length} nodes`),G("span",null,`${ol.edges.length} edges`),G("span",null,`${lu.length} pipelines`),G("span",null,`source config+components(${x.length})`),G("span",null,`run ${Eu?.runId||"--"}`),G("span",null,`score ${D9(Eu)}`),G("span",null,A?`selected ${A}`:"click node to control"))),G(DY,{epochs:Ku,activeRun:Eu,activePipeline:zu,pipelineNodes:P,pipelineEdges:e,selection:L,detailOpen:E,onDetailOpenChange:D,runDetails:N,nodeDetails:pu,nodeDetailsState:ff,ganttScale:W,onGanttScaleChange:z,onIntervalSelect:k0,onMarkerSelect:Ul,onRunChange:(fu)=>{if(c(fu),J(h0()),U(Rn()),D(!1),A)lr(fu,A)},onRaw:l}),G(F0,{title:"观测指标",eyebrow:n.refreshedAt?`Updated ${tl(n.refreshedAt)}`:"Snapshot",loading:n.loading},G("div",{className:"metric-grid"},G(pf,{label:"Health",value:n.health?.ok?"OK":"--",hint:n.health?.service||"D601 /health",tone:n.health?.ok?"ok":"warn"}),G(pf,{label:"组件",value:Uf,hint:"components registry",tone:b?.registry?.ok===!1?"warn":"ok"}),G(pf,{label:"Pipeline",value:lu.length,hint:`${P.length} nodes / ${e.length} edges`}),G(pf,{label:"运行记录",value:Ef,hint:`${mu.succeeded||0} succeeded / ${mu.running||0} running`}),G(pf,{label:"OA 记录",value:Array.isArray(uu?.submissions)?uu.submissions.length:0,hint:uu?.runId||"latest run"}),G(pf,{label:"Procedure",value:Array.isArray(uu?.procedureRuns)?uu.procedureRuns.length:0,hint:uu?.status||"no run"}),G(pf,{label:"Score",value:D9(Eu),hint:Eu?.runId||"selected epoch",tone:x9(Eu)})),G("div",{className:"panel-actions inline-actions"},G(sr,{title:"Pipeline Snapshot",data:b,onOpen:l,testId:"raw-pipeline-snapshot"}))),G(F0,{title:"评分器",eyebrow:Eu?.runId||"selected epoch",loading:n.loading},G(vS,{run:Eu,onRaw:l})),G(F0,{title:"MiniMax 限额",eyebrow:"model/minimax-m27 quota",loading:n.loading},G(VY,{quota:g,onRaw:l})),G(F0,{title:"OA 事件流",eyebrow:"100% event-driven diagnostics",className:"pipeline-wide-panel",loading:n.loading},G(BY,{diagnostics:o,onRaw:l})),G(F0,{title:"组件矩阵",eyebrow:`${Fl.length} classes`,loading:n.loading},Fl.length===0?G(Qr,{title:"暂无组件",text:"等待 D601 pipeline backend 返回 registry.components"}):G("div",{className:"component-strata"},Fl.map((fu)=>G("article",{key:fu.name,className:"component-stratum"},G("span",null,fu.name),G("strong",null,fu.count)))),G("div",{className:"pipeline-component-list"},x.slice(0,12).map((fu)=>G("span",{key:fu.key,className:"data-chip"},G("b",null,fu.componentClass||"--"),G("span",null,fu.id||fu.key||"--"))))),G(F0,{title:"Epoch 列表",eyebrow:`${Ku.length}/${Ef} preview`,loading:n.loading},Ku.length===0?G(Qr,{title:"暂无运行记录",text:"当前 pipeline 在 .state/pipeline-runs 中还没有 epoch。"}):G("div",{className:"pipeline-run-list"},Ku.map((fu)=>{let Bu=String(fu?.runId||"")===Hu?Eu:fu;return G("article",{key:fu.runId,className:`pipeline-run-card ${String(fu.runId||"")===Hu?"active":""}`,role:"button",tabIndex:0,onClick:()=>{c(String(fu.runId||"")),U(Rn())},onKeyDown:(Yu)=>{if(Yu.key==="Enter"||Yu.key===" ")c(String(fu.runId||"")),U(Rn())}},G("div",{className:"node-card-head"},G("strong",null,X9(Ku,fu)),G(bn,{status:fu.status},fu.status||"--")),G("div",{className:"docker-meta compact"},G("span",null,Bu?.pipelineId||"--"),G("span",null,`nodes ${Array.isArray(Bu?.nodes)?Bu.nodes.length:0}`),G("span",null,`oa ${Array.isArray(Bu?.submissions)?Bu.submissions.length:0}`),G("span",null,`procedures ${Array.isArray(Bu?.procedureRuns)?Bu.procedureRuns.length:0}`),G(bS,{run:Bu})),G("p",{className:"muted paragraph"},N6(Bu?.task)),G("span",{className:"pipeline-run-time"},qu(Bu?.updatedAt)))}))),G(F0,{title:"运行材料索引",eyebrow:Eu?.runId||"selected epoch",className:"pipeline-wide-panel",loading:n.loading},G(HY,{activeRun:Eu,onRaw:l}))))}var H6=Pu(Jl(),1);var tu=H6.default.createElement,{useEffect:SY}=H6.default,Z6=H6.default.useState,k9={id:"",sequenceNo:"",contractNo:"",name:"",currentStatus:"",pending:"",paymentStatus:"",notes:""};function YY({status:u,children:l}){let f=String(u||"unknown").toLowerCase();return tu("span",{className:`status-badge ${f}`},l||u||"unknown")}function O6({label:u,value:l,hint:f,tone:r}){return tu("article",{className:`metric-card ${r||""}`},tu("div",{className:"metric-label"},u),tu("div",{className:"metric-value"},l),tu("div",{className:"metric-hint"},f))}function I9({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){return tu("section",{className:`panel ${n||""}`},tu("div",{className:"panel-head"},tu("div",null,l?tu("p",{className:"panel-eyebrow"},l):null,tu(nl,{title:u,loading:i})),f?tu("div",{className:"panel-actions"},f):null),tu("div",{className:"panel-body"},r))}function hw({title:u,data:l,onOpen:f,testId:r}){return tu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>f(u,l)},"查看原始JSON")}function bw({title:u,text:l}){return tu("div",{className:"empty-state"},tu("strong",null,u),tu("span",null,l))}function pY(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function mY(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function PY(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Ny(u,l){return`${u}/microservices/project-manager/proxy${l}`}function CY(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 MY(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 g9(u){return String(u||"item").replace(/[^A-Za-z0-9_-]+/g,"-")}function RY(u){let l=new Uint8Array(u),f="",r=32768;for(let n=0;ntu("tr",{key:n.id,className:l===n.id?"active-row":"","data-testid":`project-manager-row-${g9(n.id)}`},tu("td",null,n.sequenceNo??"--"),tu("td",null,tu("strong",null,n.contractNo||"--"),tu("code",null,n.id||"--")),tu("td",null,tu("strong",null,n.name||"--"),tu("span",{className:"muted block"},n.sourceFile||"--")),tu("td",null,n.currentStatus||"--"),tu("td",null,tu("span",{className:"preline"},n.pending||"--")),tu("td",null,tu(YY,{status:Number(n.paymentRatio||0)>=1?"online":"warn"},n.paymentStatus||"--")),tu("td",null,n.notes||"--"),tu("td",null,tu("div",{className:"inline-actions"},tu("button",{type:"button",className:"ghost-btn",onClick:()=>f(n),"data-testid":`project-manager-edit-${g9(n.id)}`},"编辑"),tu(hw,{title:`Project ${n.contractNo||n.id}`,data:n,onOpen:r,testId:`raw-project-${g9(n.id)}`}))))))))}function vw({microservices:u,onRaw:l,apiBaseUrl:f="/api"}){let r=u.find((E)=>E.id==="project-manager")||null,[n,i]=Z6({loading:!1,saving:!1,importing:!1,exporting:!1,error:"",notice:"",health:null,list:null,refreshedAt:null}),[y,t]=Z6({...k9}),[_,c]=Z6(""),[A,j]=Z6("all"),{addNotification:F}=Xf();async function J(E=_,D=A){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,S]=await Promise.all([Tu(`${f}/microservices/project-manager/health`),Tu(Ny(f,`/api/projects?${h.toString()}`))]);i((p)=>({...p,loading:!1,health:V,list:S,refreshedAt:new Date,error:""}))}catch(h){i((V)=>({...V,loading:!1,error:Ou(h,"Project Manager 加载失败")}))}}SY(()=>{J()},[r?.id,r?.runtime?.providerStatus]);async function Q(E){E.preventDefault(),i((D)=>({...D,saving:!0,error:"",notice:""}));try{let D=MY(y);if(y.id)await Tu(Ny(f,`/api/projects/${encodeURIComponent(y.id)}`),{method:"PUT",body:JSON.stringify(D)});else await Tu(Ny(f,"/api/projects"),{method:"POST",body:JSON.stringify(D)});let h=y.id?"项目已更新":"项目已创建";i((V)=>({...V,saving:!1,notice:h})),F("success",h),await J()}catch(D){i((h)=>({...h,saving:!1,error:Ou(D,"保存项目失败")}))}}async function w(){if(!y.id)return;if(!window.confirm(`删除项目 ${y.contractNo||y.name||y.id} ?`))return;i((E)=>({...E,saving:!0,error:"",notice:""}));try{await Tu(Ny(f,`/api/projects/${encodeURIComponent(y.id)}`),{method:"DELETE"}),t({...k9});let E="项目已删除";i((D)=>({...D,saving:!1,notice:E})),F("success",E),await J()}catch(E){i((D)=>({...D,saving:!1,error:Ou(E,"删除项目失败")}))}}async function L(E){let D=E.target.files?.[0];if(!D)return;i((h)=>({...h,importing:!0,error:"",notice:""}));try{let h=RY(await D.arrayBuffer()),S=`Excel 已导入 ${(await Tu(Ny(f,"/api/import/excel"),{method:"POST",body:JSON.stringify({fileName:D.name,contentBase64:h,replace:!1})})).imported||0} 条项目`;i((p)=>({...p,importing:!1,notice:S})),F("success",S),E.target.value="",await J()}catch(h){i((V)=>({...V,importing:!1,error:Ou(h,"Excel 导入失败")}))}}async function U(){i((E)=>({...E,exporting:!0,error:""}));try{let E=await cJ(Ny(f,"/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:Ou(E,"Excel 导出失败")}))}}if(!r)return tu(bw,{title:"Project Manager 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=project-manager"});let N=pY(r),q=PY(r),W=mY(r),z=Array.isArray(n.list?.projects)?n.list.projects:[],Z=n.list?.summary||{},H=n.health||{};return tu("div",{className:"project-manager-page","data-testid":"project-manager-page"},tu(I9,{title:"项目管理工作台",eyebrow:"Main Server PostgreSQL 用户服务",loading:n.loading||n.exporting,actions:tu("div",{className:"panel-actions"},tu("button",{type:"button",className:"ghost-btn",disabled:n.loading,onClick:()=>J(),"data-testid":"project-manager-refresh-button"},n.loading?"刷新中":"刷新"),tu("button",{type:"button",className:"ghost-btn",disabled:n.exporting,onClick:U,"data-testid":"project-manager-export-button"},n.exporting?"导出中":"导出 Excel"),tu(hw,{title:"Project Manager 用户服务",data:r,onOpen:l,testId:"raw-project-manager-service"}))},tu("div",{className:"project-manager-hero"},tu(O6,{label:"项目总数",value:Z.total??z.length,hint:`PG 表 ${H.storage?.table||"project_manager_projects"}`,tone:"ok"}),tu(O6,{label:"进行中",value:Z.active??"--",hint:"当前状态未完全完成"}),tu(O6,{label:"已完成",value:Z.completed??"--",hint:"按 完成 关键字统计",tone:"ok"}),tu(O6,{label:"未全款",value:Z.unpaid??"--",hint:"付款比例 < 1",tone:Number(Z.unpaid||0)>0?"warn":"ok"})),tu(il,{error:n.error}),n.notice?tu("div",{className:"form-success"},n.notice):null),tu("div",{className:"project-manager-hero"},tu("div",{className:"microservice-ref-card"},tu("span",null,"Repo"),tu("strong",null,q.url||"--"),tu("code",null,q.commitId||"--")),tu("div",{className:"microservice-ref-card"},tu("span",null,"Main Server Docker"),tu("strong",null,`${W.nodeBindHost||"--"}:${W.nodePort||"--"}`),tu("code",null,`${q.composeService||"--"} / ${q.containerName||"--"}`)),tu("div",{className:"microservice-ref-card"},tu("span",null,"Runtime"),tu("strong",null,N.providerName||r.providerId),tu("code",null,`Health ${H.ok?"OK":"--"} / ${n.refreshedAt?tl(n.refreshedAt):"--"}`)),tu("div",{className:"microservice-ref-card"},tu("span",null,"Import Source"),tu("strong",null,"D601 WeChat Excel"),tu("code",null,"合作项目列表_I_20260309.xlsx"))),tu("div",{className:"project-manager-layout"},tu(I9,{title:"项目清单",eyebrow:"CRUD + Excel Export",loading:n.loading||n.importing||n.exporting,actions:tu("div",{className:"inline-actions project-manager-filters"},tu("input",{value:_,onChange:(E)=>c(E.target.value),placeholder:"搜索合同号 / 项目名称 / 状态","data-testid":"project-manager-search"}),tu("select",{value:A,onChange:(E)=>{j(E.target.value),J(_,E.target.value)},"data-testid":"project-manager-status-filter"},tu("option",{value:"all"},"全部"),tu("option",{value:"active"},"进行中"),tu("option",{value:"completed"},"已完成"),tu("option",{value:"unpaid"},"未全款")),tu("button",{type:"button",className:"ghost-btn",onClick:()=>J(_,A)},"筛选"))},tu(xY,{projects:z,activeId:y.id,onSelect:(E)=>t(CY(E)),onRaw:l})),tu(I9,{title:y.id?"编辑项目":"新建项目",eyebrow:"PostgreSQL Write Path",loading:n.saving||n.importing},tu("form",{className:"stack-form project-manager-form",onSubmit:Q,"data-testid":"project-manager-form"},y.id?tu("label",null,"项目 ID",tu("input",{value:y.id,disabled:!0})):null,tu("label",null,"序号",tu("input",{type:"number",value:y.sequenceNo,onChange:(E)=>t((D)=>({...D,sequenceNo:E.target.value}))})),tu("label",null,"合同号",tu("input",{value:y.contractNo,onChange:(E)=>t((D)=>({...D,contractNo:E.target.value})),required:!0})),tu("label",null,"项目名称",tu("input",{value:y.name,onChange:(E)=>t((D)=>({...D,name:E.target.value})),required:!0})),tu("label",null,"当前状况",tu("textarea",{value:y.currentStatus,onChange:(E)=>t((D)=>({...D,currentStatus:E.target.value}))})),tu("label",null,"待完成",tu("textarea",{value:y.pending,onChange:(E)=>t((D)=>({...D,pending:E.target.value}))})),tu("label",null,"付款情况",tu("input",{value:y.paymentStatus,onChange:(E)=>t((D)=>({...D,paymentStatus:E.target.value})),placeholder:"例如 1 / 0.5 / 50%"})),tu("label",null,"其它",tu("input",{value:y.notes,onChange:(E)=>t((D)=>({...D,notes:E.target.value}))})),tu("div",{className:"inline-actions"},tu("button",{type:"submit",className:"primary-btn",disabled:n.saving,"data-testid":"project-manager-save-button"},n.saving?"保存中":y.id?"保存修改":"创建项目"),tu("button",{type:"button",className:"ghost-btn",onClick:()=>t({...k9})},"清空"),y.id?tu("button",{type:"button",className:"danger-btn",disabled:n.saving,onClick:w,"data-testid":"project-manager-delete-button"},"删除"):null)),tu("div",{className:"project-manager-import"},tu("p",{className:"muted paragraph"},"浏览器只访问 UniDesk frontend;后端通过同源用户服务代理写入主 PostgreSQL,不暴露 4233 公网端口。"),tu("label",{className:"file-import"},n.importing?"导入中...":"导入 Excel",tu("input",{type:"file",accept:".xlsx",onChange:L,disabled:n.importing,"data-testid":"project-manager-import-input"}))))))}var D6=Pu(Jl(),1);var cu=D6.default.createElement,{useEffect:hY}=D6.default,df=D6.default.useState;function bY({status:u,children:l}){let f=String(u||"unknown").toLowerCase();return cu("span",{className:`status-badge ${f}`},l||u||"unknown")}function B6({label:u,value:l,hint:f,tone:r}){return cu("article",{className:`metric-card ${r||""}`},cu("div",{className:"metric-label"},u),cu("div",{className:"metric-value"},l),cu("div",{className:"metric-hint"},f))}function s9({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){return cu("section",{className:`panel ${n||""}`},cu("div",{className:"panel-head"},cu("div",null,l?cu("p",{className:"panel-eyebrow"},l):null,cu(nl,{title:u,loading:i})),f?cu("div",{className:"panel-actions"},f):null),cu("div",{className:"panel-body"},r))}function kw({title:u,data:l,onOpen:f,testId:r}){return cu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>f(u,l)},"查看原始JSON")}function V6({title:u,text:l}){return cu("div",{className:"empty-state"},cu("strong",null,u),cu("span",null,l))}function vY(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function kY(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function IY(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function gw(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function gY(u){if(!Number.isFinite(u))return"--";return`${u.toFixed(1)}%`}function qy(u,l){return`${u}/microservices/todo-note/proxy${l}`}function sw(u){return u.reduce((l,f)=>{let r=sw(Array.isArray(f.children)?f.children:[]),n=Boolean(f.completed);return{total:l.total+1+r.total,completed:l.completed+(n?1:0)+r.completed,active:l.active+(n?0:1)+r.active}},{total:0,completed:0,active:0})}function o9(u,l){let f=l==="all"||(l==="completed"?Boolean(u.completed):!u.completed),r=Array.isArray(u.children)?u.children:[];return f||r.some((n)=>o9(n,l))}function Iw(u){return Array.isArray(u?.instances)?u.instances:[]}function a9(u,l){for(let f of u){if(f?.id===l)return Array.isArray(f.children)?f.children:[];let r=a9(Array.isArray(f?.children)?f.children:[],l);if(r.length>0)return r}return[]}function aw({microservices:u,onRaw:l,apiBaseUrl:f="/api"}){let r=u.find((s)=>s.id==="todo-note")||null,[n,i]=df(null),[y,t]=df(null),[_,c]=df(""),[A,j]=df(null),[F,J]=df("all"),[Q,w]=df(13),[L,U]=df(""),[N,q]=df(""),[W,z]=df(""),[Z,H]=df(""),[E,D]=df(""),[h,V]=df(!1),[S,p]=df(""),[O,m]=df(null),X=Iw(y),v=sw(Array.isArray(A?.todos)?A.todos:[]),T=r?vY(r):{},Y=r?IY(r):{},k=r?kY(r):{};async function I(s=_){let[Nu,Eu]=await Promise.all([Tu(`${f}/microservices/todo-note/health`),Tu(qy(f,"/api/instances"))]);i(Nu),t(Eu);let Hu=Iw(Eu),vu=Hu.some((ul)=>ul.id===s)?s:Hu[0]?.id||"";return c(vu),vu}async function b(s=_){if(!s){j(null);return}let Nu=await Tu(qy(f,`/api/instances/${encodeURIComponent(s)}`));j(Nu)}async function o(s=_){if(!r)return;V(!0),p("");try{let Nu=await I(s);await b(Nu),m(new Date)}catch(Nu){p(Ou(Nu,"Todo Note 加载失败"))}finally{V(!1)}}async function g(s){if(!_)return null;p("");try{let Nu=await Tu(qy(f,`/api/instances/${encodeURIComponent(_)}/actions`),{method:"POST",body:JSON.stringify({action:s})});return j(Nu),await I(_),Nu}catch(Nu){return p(Ou(Nu,"Todo 操作失败")),null}}async function x(s){s.preventDefault();let Nu=L.trim();if(!Nu)return;V(!0),p("");try{let Eu=await Tu(qy(f,"/api/instances"),{method:"POST",body:JSON.stringify({name:Nu})});U(""),await o(Eu.id)}catch(Eu){p(Ou(Eu,"创建清单失败"))}finally{V(!1)}}async function lu(s){if(!window.confirm("确认删除这个 Todo Note 清单?"))return;V(!0),p("");try{await Tu(qy(f,`/api/instances/${encodeURIComponent(s)}`),{method:"DELETE"}),await o(_===s?"":_)}catch(Nu){p(Ou(Nu,"删除清单失败"))}finally{V(!1)}}async function _u(s){s.preventDefault();let Nu=N.trim();if(!Nu)return;q(""),await g({type:"addTodo",title:Nu})}async function $u(s){if(!_)return;p("");try{let Nu=await Tu(qy(f,`/api/instances/${encodeURIComponent(_)}/${s}`),{method:"POST",body:JSON.stringify({})});j(Nu),await I(_)}catch(Nu){p(Ou(Nu,`${s} 失败`))}}function ju(s){z(s.id),H(String(s.title||""))}async function zu(s){let Nu=Z.trim();if(z(""),H(""),Nu)await g({type:"updateTodoTitle",todoId:s,title:Nu})}async function Wu(s){let Eu=window.prompt("新增子任务标题")?.trim();if(!Eu)return;let Hu=a9(Array.isArray(A?.todos)?A.todos:[],s),vu=new Set(Hu.map((Uf)=>Uf.id)),ul=await g({type:"addTodo",title:Eu,parentId:s,targetIndex:0});if(!ul)return;let mu=a9(Array.isArray(ul?.todos)?ul.todos:[],s),Fl=mu.find((Uf)=>!vu.has(Uf.id));if(Fl&&mu[0]?.id!==Fl.id)await g({type:"moveTodo",todoId:Fl.id,targetParentId:s,targetIndex:0})}async function P(s,Nu){if(!E)return;let Eu={type:"moveTodo",todoId:E,targetIndex:Nu};if(s)Eu.targetParentId=s;D(""),await g(Eu)}if(hY(()=>{o()},[r?.id,r?.runtime?.providerStatus]),!r)return cu(V6,{title:"Todo Note 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=todo-note"});let e=X.find((s)=>s.id===_)||null,uu=Array.isArray(A?.todos)?A.todos:[],Ku=uu.map((s,Nu)=>({todo:s,index:Nu})).filter((s)=>o9(s.todo,F));return cu("div",{className:"todo-note-page","data-testid":"todo-note-page"},cu(s9,{title:"Todo Note 工作台",eyebrow:"Main Server 用户服务",loading:h,actions:cu("div",{className:"panel-actions"},cu("button",{type:"button",className:"ghost-btn",disabled:h,onClick:()=>o(_),"data-testid":"todo-note-refresh-button"},h?"刷新中":"刷新"),cu(kw,{title:"Todo Note 用户服务",data:r,onOpen:l,testId:"raw-todo-note-service"}))},cu("div",{className:"todo-note-hero"},cu("div",null,cu("div",{className:"node-version-line"},cu(bY,{status:T.providerStatus==="online"?"online":"warn"},T.providerStatus||"unknown"),cu("span",null,r.providerId),cu("span",null,k.public?"公网暴露":"仅 UniDesk frontend 代理访问"),cu("span",null,n?.ok?"Health OK":"Health --")),cu("p",{className:"muted paragraph"},r.description)),cu("div",{className:"microservice-ref-card"},cu("span",null,"Repo"),cu("strong",null,Y.url||"--"),cu("code",null,Y.commitId||"--")),cu("div",{className:"microservice-ref-card"},cu("span",null,"Main Server Docker"),cu("strong",null,`${k.nodeBindHost||"--"}:${k.nodePort||"--"}`),cu("code",null,`${Y.composeService||"--"} / ${Y.containerName||"--"}`))),cu(il,{error:S,wide:!0})),cu("div",{className:"todo-note-layout"},cu(s9,{title:"清单",eyebrow:`${X.length} Instances`,className:"todo-list-panel",loading:h},cu("form",{className:"todo-create-list",onSubmit:x},cu("input",{placeholder:"新清单名称",value:L,onChange:(s)=>U(s.target.value),"aria-label":"新清单名称"}),cu("button",{type:"submit",className:"ghost-btn",disabled:h||!L.trim()},"创建")),X.length===0?cu(V6,{title:"暂无清单",text:"迁移或创建清单后会出现在这里"}):cu("div",{className:"todo-instance-list"},X.map((s)=>cu("button",{key:s.id,type:"button",className:`todo-instance-row ${_===s.id?"active":""}`,onClick:()=>{c(s.id),b(s.id)},"data-testid":`todo-instance-${gw(s.id)}`},cu("strong",null,s.name),cu("span",null,`${s.completedCount??0}/${s.todoCount??0} 完成`),cu("code",null,s.id))))),cu("div",{className:"todo-main-stack"},cu(s9,{title:e?.name||"待选择清单",eyebrow:O?`Updated ${tl(O)}`:"Todo Tree",loading:h,actions:A?cu("div",{className:"panel-actions"},cu("button",{type:"button",className:"ghost-btn",onClick:()=>g({type:"renameInstance",name:window.prompt("清单新名称",A.name)||A.name})},"重命名"),cu("button",{type:"button",className:"ghost-btn danger",onClick:()=>lu(_)},"删除清单"),cu(kw,{title:`Todo Instance ${_}`,data:A,onOpen:l,testId:"raw-todo-instance"})):null},!A?cu(V6,{title:"未选择清单",text:"左侧选择一个 Todo Note 清单"}):cu("div",{className:"todo-workbench",style:{"--todo-font-size":`${Q}px`}},cu("div",{className:"todo-toolbar"},cu("form",{className:"todo-add-form",onSubmit:_u},cu("input",{placeholder:"新增根任务",value:N,onChange:(s)=>q(s.target.value),"aria-label":"新增根任务"}),cu("button",{type:"submit",className:"ghost-btn",disabled:!N.trim()},"新增")),cu("div",{className:"todo-filter-strip"},["all","active","completed"].map((s)=>cu("button",{key:s,type:"button",className:`todo-filter ${F===s?"active":""}`,onClick:()=>J(s)},s==="all"?"全部":s==="active"?"未完成":"已完成"))),cu("div",{className:"todo-toolbar-actions"},cu("button",{type:"button",className:"ghost-btn",onClick:()=>g({type:"setAllTodosExpanded",expanded:!0})},"全部展开"),cu("button",{type:"button",className:"ghost-btn",onClick:()=>g({type:"setAllTodosExpanded",expanded:!1})},"全部收起"),cu("button",{type:"button",className:"ghost-btn",onClick:()=>$u("undo")},"撤销"),cu("button",{type:"button",className:"ghost-btn",onClick:()=>$u("redo")},"重做"),cu("label",{className:"todo-font-control"},"字号",cu("input",{type:"range",min:11,max:18,value:Q,onChange:(s)=>w(Number(s.target.value))})))),cu("div",{className:"todo-stats-grid"},cu(B6,{label:"总任务",value:v.total,hint:`${X.length} lists`}),cu(B6,{label:"已完成",value:v.completed,hint:`${gY(v.total?v.completed/v.total*100:0)}`,tone:"ok"}),cu(B6,{label:"未完成",value:v.active,hint:F==="active"?"当前筛选":"active tasks",tone:v.active>0?"warn":"ok"}),cu(B6,{label:"历史指针",value:A.historyPointer??0,hint:"undo / redo"})),cu("div",{className:"todo-root-drop",onDragOver:(s)=>s.preventDefault(),onDrop:(s)=>{s.preventDefault(),P(null,uu.length)}},"拖到这里可移为根任务末尾"),cu("div",{className:"todo-tree","data-testid":"todo-note-tree"},Ku.length===0?cu(V6,{title:"没有匹配任务",text:"调整筛选或新增任务"}):Ku.map(({todo:s,index:Nu})=>cu(ow,{key:s.id,todo:s,depth:0,parentId:null,index:Nu,siblingCount:uu.length,filter:F,editingId:W,editingTitle:Z,setEditingTitle:H,beginEdit:ju,saveEdit:zu,applyTodoAction:g,addChild:Wu,dragTodoId:E,setDragTodoId:D,dropTodo:P}))))))))}function ow(u){let{todo:l,depth:f,parentId:r,index:n,siblingCount:i,filter:y,editingId:t,editingTitle:_,setEditingTitle:c,beginEdit:A,saveEdit:j,applyTodoAction:F,addChild:J,dragTodoId:Q,setDragTodoId:w,dropTodo:L}=u,U=Array.isArray(l.children)?l.children:[],N=U.map((z,Z)=>({child:z,childIndex:Z})).filter((z)=>o9(z.child,y)),q=t===l.id,W=r||null;return cu("div",{className:"todo-row-wrap"},cu("article",{className:`todo-row ${l.completed?"completed":""} ${Q===l.id?"dragging":""}`,style:{"--todo-depth":f},draggable:!0,onDragStart:(z)=>{w(l.id),z.dataTransfer.effectAllowed="move"},onDragOver:(z)=>z.preventDefault(),onDrop:(z)=>{z.preventDefault(),L(l.id,U.length)},"data-testid":`todo-row-${gw(l.id)}`},cu("button",{type:"button",className:"todo-expand",disabled:U.length===0,onClick:()=>F({type:"toggleTodoExpanded",todoId:l.id})},U.length===0?"·":l.expanded?"▾":"▸"),cu("input",{type:"checkbox",checked:Boolean(l.completed),onChange:()=>F({type:"toggleTodoCompleted",todoId:l.id}),"aria-label":`完成 ${l.title}`}),cu("div",{className:"todo-title-cell",onDoubleClick:()=>A(l)},q?cu("div",{className:"todo-edit-inline"},cu("input",{value:_,autoFocus:!0,onChange:(z)=>c(z.target.value),onKeyDown:(z)=>{if(z.key==="Enter")j(l.id);if(z.key==="Escape")A({id:"",title:""})}}),cu("button",{type:"button",className:"ghost-btn",onClick:()=>j(l.id)},"保存")):cu("strong",null,l.title||"Untitled"),cu("div",{className:"todo-meta-line"},cu("span",null,`子项 ${U.length}`),cu("span",null,`更新 ${qu(l.updatedAt)}`),l.reminderAt?cu("span",{className:"todo-reminder"},`提醒 ${qu(l.reminderAt)}`):cu("span",null,"无提醒"))),cu("input",{className:"todo-reminder-input",type:"datetime-local",value:r8(l.reminderAt),onChange:(z)=>F({type:"setTodoReminder",todoId:l.id,reminderAt:h7(z.target.value)})}),cu("div",{className:"todo-row-actions"},cu("button",{type:"button",className:"ghost-btn",onClick:()=>A(l)},"编辑"),cu("button",{type:"button",className:"ghost-btn",onClick:()=>J(l.id)},"子项"),cu("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:l.id,...W?{targetParentId:W}:{},targetIndex:n-1})},"上移"),cu("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:l.id,...W?{targetParentId:W}:{},targetIndex:0})},"置顶"),cu("button",{type:"button",className:"ghost-btn",disabled:n>=i-1,onClick:()=>F({type:"moveTodo",todoId:l.id,...W?{targetParentId:W}:{},targetIndex:n+1})},"下移"),cu("button",{type:"button",className:"ghost-btn",disabled:!r,onClick:()=>F({type:"moveTodo",todoId:l.id,targetIndex:9999})},"提升"),cu("button",{type:"button",className:"ghost-btn danger",onClick:()=>F({type:"deleteTodo",todoId:l.id})},"删除"))),l.expanded&&N.length>0?cu("div",{className:"todo-children"},N.map(({child:z,childIndex:Z})=>cu(ow,{key:z.id,todo:z,depth:f+1,parentId:l.id,index:Z,siblingCount:U.length,filter:y,editingId:t,editingTitle:_,setEditingTitle:c,beginEdit:A,saveEdit:j,applyTodoAction:F,addChild:J,dragTodoId:Q,setDragTodoId:w,dropTodo:L}))):null)}var dw=Pu(Jl(),1),kn=dw.default.createElement;function ew({title:u,items:l,actions:f,className:r,testId:n}){let i=Array.isArray(l)?l:[];return kn("section",{className:`top-status-bar ${r||""}`,"data-testid":n},kn("div",{className:"top-status-main"},u?kn("strong",{className:"top-status-title"},u):null,kn("div",{className:"top-status-chips"},i.map((y,t)=>kn("span",{key:y?.key||`${y?.label||"status"}-${t}`,className:`top-status-chip ${y?.tone||""}`,"data-testid":y?.testId},y?.label?kn("b",null,y.label):null,kn("span",null,y?.value??"--"))))),f?kn("div",{className:"top-status-actions"},f):null)}var M_=Pu(Jl(),1);var Qu=M_.default.createElement,{useEffect:sY,useMemo:aY}=M_.default,oY=M_.default.useState;function uL({status:u,children:l,title:f}){let r=String(u||"unknown").toLowerCase();return Qu("span",{className:`status-badge ${r}`,title:f},l||u||"unknown")}function X6({label:u,value:l,hint:f,tone:r}){return Qu("article",{className:`metric-card ${r||""}`},Qu("div",{className:"metric-label"},u),Qu("div",{className:"metric-value"},l),Qu("div",{className:"metric-hint"},f))}function d9({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){return Qu("section",{className:`panel ${n||""}`},Qu("div",{className:"panel-head"},Qu("div",null,l?Qu("p",{className:"panel-eyebrow"},l):null,Qu(nl,{title:u,loading:i})),f?Qu("div",{className:"panel-actions"},f):null),Qu("div",{className:"panel-body"},r))}function lL({title:u,data:l,onOpen:f,testId:r}){return Qu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>f?.(u,l)},"查看原始JSON")}function e9({title:u,text:l}){return Qu("div",{className:"empty-state"},Qu("strong",null,u),Qu("span",null,l))}function Wy(u){return Array.isArray(u)?u:[]}function u7(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function dY(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function eY(u,l){return`${u}/microservices/v3sctl-adapter/proxy${l}`}function up(u){return u.find((l)=>String(l?.id||"")==="v3sctl-adapter")||null}function lp(u){if(u?.healthy===!0)return"online";if(String(u?.role||"")==="standby")return"warn";return"failed"}function fp(u){return u?.healthy===!0?"online":"failed"}function rp(u){if(u===!0)return"YES";if(u===!1)return"NO";return"--"}function np(u){return Array.from(new Set(u.flatMap((l)=>Wy(l?.expectedNodeIds).map((f)=>String(f))))).filter(Boolean).sort()}function ip(u){let l=u.find((f)=>f?.id==="code-queue")||u[0];return String(l?.activeInstanceId||"--")}function yp(u){return Qu("article",{key:u?.id||u?.nodeId,className:"v3s-instance-card"},Qu("div",{className:"node-card-head"},Qu("strong",null,u?.nodeId||u?.id||"--"),Qu(uL,{status:lp(u)},u?.healthy?"HEALTHY":"DEGRADED")),Qu("div",{className:"v3s-instance-role"},Qu("span",null,String(u?.role||"worker").toUpperCase()),Qu("code",null,u?.id||"--")),Qu("dl",{className:"v3s-kv"},Qu("dt",null,"Base URL"),Qu("dd",null,Qu("code",null,u?.baseUrl||"--")),Qu("dt",null,"Proxy"),Qu("dd",null,u?.proxyMode||"--"),Qu("dt",null,"Health"),Qu("dd",null,`${u?.upstreamStatus??"--"} / ${u?.status||"unknown"}`),Qu("dt",null,"Checked"),Qu("dd",null,qu(u?.checkedAt))))}function tp(u,l){let f=Wy(u?.instances),r=u7(u?.active);return Qu(d9,{key:u?.id||"service",title:u?.id||"managed-service",eyebrow:`${u?.namespace||"unidesk"} / v3s managed service`,className:"v3s-service-panel",actions:Qu(lL,{title:`v3s service ${u?.id||""}`,data:u,onOpen:l,testId:`raw-v3s-service-${u?.id||"unknown"}`})},Qu("div",{className:"v3s-service-summary"},Qu("div",null,Qu("span",null,"状态"),Qu(uL,{status:fp(u)},u?.status||"unknown")),Qu("div",null,Qu("span",null,"Active"),Qu("strong",null,u?.activeInstanceId||"--")),Qu("div",null,Qu("span",null,"Single Writer"),Qu("strong",null,rp(u?.singleWriter))),Qu("div",null,Qu("span",null,"Active Health"),Qu("strong",null,r?.upstreamStatus??"--"))),f.length===0?Qu(e9,{title:"暂无 v3s 实例",text:"adapter 没有返回该服务的 endpoint 列表"}):Qu("div",{className:"v3s-instance-grid"},f.map(yp)))}function fL({microservices:u,onRaw:l,apiBaseUrl:f,onNavigate:r}){let n=up(Array.isArray(u)?u:[]),i=dY(n),[y,t]=oY({loading:!1,error:"",data:null,refreshedAt:null});async function _(){t((N)=>({...N,loading:!0,error:""}));try{let N=await Tu(eY(f,"/api/control-plane"));t({loading:!1,error:"",data:N,refreshedAt:new Date})}catch(N){t((q)=>({...q,loading:!1,error:Ou(N,"加载 v3s 控制平面失败")}))}}sY(()=>{_()},[f]);let c=aY(()=>Wy(y.data?.services),[y.data]),A=np(c),j=c.filter((N)=>N?.healthy===!0).length,F=c.reduce((N,q)=>N+Wy(q?.instances).length,0),J=c.reduce((N,q)=>N+Wy(q?.instances).filter((W)=>W?.healthy===!0).length,0),Q=ip(c),w=u7(y.data?.kubectl),L=u7(y.data?.kubeApiProxy),U=Wy(y.data?.manifestPaths).map((N)=>String(N));if(!n)return Qu(e9,{title:"v3sctl-adapter 未登记",text:"请在 config.json 的 microservices 中登记 id=v3sctl-adapter,并通过该微服务连接 v3s 控制平面。"});return Qu("div",{className:"v3s-page","data-testid":"v3sctl-page"},Qu(d9,{title:"V3S Control Plane",eyebrow:"Managed by v3sctl-adapter",className:"v3s-hero-panel",loading:y.loading,actions:Qu(M_.default.Fragment,null,Qu("button",{type:"button",className:"ghost-btn",onClick:_,disabled:y.loading,"data-testid":"v3s-refresh-button"},y.loading?"刷新中":"刷新"),r?Qu("button",{type:"button",className:"ghost-btn",onClick:()=>r("apps","code-queue"),"data-testid":"v3s-open-code-queue"},"打开 Code Queue"):null,Qu(lL,{title:"v3sctl-adapter microservice",data:n,onOpen:l,testId:"raw-v3s-adapter"}))},Qu("div",{className:"v3s-hero"},Qu("div",{className:"v3s-orb","aria-hidden":"true"},Qu("span",null,"v3s")),Qu("div",{className:"v3s-hero-copy"},Qu("p",{className:"eyebrow"},"D601 control plane / D518 managed node"),Qu("h2",null,"UniDesk 只管理 adapter;业务微服务交给 v3s 标准服务路由"),Qu("p",{className:"muted paragraph"},"Code Queue 的前端/API 请求进入 v3sctl-adapter,再由 adapter 转发到 v3s active service。provider-gateway 只用于维护 adapter 和节点诊断,不再直接管理 Code Queue 容器。"),Qu("div",{className:"v3s-route-strip"},Qu("span",null,"NO FALLBACK"),Qu("code",null,y.data?.runtimePath||"frontend -> backend-core -> v3sctl-adapter")))),Qu("div",{className:"metric-grid"},Qu(X6,{label:"控制面",value:y.data?.clusterId||"D601",hint:`adapter ${i.providerStatus||"unknown"}`,tone:i.providerStatus==="online"?"ok":"warn"}),Qu(X6,{label:"代管服务",value:c.length,hint:`${j}/${c.length||0} healthy`,tone:j===c.length&&c.length>0?"ok":"warn"}),Qu(X6,{label:"节点",value:A.join(" / ")||"--",hint:"expected v3s nodes"}),Qu(X6,{label:"实例",value:`${J}/${F}`,hint:`active ${Q}`,tone:J===F&&F>0?"ok":"warn"})),Qu("div",{className:"v3s-control-plane-grid"},Qu("article",{className:"v3s-control-plane-card"},Qu("span",null,"service proxy"),Qu("strong",null,L.configured===!0?"K8S API PROXY":"PROXY DEGRADED"),Qu("p",null,L.configured===!0?`${L.mode||"kubernetes-api-service-proxy"} via ${L.connectHost||"--"}`:"adapter 必须通过 k8s API service proxy 访问业务服务,不回退到业务容器直连。")),Qu("article",{className:"v3s-control-plane-card"},Qu("span",null,"manifests"),Qu("strong",null,U.length||"--"),Qu("p",null,U.join(" / ")||"未配置 manifest")),Qu("article",{className:"v3s-control-plane-card"},Qu("span",null,"cluster snapshot"),Qu("strong",null,w.enabled===!0?w.ok===!0?"KUBECTL OK":"KUBECTL DEGRADED":"API ONLY"),Qu("p",null,w.enabled===!0?`nodes ${w.nodeCount??"--"}`:"控制面页面以 adapter 返回的 k8s service proxy 状态为准;kubectl 只作为可选快照。"))),y.error?Qu(il,{error:y.error}):null,y.refreshedAt?Qu("p",{className:"muted paragraph"},`最近刷新 ${tl(y.refreshedAt)}`):null),c.length===0?Qu(d9,{title:"代管服务",eyebrow:"v3s services",loading:y.loading},Qu(e9,{title:"暂无 v3s 服务",text:"等待 v3sctl-adapter 返回 /api/services;Code Queue 切换后这里应显示 D601 和 D518 两个实例。"})):c.map((N)=>tp(N,l)))}var R_=Pu(Jl(),1);var hl=R_.default.createElement;function rL({onClose:u}){let{notifications:l,removeNotification:f,clearNotifications:r}=Xf(),n=R_.default.useRef(null);if(R_.default.useEffect(()=>{let i=(y)=>{if(n.current&&!n.current.contains(y.target))u()};return document.addEventListener("mousedown",i),()=>document.removeEventListener("mousedown",i)},[u]),l.length===0)return hl("div",{className:"notification-popup",ref:n},hl("div",{className:"notification-popup-header"},hl("span",null,"通知"),hl("button",{className:"notification-popup-close",onClick:u},"×")),hl("div",{className:"notification-popup-empty"},"暂无通知"));return hl("div",{className:"notification-popup",ref:n},hl("div",{className:"notification-popup-header"},hl("span",null,`通知 (${l.length})`),hl("div",{className:"notification-popup-actions"},hl("button",{className:"notification-popup-clear",onClick:r},"清空"),hl("button",{className:"notification-popup-close",onClick:u},"×"))),hl("div",{className:"notification-popup-list"},l.slice().reverse().map((i)=>hl("div",{key:i.id,className:`notification-item ${i.type}`},hl("span",{className:"notification-item-icon"},i.type==="success"?"✓":"×"),hl("span",{className:"notification-item-message"},i.message),hl("button",{className:"notification-item-dismiss",onClick:()=>f(i.id)},"×")))))}function nL({notification:u}){let{removeNotification:l}=Xf();return R_.default.useEffect(()=>{let f=setTimeout(()=>{l(u.id)},3000);return()=>clearTimeout(f)},[u.id,l]),hl("div",{className:`notification-banner ${u.type}`,role:"alert"},hl("span",{className:"notification-banner-icon"},u.type==="success"?"✓":"×"),hl("span",{className:"notification-banner-message"},u.message),hl("button",{className:"notification-banner-dismiss",onClick:()=>l(u.id)},"×"))}function QL(u,l){let f=document.getElementById("root")?.getAttribute(u);if(!f)return l;try{let r=JSON.parse(f);return typeof r==="object"&&r!==null&&!Array.isArray(r)?r:l}catch{return l}}var gu=QL("data-config",{apiBaseUrl:"/api",authUsername:"admin"}),_p=QL("data-codex-overview",null),$=gn.default.createElement,{useEffect:J0,useMemo:b_}=gn.default,bu=gn.default.useState,n7=gn.default.createContext(!1),Dr=oQ(ic),$p={id:"code-queue",name:"Code Queue",providerId:"D601",description:"Code Queue",repository:{containerName:"v3s:code-queue"},backend:{nodeBaseUrl:"v3s://code-queue",nodeBindHost:"v3s://unidesk/code-queue",nodePort:4222,proxyMode:"v3sctl-adapter-http",public:!1},deployment:{mode:"v3sctl-managed",adapterServiceId:"v3sctl-adapter",v3sServiceId:"code-queue"},runtime:{orchestrator:"v3sctl",providerStatus:"loading",providerName:"D601"}};function iL(){return typeof document>"u"||document.visibilityState!=="hidden"}function cp(u,l){if(u==="ops"&&l==="status")return 5000;if(u==="nodes"&&l==="monitor")return 5000;if(u==="tasks"&&(l==="dispatch"||l==="scheduled"||l==="pending"))return 5000;if(u==="nodes"||u==="ops")return 1e4;if(u==="apps")return 15000;if(u==="tasks")return 15000;return 30000}async function Ap(u){if(!u?._summaryOnly||!u?.id)return u;return(await Tu(`${gu.apiBaseUrl}/tasks/${encodeURIComponent(String(u.id))}`))?.task||u}function v_(u){return u?._summaryOnly?{...u,_loadRaw:()=>Ap(u)}:u}function b0(u){if(!Number.isFinite(u))return"--";let l=Math.max(0,u);if(l===0)return"0s";if(l<0.01)return"<0.01s";if(l<0.1)return`${l.toFixed(2)}s`;if(l<1)return`${l.toFixed(1)}s`;if(l<10&&!Number.isInteger(l))return`${l.toFixed(1)}s`;if(l<60)return`${Math.round(l)}s`;let f=Math.floor(l);if(f<3600)return`${Math.floor(f/60)}m ${f%60}s`;return`${Math.floor(f/3600)}h ${Math.floor(f%3600/60)}m`}function Nr(u){let l=Number(u);if(!Number.isFinite(l))return"--";if(l<1)return`${Math.max(0,l).toFixed(1)}ms`;if(l<10)return`${l.toFixed(1)}ms`;if(l<1000)return`${Math.round(l)}ms`;return b0(l/1000)}function Tf(u){let l=Number(u);if(!Number.isFinite(l)||l<=0)return"--";let f=["B","KB","MB","GB","TB"],r=l,n=0;while(r>=1024&&n0)return f[r]}return"任务失败但 provider 未返回明确原因"}function hi(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 Fp(u,l){let f=u.replace(/[-_\s]/g,"").toLowerCase(),r=f==="ts"||f.endsWith("at")||f.endsWith("timestamp")||f.endsWith("heartbeat");if((typeof l==="string"||typeof l==="number")&&r){let n=qu(l);if(n!=="--")return n}if(u==="bodyText"&&typeof l==="string")return`${/^\s*[{[]/.test(l)?"JSON":"HTTP"} body ${l.length} chars`;return hi(l)}function WL(u){if(!u||typeof u!=="object"||Array.isArray(u))return[];return Object.entries(u)}function ef(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function y7(u,l){return u&&typeof u==="object"&&!Array.isArray(u)?u[l]:void 0}function Y6(u,l,f="未知"){let r=y7(u?.labels,l);return typeof r==="string"&&r.length>0?r:f}function wL(u){return Y6(u,"providerGatewayVersion")}function h_(u){return Y6(u,"providerGatewayUpgradePolicy")}function yL(u){return Y6(u,"providerGatewayStartedAt","")}function LL(u){let l=y7(u?.labels,"unideskCapabilities");if(typeof l==="string")return l.split(",").map((f)=>f.trim()).filter(Boolean);return Array.isArray(l)?l.filter((f)=>typeof f==="string"):[]}function KL(u,l){return LL(u).includes(l)}function tL(u,l){let f=y7(u?.labels,l);return f===!0||f==="true"||f==="1"}function Up(u){if(!KL(u,"host.ssh"))return{tone:"fail",label:"不可用",detail:"未声明 host.ssh"};if(!tL(u,"hostSshConfigured"))return{tone:"warn",label:"未配置",detail:"缺少 SSH 环境变量"};if(!tL(u,"hostSshKeyPresent"))return{tone:"warn",label:"缺 key",detail:"私钥未挂载"};return{tone:"ok",label:"可用",detail:Y6(u,"hostSshTarget","host.ssh ready")}}function Jp(u){if(!KL(u,"provider.upgrade"))return{tone:"fail",label:"不可用",detail:"未声明 provider.upgrade"};let l=h_(u);if(l!=="always-enabled")return{tone:"warn",label:"待确认",detail:`策略 ${l}`};return{tone:"ok",label:"可用",detail:"always-enabled"}}function t7(u){let l=typeof u==="string"&&u.length>0?u:"未知";if(l==="未知")return"版本未知";return l.startsWith("v")?l:`v${l}`}function GL(u){return u?.payload&&typeof u.payload==="object"&&!Array.isArray(u.payload)?u.payload:{}}function p6(u){return u?.result&&typeof u.result==="object"&&!Array.isArray(u.result)?u.result:{}}function S6(u){let l=GL(u),f=p6(u);return(l.mode??f.mode)==="schedule"?"schedule":"plan"}function Qp(u){let l=GL(u).source;return typeof l==="string"&&l.length>0?l:"unknown"}function Np(u){let l=p6(u),f=l.plan&&typeof l.plan==="object"&&!Array.isArray(l.plan)?l.plan:{},r=l.policy??f.policy;return typeof r==="string"&&r.length>0?r:"--"}function zL(u){let l=p6(u),f=l.plan&&typeof l.plan==="object"&&!Array.isArray(l.plan)?l.plan:{},r=l.targetProviderGatewayVersion??l.providerGatewayVersion??f.targetProviderGatewayVersion??f.providerGatewayVersion;return typeof r==="string"&&r.length>0?t7(r):"版本未知"}function TL(u){if(String(u?.status||"").toLowerCase()==="failed")return qL(u);if(Ly(u))return"等待 provider 回传升级终态";let f=p6(u);if(typeof f.updaterContainerId==="string"&&f.updaterContainerId.length>0)return`updater ${f.updaterContainerId.slice(0,18)}`;if(typeof f.message==="string"&&f.message.length>0)return f.message;if(f.plan)return"升级计划已生成";return"无升级结果摘要"}function EL(u,l){return u.filter((f)=>f?.providerId===l&&f?.command==="provider.upgrade").sort((f,r)=>(Q0(r.updatedAt)??0)-(Q0(f.updatedAt)??0))}function qp(u){return u.find((l)=>S6(l)==="schedule")||u[0]||null}function ZL(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function _L(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function Wp(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function wl({status:u,children:l}){let f=String(u||"unknown").toLowerCase();return $("span",{className:`status-badge ${f}`},l||u||"unknown")}function cl({label:u,value:l,hint:f,tone:r,onClick:n,testId:i}){let y=typeof n==="function";return $("article",{className:`metric-card ${r||""} ${y?"clickable":""}`,role:y?"button":void 0,tabIndex:y?0:void 0,"data-testid":i,onClick:n,onKeyDown:y?(t)=>{if(t.key==="Enter"||t.key===" ")t.preventDefault(),n()}:void 0},$("div",{className:"metric-label"},u),$("div",{className:"metric-value"},l),$("div",{className:"metric-hint"},f))}function du({title:u,eyebrow:l,actions:f,children:r,className:n,loading:i}){let y=gn.default.useContext(n7),t=Boolean(i)||y;return $("section",{className:`panel ${n||""}`},$("div",{className:"panel-head"},$("div",null,l?$("p",{className:"panel-eyebrow"},l):null,$(nl,{title:u,loading:t})),f?$("div",{className:"panel-actions"},f):null),$("div",{className:"panel-body"},r))}function bl({title:u,data:l,onOpen:f,testId:r}){let[n,i]=bu(!1),y=l&&typeof l==="object"&&typeof l._loadRaw==="function"?l._loadRaw:null;async function t(){if(!y){f(u,l);return}i(!0);try{f(u,await y())}catch(_){f(u,{ok:!1,error:Ou(_,"读取原始 JSON 失败"),fallback:l})}finally{i(!1)}}return $("button",{type:"button",className:"ghost-btn","data-testid":r,disabled:n,onClick:()=>void t()},n?"读取中":"查看原始JSON")}function wp({raw:u,onClose:l}){if(!u)return null;return $("div",{className:"modal-backdrop",role:"presentation"},$("section",{className:"raw-dialog",role:"dialog","aria-modal":"true","aria-label":u.title},$("div",{className:"raw-dialog-head"},$("h2",null,u.title),$("button",{type:"button",className:"ghost-btn",onClick:l},"关闭")),$("pre",{className:"raw-json","data-testid":"raw-json"},JSON.stringify(u.data,null,2))))}function OL({labels:u,limit:l=8}){let f=WL(u).slice(0,l);if(f.length===0)return $("span",{className:"muted"},"无标签");return $("div",{className:"chip-row"},f.map(([r,n])=>$("span",{key:r,className:"data-chip"},$("b",null,r),$("span",null,hi(n)))))}function wy({node:u}){let l=wL(u);return $("span",{className:`version-chip ${l==="未知"?"unknown":""}`,"data-testid":`gateway-version-${ef(u?.providerId||"unknown")}`},t7(l))}function $L({title:u,state:l,testId:f}){return $("span",{className:`capability-badge ${l.tone}`,title:l.detail,"data-testid":f},$("b",null,u),$("strong",null,l.label),$("small",null,l.detail))}function _7({node:u}){let l=ef(u?.providerId||"unknown");return $("div",{className:"node-availability-strip"},$($L,{title:"SSH 透传",state:Up(u),testId:`ssh-availability-${l}`}),$($L,{title:"远程更新",state:Jp(u),testId:`upgrade-availability-${l}`}))}function sn({data:u,empty:l="无数据"}){if(u===null||u===void 0)return $("span",{className:"muted"},l);if(typeof u!=="object")return $("span",{className:"summary-value"},hi(u));if(Array.isArray(u))return $("span",{className:"summary-value"},`${u.length} 项列表`);let f=Object.entries(u).slice(0,5);if(f.length===0)return $("span",{className:"muted"},l);return $("div",{className:"summary-grid"},f.map(([r,n])=>$("span",{key:r,className:"summary-item"},$("b",null,r),$("span",null,Fp(r,n)))))}function jl({title:u,text:l}){return $("div",{className:"empty-state"},$("strong",null,u),$("span",null,l))}function Lp({onLogin:u}){let[l,f]=bu(gu.authUsername||"admin"),[r,n]=bu(""),[i,y]=bu(""),[t,_]=bu(!1);async function c(A){A.preventDefault(),_(!0),y("");try{let j=await Tu("/login",{method:"POST",body:JSON.stringify({username:l,password:r})});u(j)}catch(j){y(Ou(j,"登录失败"))}finally{_(!1)}}return $("main",{className:"login-screen","data-testid":"login-screen"},$("section",{className:"login-card"},$("div",{className:"login-brand"},$("span",{className:"brand-mark"},"UD"),$("div",null,$("h1",null,"UniDesk"),$("p",null,"Control Plane Login"))),$("form",{className:"login-form",onSubmit:c},$("label",null,"账号",$("input",{name:"username",autoComplete:"username",value:l,onChange:(A)=>f(A.target.value)})),$("label",null,"密码",$("input",{name:"password",type:"password",autoComplete:"current-password",value:r,onChange:(A)=>n(A.target.value)})),$(il,{error:i}),$("button",{type:"submit",disabled:t},t?"登录中":"登录")),$("div",{className:"login-note"},"默认账号由 config.json 注入;公网入口只暴露前端登录面。")))}function Kp({connection:u,lastRefresh:l,onRefresh:f,onLogout:r,session:n,clock:i,activeStatusItems:y=[],onNotificationToggle:t,unreadCount:_=0}){let c=[{key:"core",label:"核心",value:u.text,tone:u.ok?"ok":"fail",testId:"conn-text"},...Array.isArray(y)?y:[],{key:"refresh",label:"刷新",value:l?tl(l):"未刷新"},{key:"clock",label:c$,value:tl(i)},{key:"user",label:"用户",value:n?.user?.username||"--",tone:"user"}];return $("header",{className:"topbar"},$("div",null,$("p",{className:"eyebrow"},"Distributed Work Platform"),$("h1",null,"UniDesk 控制平面")),$(ew,{className:"global-top-status",title:"状态",items:c,actions:[$("button",{key:"notification",type:"button",className:`notification-icon-btn ${_>0?"has-unread":""}`,onClick:t,"aria-label":"通知"},"\uD83D\uDD14",_>0?$("span",{key:"badge",className:"notification-badge"},_>99?"99+":_):null),$("button",{key:"refresh",type:"button",className:"ghost-btn",onClick:f},"刷新"),$("button",{key:"logout",type:"button",className:"ghost-btn danger",onClick:r},"退出")]}))}function Gp(u){return!u.defaultPrevented&&u.button===0&&!u.metaKey&&!u.altKey&&!u.ctrlKey&&!u.shiftKey&&u.currentTarget.target!=="_blank"}function HL({moduleId:u,tabId:l,className:f,active:r=!1,title:n,testId:i,onNavigate:y,children:t}){let _=yc(Dr,u,l);return $("a",{href:_,role:"button",className:f,title:n,"aria-current":r?"page":void 0,"data-testid":i,"data-route":_,onClick:(c)=>{if(!Gp(c))return;c.preventDefault(),y(u,l)}},t)}function zp({activeModule:u,activeTabs:l,onNavigate:f,collapsed:r,onToggle:n}){return $("aside",{className:`rail ${r?"collapsed":""}`,"aria-label":"主模块"},$("div",{className:"brand"},$("span",{className:"brand-mark"},"UD"),$("span",{className:"brand-text"},"UniDesk"),$("button",{type:"button",className:"rail-toggle",onClick:n,"aria-label":r?"展开左侧边栏":"收起左侧边栏","data-testid":"rail-toggle"},r?"»":"«")),ic.map((i)=>{let y=l[i.id]||st[i.id]||i.tabs[0]?.id||"";return $(HL,{key:i.id,moduleId:i.id,tabId:y,className:`module ${u===i.id?"active":""}`,active:u===i.id,title:i.label,onNavigate:f},$("span",{className:"module-code"},i.code),$("span",null,i.label))}))}function Tp({module:u,activeTab:l,onNavigate:f}){return $("nav",{className:"tabs","aria-label":`${u.label} 子功能`},u.tabs.map((r)=>$(HL,{key:r.id,moduleId:u.id,tabId:r.id,className:`tab ${l===r.id?"active":""}`,active:l===r.id,onNavigate:f},r.label)))}function Ep({data:u,onRaw:l,onNavigate:f}){let r=u.overview||{},n=u.nodes.filter((J)=>J.status==="online"),i=u.pendingTasks||u.tasks.filter(Ly),y=r.pendingTaskCount??i.length,t=u.tasks.slice(0,5),_=r.pgdata||{},c=r.microserviceAvailability||{},A=Mu(c.totalCount),j=Mu(c.healthyCount),F=Mu(c.unhealthyCount);return $("div",{className:"page-grid overview-grid","data-testid":"overview-page"},$(du,{title:"核心指标",eyebrow:"Control"},$("div",{className:"metric-grid"},$(cl,{label:"数据库",value:r.dbReady?"READY":"WAIT",hint:"PostgreSQL internal network",tone:r.dbReady?"ok":"warn"}),$(cl,{label:"PGDATA",value:Tf(_.databaseBytes),hint:`${_.volumeName||"unidesk_pgdata_10gb"} / ${_.databasePretty||"--"}`,tone:"ok",testId:"pgdata-usage-card"}),$(cl,{label:"在线节点",value:r.onlineNodeCount??0,hint:`${r.nodeCount??0} registered`,tone:"ok"}),$(cl,{label:"WebSocket",value:r.activeSocketCount??0,hint:"Provider ingress sockets"}),$(cl,{label:"用户服务可用",value:A>0?`${j}/${A}`:"--",hint:A>0?`healthyCount ${j} · unhealthyCount ${F}`:"strict /health probes",tone:A>0&&F===0?"ok":"warn",testId:"microservice-availability-card"}),$(cl,{label:"待处理任务",value:y,hint:y>0?"点击查看具体任务":`timeout ${b0(Math.floor((r.taskPendingTimeoutMs??0)/1000))}`,tone:y>0?"warn":"ok",onClick:()=>f("tasks","pending"),testId:"pending-task-card"}))),$(du,{title:"本机 Provider",eyebrow:"Self Connected"},n.length===0?$(jl,{title:"暂无在线节点",text:"provider-gateway 未完成自接入"}):$("div",{className:"node-card-list"},n.slice(0,4).map((J)=>$(Zp,{key:J.providerId,node:J,onRaw:l})))),$(du,{title:"待处理任务明细",eyebrow:`${y} Pending`,actions:$("button",{type:"button",className:"ghost-btn",onClick:()=>f("tasks","pending"),"data-testid":"pending-task-detail-link"},"进入任务调度")},i.length===0?$(jl,{title:"当前无待处理",text:"queued / dispatched / running 超时后会自动转为 failed,避免总览长期卡住"}):$("div",{className:"compact-list"},i.slice(0,5).map((J)=>$(FL,{key:J.id,task:J,onRaw:l})))),$(du,{title:"最近任务",eyebrow:"Dispatch"},t.length===0?$(jl,{title:"暂无任务",text:"可以在任务调度模块发起 docker.ps 或 echo"}):$("div",{className:"compact-list"},t.map((J)=>$(FL,{key:J.id,task:J,onRaw:l})))))}function Zp({node:u,onRaw:l}){return $("article",{className:"node-card"},$("div",{className:"node-card-head"},$("div",null,$("strong",null,u.name),$("code",null,u.providerId)),$(wl,{status:u.status})),$("div",{className:"node-version-line"},$(wy,{node:u}),$("span",null,`升级策略 ${h_(u)}`)),$(_7,{node:u}),$(OL,{labels:u.labels,limit:6}),$("div",{className:"node-card-foot"},$("span",null,`心跳 ${qu(u.lastHeartbeat)}`),$(bl,{title:`Provider ${u.providerId}`,data:u,onOpen:l,testId:`raw-node-${ef(u.providerId)}`})))}function Op({events:u,onRaw:l}){return $(du,{title:"事件摘要",eyebrow:"Latest 100"},u.length===0?$(jl,{title:"暂无事件",text:"Provider 注册、心跳超时和任务状态会写入事件流"}):$("div",{className:"table-wrap"},$("table",null,$("thead",null,$("tr",null,$("th",null,"ID"),$("th",null,"类型"),$("th",null,"来源"),$("th",null,"摘要"),$("th",null,"时间"),$("th",null,"操作"))),$("tbody",null,u.map((f)=>$("tr",{key:f.id},$("td",null,$("code",null,f.id)),$("td",null,$(wl,{status:f.type},f.type)),$("td",null,$("code",null,f.source)),$("td",null,$(sn,{data:f.payload})),$("td",null,qu(f.createdAt)),$("td",null,$(bl,{title:`Event ${f.id}`,data:f,onOpen:l}))))))))}function Hp({logs:u,onRaw:l}){return $(du,{title:"服务日志",eyebrow:"Core Recent"},u.length===0?$(jl,{title:"暂无日志",text:"backend-core 内存日志会在请求和 provider 事件后出现"}):$("div",{className:"log-list"},u.slice(-80).reverse().map((f,r)=>$("article",{key:r,className:`log-row ${f.level||"info"}`},$("span",null,qu(f.ts)),$("b",null,f.level||"info"),$("strong",null,f.message||"log"),$(sn,{data:f.data,empty:"无附加字段"}),$(bl,{title:`Log ${f.message||r}`,data:f,onOpen:l})))))}function Bp({nodes:u,onRaw:l}){return $(du,{title:"节点清单",eyebrow:`${u.length} Providers`},u.length===0?$(jl,{title:"暂无 Provider 节点",text:"确认 provider-gateway 已连接 provider ingress"}):$("div",{className:"table-wrap"},$("table",{className:"node-list-table"},$("thead",null,$("tr",null,$("th",null,"状态"),$("th",null,"Provider"),$("th",null,"网关版本"),$("th",null,"运维可用性"),$("th",null,"资源标签"),$("th",null,"连接时间"),$("th",null,"最后心跳"),$("th",null,"操作"))),$("tbody",null,u.map((f)=>$("tr",{key:f.providerId},$("td",null,$(wl,{status:f.status})),$("td",null,$("strong",null,f.name),$("code",null,f.providerId)),$("td",null,$("div",{className:"gateway-cell"},$(wy,{node:f}),$("span",null,h_(f)))),$("td",null,$(_7,{node:f})),$("td",null,$(OL,{labels:f.labels,limit:5})),$("td",null,qu(f.connectedAt)),$("td",null,qu(f.lastHeartbeat)),$("td",null,$(bl,{title:`Provider ${f.providerId}`,data:f,onOpen:l,testId:`raw-node-table-${ef(f.providerId)}`}))))))))}function Vp({nodes:u}){let l=b_(()=>{let f=[];for(let r of u)for(let[n,i]of WL(r.labels))f.push({providerId:r.providerId,name:r.name,key:n,value:i});return f},[u]);return $(du,{title:"资源标签",eyebrow:"Structured Labels"},l.length===0?$(jl,{title:"暂无标签",text:"provider-gateway 注册消息会同步资源标签"}):$("div",{className:"label-matrix"},l.map((f)=>$("article",{key:`${f.providerId}-${f.key}`,className:"label-card"},$("span",null,f.key),$("strong",null,hi(f.value)),$("code",null,f.providerId)))))}function Dp({nodes:u}){return $(du,{title:"心跳状态",eyebrow:"Provider Liveness"},u.length===0?$(jl,{title:"无心跳",text:"等待 provider 注册和 heartbeat"}):$("div",{className:"heartbeat-list"},u.map((l)=>$("article",{key:l.providerId,className:"heartbeat-row"},$("span",{className:`pulse ${l.status}`}),$("div",null,$("strong",null,l.name),$("code",null,l.providerId)),$("div",null,$("span",null,"connected"),$("b",null,qu(l.connectedAt))),$("div",null,$("span",null,"last heartbeat"),$("b",null,qu(l.lastHeartbeat)))))))}function Xp({nodes:u,systemStatuses:l,tasks:f,onRaw:r,refresh:n}){let[i,y]=bu(""),t=b_(()=>u.map((w)=>{let L=l.find((U)=>U.providerId===w.providerId);return{...w,systemCurrent:L?.current||null,systemHistory:L?.history||[],systemUpdatedAt:L?.updatedAt||null}}),[u,l]),_=t.find((w)=>w.providerId===i)||t[0]||null;if(J0(()=>{if(!i&&t[0])y(t[0].providerId)},[t.length,i]),!_)return $(jl,{title:"暂无资源监控",text:"等待 provider 上报 CPU、内存和硬盘指标"});let c=_.systemCurrent,A=_.systemHistory||[],j=c?.cpu||{},F=c?.memory||{},J=c?.disk||{},Q=A.length>0?A:c?[{at:c.collectedAt,cpuPercent:Mu(j.percent),memoryPercent:Mu(F.percent),diskPercent:Mu(J.percent)}]:[];return $("div",{className:"monitor-page","data-testid":"node-monitor-page"},$("div",{className:"docker-node-strip"},t.map((w)=>$("button",{key:w.providerId,type:"button",className:`docker-node-tile ${_.providerId===w.providerId?"active":""}`,onClick:()=>y(w.providerId)},$("span",{className:`pulse ${w.status}`}),$("strong",null,w.name),$("code",null,w.providerId),$("span",null,w.systemCurrent?`CPU ${In(w.systemCurrent.cpu?.percent)} / MEM ${In(w.systemCurrent.memory?.percent)}`:"等待指标")))),$("div",{className:"monitor-layout"},$(du,{title:"任务管理器视图",eyebrow:_.name,className:"monitor-main-panel",actions:c?$(bl,{title:`System ${_.providerId}`,data:{current:c,history:A},onOpen:r}):null},!c?$(jl,{title:"系统指标未上报",text:"provider-gateway 会周期性采集 /proc 与 df,并保存历史曲线"}):$("div",null,$("div",{className:"monitor-hero"},$("div",null,$("p",{className:"panel-eyebrow"},"Node Performance"),$("h3",null,_.name),$("div",{className:"docker-meta"},$("span",null,`${j.cores||0} CPU cores`),$("span",null,`load ${Mu(j.load1).toFixed(2)} / ${Mu(j.load5).toFixed(2)} / ${Mu(j.load15).toFixed(2)}`),$("span",null,`memory actual ${Tf(F.usedBytes)} / ${Tf(F.totalBytes)}`),$("span",null,`disk ${Tf(J.usedBytes)} / ${Tf(J.totalBytes)}`))),$(wl,{status:c.ok?"online":"warn"},c.ok?"METRICS READY":"METRICS DEGRADED")),$("div",{className:"monitor-chart-grid"},$(f7,{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"}),$(f7,{title:"Memory",metricKey:"memoryPercent",current:F.percent,points:Q,detail:`${Tf(F.usedBytes)} actual / ${Tf(F.cacheBytes)} cache excluded`,tone:"memory",testId:"metric-chart-memory"}),$(f7,{title:"Disk",metricKey:"diskPercent",current:J.percent,points:Q,detail:`${J.path||"/"} mounted ${J.mount||"--"}`,tone:"disk",testId:"metric-chart-disk"})),$("div",{className:"monitor-summary-grid"},$(cl,{label:"CPU 当前",value:In(j.percent),hint:`history ${Q.length} samples`,tone:"ok"}),$(cl,{label:"实际内存",value:Tf(F.usedBytes),hint:`${In(F.percent)} 不含缓存`}),$(cl,{label:"硬盘已用",value:Tf(J.usedBytes),hint:In(J.percent)}),$(cl,{label:"更新时间",value:qu(_.systemUpdatedAt||c.collectedAt),hint:_.providerId})),$(Sp,{current:c,onRaw:r}))),$("div",{className:"monitor-side-stack"},$(xp,{provider:_,refresh:n,onRaw:r}),$(hp,{provider:_,tasks:f,onRaw:r,limit:5}),$(du,{title:"采样说明",eyebrow:"Retention"},$("div",{className:"monitor-note-list"},$("article",null,$("b",null,"CPU"),$("span",null,"从 /proc/stat 计算相邻采样差值,首个采样用 load/cores 近似")),$("article",null,$("b",null,"Memory"),$("span",null,"实际内存 = MemTotal - MemFree - Buffers - Cached - SReclaimable + Shmem,不把 page cache / buffer 计入占用")),$("article",null,$("b",null,"Disk"),$("span",null,"使用 df -PB1 对配置路径采样,默认监控根文件系统")),$("article",null,$("b",null,"Process"),$("span",null,"从 /proc/[pid] 采集进程 CPU、实际内存 RSS、线程数和磁盘 I/O 速率;表格默认按内存占用降序")))))))}function cL(u,l){if(l==="memory")return Mu(u.rssBytes);if(l==="cpu")return Mu(u.cpuPercent);if(l==="disk")return Mu(u.readBytesPerSecond)+Mu(u.writeBytesPerSecond);if(l==="pid")return Mu(u.pid);if(l==="threads")return Mu(u.threads);if(l==="runtime")return Mu(u.elapsedSeconds);if(l==="user")return String(u.user||"");return String(u.name||u.command||"")}function AL({value:u,label:l,tone:f}){let r=Math.max(1,Math.min(100,Mu(u)));return $("div",{className:`process-meter ${f||""}`},$("span",{style:{width:`${r}%`}}),$("b",null,l))}function Sp({current:u,onRaw:l}){let[f,r]=bu({key:"memory",direction:"desc"}),n=gn.default.useContext(n7),i=u?.processSummary&&typeof u.processSummary==="object"?u.processSummary:{},y=Array.isArray(u?.processes)?u.processes:[],t=b_(()=>{let c=f.direction==="asc"?1:-1;return[...y].sort((A,j)=>{let F=cL(A,f.key),J=cL(j,f.key);if(typeof F==="string"||typeof J==="string")return String(F).localeCompare(String(J),"zh-CN")*c;return(F-J)*c||Mu(A.pid)-Mu(j.pid)})},[y,f.key,f.direction]),_=(c,A)=>{let j=f.key===A,F=j?f.direction==="asc"?"ascending":"descending":"none";return $("th",{"aria-sort":F},$("button",{type:"button",className:`process-sort-button ${j?"active":""}`,"data-testid":`process-sort-${A}`,onClick:()=>r((J)=>({key:A,direction:J.key===A&&J.direction==="desc"?"asc":"desc"}))},c,$("span",null,j?f.direction==="desc"?"↓":"↑":"↕")))};return $("section",{className:"process-resource-panel","data-testid":"process-resource-panel"},$("div",{className:"process-resource-head"},$("div",null,$("p",{className:"panel-eyebrow"},"Windows Resource Monitor Style"),$(nl,{title:"进程资源占用",level:3,loading:n})),$("div",{className:"process-resource-actions"},$("span",{className:"data-chip"},"默认按内存排序"),$("span",{className:"data-chip"},`${Mu(i.visible,t.length)} / ${Mu(i.total,t.length)} 进程`),$(bl,{title:"Process Resource Snapshot",data:{processSummary:i,processes:y},onOpen:l,testId:"raw-process-resources"}))),t.length===0?$(jl,{title:"暂无进程资源数据",text:"等待 provider-gateway 上报 /proc/[pid] 采样;旧版 provider 需要先升级到支持进程资源表的版本"}):$("div",{className:"process-table-wrap"},$("table",{className:"process-resource-table","data-testid":"process-resource-table"},$("thead",null,$("tr",null,_("进程","name"),_("PID","pid"),_("用户","user"),$("th",null,"状态"),_("CPU","cpu"),_("内存","memory"),$("th",null,"RSS"),_("磁盘 I/O","disk"),_("线程","threads"),_("运行时长","runtime"))),$("tbody",null,t.map((c)=>{let A=Mu(c.readBytesPerSecond)+Mu(c.writeBytesPerSecond);return $("tr",{key:`${c.pid}-${c.startedAt}`,"data-testid":`process-row-${ef(c.pid)}`,"data-memory-bytes":String(Mu(c.rssBytes)),"data-cpu-percent":String(Mu(c.cpuPercent)),"data-disk-bps":String(A),"data-pid":String(Mu(c.pid))},$("td",null,$("div",{className:"process-name-cell"},$("strong",null,c.name||"--"),$("span",{className:"process-command"},c.command||"--"))),$("td",null,$("code",null,c.pid||"--")),$("td",null,c.user||`uid:${c.uid??"--"}`),$("td",null,$("span",{className:`process-state state-${ef(c.state||"unknown")}`},c.state||"?")),$("td",null,$(AL,{value:c.cpuPercent,label:jp(c.cpuPercent),tone:"cpu"})),$("td",null,$(AL,{value:c.memoryPercent,label:In(c.memoryPercent),tone:"memory"})),$("td",null,Tf(c.rssBytes)),$("td",null,$("div",{className:"process-io-cell"},$("strong",null,l7(A)),$("span",null,`R ${l7(c.readBytesPerSecond)} / W ${l7(c.writeBytesPerSecond)}`))),$("td",null,c.threads||0),$("td",null,b0(Mu(c.elapsedSeconds))))})))))}function f7({title:u,metricKey:l,current:f,points:r,detail:n,tone:i,testId:y}){let t=r.map((F)=>Math.max(0,Math.min(100,Mu(F[l])))),_=t.length>1?t:[t[0]||0,t[0]||0],c=_.length<=1?100:100/(_.length-1),A=_.map((F,J)=>`${(J*c).toFixed(2)},${(46-F*0.42).toFixed(2)}`).join(" "),j=`0,48 ${A} 100,48`;return $("article",{className:`metric-chart ${i}`,"data-testid":y},$("div",{className:"metric-chart-head"},$("div",null,$("span",null,u),$("strong",null,In(f))),$("code",null,`${r.length} pts`)),$("svg",{viewBox:"0 0 100 48",preserveAspectRatio:"none",role:"img","aria-label":`${u} usage curve`},$("polygon",{points:j}),$("polyline",{points:A}),$("line",{x1:"0",x2:"100",y1:"24",y2:"24"})),$("div",{className:"metric-chart-foot"},$("span",null,"0%"),$("span",null,n),$("span",null,"100%")))}function v0(u){return Array.isArray(u)?u:[]}function Yp(u){let l=v0(u?.core?.requests?.componentSummary);return[...v0(u?.frontend?.requests?.componentSummary),...l].sort((r,n)=>Mu(n.requestCount)-Mu(r.requestCount))}function pp(u){let l=v0(u?.core?.operations?.summary);return[...v0(u?.frontend?.operations?.summary),...l].sort((r,n)=>Mu(n.count)-Mu(r.count))}function mp(u){let l=v0(u?.core?.requests?.recentFailures).map((r)=>({source:"backend",...r}));return[...v0(u?.frontend?.requests?.recentFailures).map((r)=>({source:"frontend",...r})),...l].sort((r,n)=>(Q0(n.at)??0)-(Q0(r.at)??0)).slice(0,20)}function Pp(u){let l=v0(u?.core?.operations?.recentSlowOperations);return[...v0(u?.frontend?.operations?.recentSlowOperations),...l].sort((r,n)=>Mu(n.durationMs)-Mu(r.durationMs)).slice(0,20)}function Cp(u){let l=performance.memory,f=Number(l?.usedJSHeapSize);if(Number.isFinite(f)&&f>0)return f;let r=Number(u?.appBundleBytes);if(Number.isFinite(r)&&r>0)return r;return Mu(u?.process?.heapUsedBytes)}function Mp({points:u}){let l=v0(u),f=l.map((F)=>Mu(F.mb)),r=Math.max(1,...f),n=Math.max(0,Math.min(...f,0)),i=Math.max(1,r-n),y=l.length>1?l:[...l,...l],t=y.length<=1?100:100/(y.length-1),_=y.map((F,J)=>{let Q=Mu(F.mb);return`${(J*t).toFixed(2)},${(48-(Q-n)/i*42).toFixed(2)}`}).join(" "),c=`0,50 ${_} 100,50`,A=l.at(-1),j=l[0];return $("article",{className:"performance-memory-card","data-testid":"performance-memory-chart"},$("div",{className:"performance-memory-head"},$("strong",null,`Bwebui: ${A?`${Mu(A.mb).toFixed(1)}MB`:"--"}`),$("span",null,l.length>0?`${l.length} samples`:"等待采样")),$("svg",{viewBox:"0 0 100 50",preserveAspectRatio:"none",role:"img","aria-label":"Bwebui memory trend"},$("polygon",{points:c}),$("polyline",{points:_}),$("line",{x1:"0",x2:"100",y1:"25",y2:"25"})),$("div",{className:"performance-axis-row"},$("span",null,j?tl(new Date(j.at)):"--"),$("span",null,"时间"),$("span",null,A?tl(new Date(A.at)):"--")),$("div",{className:"performance-axis-row"},$("span",null,`${n.toFixed(1)}`),$("span",null,"(MB)"),$("span",null,`${r.toFixed(1)}`)))}function Rp({onRaw:u}){let[l,f]=bu({core:null,frontend:null}),[r,n]=bu([]),[i,y]=bu(""),[t,_]=bu(!1),[c,A]=bu(null),[j,F]=bu(!1);async function J(){_(!0),y("");try{let[S,p]=await Promise.all([Tu(`${gu.apiBaseUrl}/performance`,{cache:"no-store"}),Tu(`${gu.apiBaseUrl}/frontend-performance`,{cache:"no-store"})]);f({core:S,frontend:p});let O=Cp(p);n((m)=>[...m,{at:new Date().toISOString(),mb:O/1048576}].slice(-80))}catch(S){y(Ou(S,"性能指标加载失败"))}finally{_(!1)}}J0(()=>{J();let S=setInterval(()=>void J(),5000);return()=>clearInterval(S)},[]);async function Q(){F(!0),y(""),A(null);try{let S=await Tu(`${gu.apiBaseUrl}/code-queue-load-test`,{method:"POST",body:JSON.stringify({targetMs:1000,timeoutMs:90000,url:gu.frontendPublicUrl||window.location.origin})});A(S),J()}catch(S){y(Ou(S,"Code Queue Playwright 测量失败"))}finally{F(!1)}}let w=Yp(l),L=mp(l),U=pp(l),N=Pp(l),q=l.core?.process||{},W=l.frontend?.process||{},z=l.core?.database?.codeQueueStorage||{},Z=Mu(z.total),H=c?.result||{},E=Mu(H.wallMs,NaN),D=Mu(H.networkIdleMs,NaN),h=H.withinTarget===!0,V=j?"running":c===null?"idle":c.measurementOk===!0?h?"passed":"slow":"failed";return $("div",{className:"performance-page","data-testid":"performance-page"},$("div",{className:"performance-hero"},$("div",null,$("p",{className:"panel-eyebrow"},"Unified Performance"),$(nl,{title:"性能面板",loading:t||j}),$("p",null,"按组件统计 HTTP 请求、失败率、P95 延迟,并汇总 backend/frontend 内部操作耗时。")),$("div",{className:"inline-actions"},$("button",{type:"button",className:"ghost-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-button"},j?"测试中...":"测试 Code Queue 加载"),$("button",{type:"button",className:"ghost-btn",onClick:()=>void J(),disabled:t,"data-testid":"performance-refresh-button"},t?"刷新中":"刷新"),$(bl,{title:"Performance Snapshot",data:l,onOpen:u,testId:"raw-performance"}))),$(il,{error:i}),$("div",{className:"performance-top-grid"},$(Mp,{points:r}),$("div",{className:"performance-metric-stack"},$(cl,{label:"backend RSS",value:Tf(q.rssBytes),hint:`heap ${Tf(q.heapUsedBytes)}`}),$(cl,{label:"frontend RSS",value:Tf(W.rssBytes),hint:`bundle ${Tf(l.frontend?.appBundleBytes)}`}),$(cl,{label:"Codex PG 任务",value:Z||"--",hint:z.ok?"unidesk_code_queue_tasks":"等待表初始化",tone:z.ok?"ok":"warn"}),$(cl,{label:"请求样本",value:Mu(l.core?.requests?.sampleCount)+Mu(l.frontend?.requests?.sampleCount),hint:"rolling window 3000"}))),$(du,{title:"Code Queue 加载基准",eyebrow:"Playwright / target <1s",className:"codex-load-test-panel",loading:j,actions:$("div",{className:"panel-actions"},$("button",{type:"button",className:"primary-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-panel-button"},j?"正在运行 Playwright...":"手动触发测试"),c?$(bl,{title:"Code Queue Load Test",data:c,onOpen:u,testId:"raw-code-queue-load-test"}):null)},$("div",{className:"codex-load-test-grid","data-testid":"code-queue-load-test-result"},$(cl,{label:"总耗时",value:j?"运行中":Number.isFinite(E)?Nr(E):"--",hint:c===null?"点击按钮启动远端 Playwright":`目标 ${Nr(H.targetMs||1000)} / ${H.url||"Code Queue"}`,tone:V==="passed"?"ok":V==="failed"||V==="slow"?"warn":""}),$(cl,{label:"判定",value:j?"RUNNING":V==="passed"?"PASS <1s":V==="slow"?"SLOW":V==="failed"?"FAILED":"--",hint:c?.measurementOk===!1?String(c.error||H.error||"measurement failed").slice(0,120):"导航开始 -> DOMContentLoaded -> data-load-state=complete",tone:V==="passed"?"ok":V==="idle"||V==="running"?"":"fail"}),$(cl,{label:"Network idle",value:Number.isFinite(D)?Nr(D):"--",hint:`DOMContentLoaded ${Nr(H.domContentLoadedMs)} / ${H.networkIdleReached===!1?"未在 5s 内空闲":"已空闲"}`,tone:Number.isFinite(D)&&D<=1000?"ok":"warn"}),$(cl,{label:"组件耗时",value:Number.isFinite(Mu(H.componentLoadMs,NaN))?Nr(H.componentLoadMs):"--",hint:`queue ${Nr(H.queueMs)} / detail ${Nr(H.detailMs)}`,tone:Mu(H.componentLoadMs)>1000?"warn":"ok"}),$(cl,{label:"Trace 规模",value:Number.isFinite(Mu(H.transcriptRows,NaN))?String(H.transcriptRows):"--",hint:`${H.visibleTaskCount??0} visible tasks / ${H.partial?"preview":"complete"}`})),j?$("div",{className:"performance-empty-line"},"正在通过 main-server Host SSH 启动 Playwright,完成后会显示 wall time、组件耗时和最慢 API。"):null,c&&Array.isArray(H.slowestApi)&&H.slowestApi.length>0?$("div",{className:"table-wrap performance-table-wrap compact codex-load-api-table"},$("table",{className:"performance-table"},$("thead",null,$("tr",null,["API","状态","耗时"].map((S)=>$("th",{key:S},S)))),$("tbody",null,H.slowestApi.slice(0,5).map((S,p)=>$("tr",{key:`${S.url}-${p}`},$("td",null,$("code",null,S.url)),$("td",null,S.status),$("td",null,Nr(S.durationMs))))))):null),$("div",{className:"performance-grid"},$(du,{title:"组件汇总",eyebrow:"Requests",loading:t},w.length===0?$(jl,{title:"暂无请求样本",text:"刷新几次或打开页面后会自动形成组件统计"}):$("div",{className:"table-wrap performance-table-wrap"},$("table",{className:"performance-table"},$("thead",null,$("tr",null,["组件","请求数","失败数","失败率","平均延迟","P95"].map((S)=>$("th",{key:S},S)))),$("tbody",null,w.map((S)=>$("tr",{key:S.component},$("td",null,$("code",null,S.component)),$("td",null,S.requestCount),$("td",null,S.failureCount),$("td",null,In(Mu(S.failureRate)*100)),$("td",null,Nr(S.averageLatencyMs)),$("td",null,Nr(S.p95LatencyMs)))))))),$(du,{title:"最近失败请求",eyebrow:"Failures",loading:t},L.length===0?$("div",{className:"performance-empty-line"},"最近没有失败请求"):$("div",{className:"table-wrap performance-table-wrap compact"},$("table",{className:"performance-table"},$("thead",null,$("tr",null,["时间","来源","组件","状态","路径"].map((S)=>$("th",{key:S},S)))),$("tbody",null,L.map((S,p)=>$("tr",{key:`${S.at}-${p}`},$("td",null,qu(S.at)),$("td",null,S.source),$("td",null,$("code",null,S.component)),$("td",null,$(wl,{status:"failed"},S.status)),$("td",null,$("code",null,S.path)))))))),$(du,{title:"内部操作汇总",eyebrow:"Operations",loading:t},U.length===0?$(jl,{title:"暂无内部操作样本",text:"API 查询和代理请求会自动记录内部操作耗时"}):$("div",{className:"table-wrap performance-table-wrap"},$("table",{className:"performance-table"},$("thead",null,$("tr",null,["服务","操作","次数","平均延迟","P95"].map((S)=>$("th",{key:S},S)))),$("tbody",null,U.map((S)=>$("tr",{key:`${S.service}-${S.operation}`},$("td",null,S.service),$("td",null,$("code",null,S.operation)),$("td",null,S.count),$("td",null,Nr(S.averageLatencyMs)),$("td",null,Nr(S.p95LatencyMs)))))))),$(du,{title:"最近慢操作",eyebrow:"Slowest",loading:t},N.length===0?$(jl,{title:"暂无慢操作",text:"后端会记录最近窗口内耗时最高的内部操作"}):$("div",{className:"table-wrap performance-table-wrap"},$("table",{className:"performance-table"},$("thead",null,$("tr",null,["时间","操作","耗时","结果","细节"].map((S)=>$("th",{key:S},S)))),$("tbody",null,N.map((S,p)=>$("tr",{key:`${S.at}-${S.operation}-${p}`},$("td",null,qu(S.at)),$("td",null,$("code",null,S.operation)),$("td",null,Nr(S.durationMs)),$("td",null,S.ok?"成功":"失败"),$("td",null,S.detail||"-")))))))))}function xp({provider:u,refresh:l,onRaw:f}){let[r,n]=bu(""),[i,y]=bu(null),[t,_]=bu("");async function c(A){n(A),_("");try{let j=await Tu(`${gu.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:u.providerId,command:"provider.upgrade",payload:{mode:A,source:"frontend-resource-monitor",requestedAt:new Date().toISOString()}})});y({mode:A,...j}),await l()}catch(j){_(Ou(j,"升级命令下发失败"))}finally{n("")}}return $(du,{title:"Provider Gateway 升级",eyebrow:"Remote Control",loading:Boolean(r)},$("div",{className:"upgrade-control","data-testid":"provider-upgrade-control"},$("p",null,"通过 UniDesk WebSocket 向当前计算节点下发 provider.upgrade;预检只生成升级计划,执行升级会调度节点本地 updater 容器。"),$("div",{className:"upgrade-target-line"},$("span",null,"指定 Provider"),$("code",null,u.providerId),$(wy,{node:u})),$("div",{className:"upgrade-actions"},$("button",{type:"button",className:"ghost-btn",disabled:Boolean(r),onClick:()=>c("plan"),"data-testid":"upgrade-plan-button"},r==="plan"?"预检中":"预检升级"),$("button",{type:"button",className:"ghost-btn danger",disabled:Boolean(r),onClick:()=>c("schedule"),"data-testid":"upgrade-schedule-button"},r==="schedule"?"调度中":"执行升级")),$(il,{error:t}),i?$("div",{className:"upgrade-result"},$(wl,{status:i.status||"queued"},i.status||"queued"),$("span",null,`${i.mode==="schedule"?"执行升级":"预检升级"} 已下发`),$("span",null,`指定版本 ${t7(wL(u))}`),$("code",null,i.taskId||"--"),$(bl,{title:"Provider Upgrade Dispatch",data:i,onOpen:f})):$("span",{className:"muted"},"升级任务结果会进入任务历史;执行升级可能导致 provider 短暂重连。")))}function BL({records:u,onRaw:l,compact:f=!1}){if(u.length===0)return $(jl,{title:"暂无远程更新记录",text:"该节点还没有 provider.upgrade 任务;执行预检或升级后会在这里形成结构化记录"});return $("div",{className:`upgrade-record-table-wrap table-wrap ${f?"compact":""}`},$("table",{className:"upgrade-record-table"},$("thead",null,$("tr",null,$("th",null,"状态"),$("th",null,"模式"),$("th",null,"任务"),$("th",null,"来源"),$("th",null,"耗时"),$("th",null,"策略"),$("th",null,"Gateway 版本"),$("th",null,"结果记录"),$("th",null,"更新时间"),$("th",null,"操作"))),$("tbody",null,u.map((r)=>$("tr",{key:r.id,"data-testid":`gateway-upgrade-record-${ef(r.id)}`},$("td",null,$(wl,{status:r.status})),$("td",null,$("span",{className:`mode-chip ${S6(r)}`},S6(r)==="schedule"?"执行升级":"预检")),$("td",null,$("strong",null,"provider.upgrade"),$("code",null,r.id)),$("td",null,Qp(r)),$("td",null,$(DL,{task:r})),$("td",null,Np(r)),$("td",null,$("span",{className:"version-chip"},zL(r))),$("td",null,$("span",{className:`upgrade-outcome ${String(r.status||"").toLowerCase()}`},TL(r))),$("td",null,qu(r.updatedAt)),$("td",null,$(bl,{title:`Provider Upgrade Task ${r.id}`,data:v_(r),onOpen:l})))))))}function hp({provider:u,tasks:l,onRaw:f,limit:r=5}){let n=EL(l,u.providerId).slice(0,r);return $(du,{title:"远程更新记录",eyebrow:u.providerId,actions:$(wy,{node:u}),className:"provider-upgrade-records-panel"},$("div",{"data-testid":`provider-upgrade-records-${ef(u.providerId)}`},$(BL,{records:n,onRaw:f,compact:!0})))}function bp({nodes:u,tasks:l,onRaw:f}){let r=b_(()=>u.map((i)=>{let y=EL(l,i.providerId);return{node:i,records:y,latest:qp(y),capabilities:LL(i)}}),[u,l]),n=r.reduce((i,y)=>i+y.records.length,0);return $("div",{className:"gateway-page","data-testid":"gateway-version-page"},$(du,{title:"Provider Gateway 版本",eyebrow:`${u.length} Providers / ${n} 更新记录`},u.length===0?$(jl,{title:"暂无 Provider 节点",text:"等待 provider-gateway 注册后显示版本号和升级记录"}):$("div",{className:"table-wrap gateway-version-table-wrap"},$("table",{className:"gateway-version-table"},$("thead",null,$("tr",null,$("th",null,"状态"),$("th",null,"Provider"),$("th",null,"Gateway 版本"),$("th",null,"升级策略"),$("th",null,"运维可用性"),$("th",null,"运行时间"),$("th",null,"能力"),$("th",null,"最近远程更新"),$("th",null,"操作"))),$("tbody",null,r.map((i)=>$("tr",{key:i.node.providerId},$("td",null,$(wl,{status:i.node.status})),$("td",null,$("strong",null,i.node.name),$("code",null,i.node.providerId)),$("td",null,$(wy,{node:i.node})),$("td",null,h_(i.node)),$("td",null,$(_7,{node:i.node})),$("td",null,yL(i.node)?qu(yL(i.node)):"待新版上报"),$("td",null,$("div",{className:"capability-row"},i.capabilities.length===0?$("span",{className:"muted"},"未声明"):i.capabilities.slice(0,5).map((y)=>$("span",{key:y,className:"data-chip"},y)))),$("td",null,i.latest?$("div",{className:"latest-upgrade-cell"},$(wl,{status:i.latest.status}),$("span",null,`${S6(i.latest)==="schedule"?"执行升级":"预检"} / ${qu(i.latest.updatedAt)}`),$("small",null,`Gateway ${zL(i.latest)}`),$("small",null,TL(i.latest))):$("span",{className:"muted"},"暂无记录")),$("td",null,$(bl,{title:`Provider ${i.node.providerId}`,data:i.node,onOpen:f})))))))),$(du,{title:"远程更新记录",eyebrow:"Structured provider.upgrade records"},u.length===0?$(jl,{title:"暂无记录",text:"没有 provider 节点时不会生成远程更新记录"}):$("div",{className:"gateway-record-grid"},r.map((i)=>$("article",{key:i.node.providerId,className:"gateway-record-card","data-testid":`gateway-records-${ef(i.node.providerId)}`},$("div",{className:"gateway-record-head"},$("div",null,$("strong",null,i.node.name),$("code",null,i.node.providerId)),$(wy,{node:i.node})),$("div",{className:"gateway-record-meta"},$("span",null,`心跳 ${qu(i.node.lastHeartbeat)}`),$("span",null,`策略 ${h_(i.node)}`),$("span",null,`${i.records.length} 条记录`)),$(BL,{records:i.records.slice(0,8),onRaw:f,compact:!0}))))))}function vp(u){if(u==="running")return"online";if(u==="paused"||u==="restarting")return"warn";if(u==="exited"||u==="dead")return"offline";return"internal"}function VL(u){return/^[a-f0-9]{48,64}$/i.test(u)}function x_(u){let l=String(u?.name||""),f=String(u?.labels||"");return l==="unidesk_pgdata_10gb"||f.includes("com.docker.compose.volume=unidesk_pgdata_10gb")||l.toLowerCase().includes("pgdata")}function jL(u){let l=String(u?.name||""),f=String(u?.labels||"");if(x_(u))return 0;if(f.includes("com.docker.compose.project=unidesk"))return 1;if(!VL(l))return 2;return 3}function kp(u){return[...u].sort((l,f)=>{let r=jL(l)-jL(f);if(r!==0)return r;return String(l.name||"").localeCompare(String(f.name||""))})}function Ip({nodes:u,dockerStatuses:l,onRaw:f}){let[r,n]=bu(""),i=b_(()=>u.map((N)=>{let q=l.find((W)=>W.providerId===N.providerId);return{...N,dockerStatus:q?.dockerStatus||null,dockerUpdatedAt:q?.updatedAt||null}}),[u,l]),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 $(jl,{title:"暂无 Docker 节点",text:"等待 provider 上报 Docker daemon 状态"});let t=y.dockerStatus,_=y.providerId==="main-server",c=t?.counts||{},A=t?.daemon||{},j=t?.containers||[],F=t?.images||[],J=kp(t?.volumes||[]),Q=_?J.find(x_):null,w=t?.networks||[],L=j.filter((N)=>N.state==="running"),U=j.filter((N)=>N.state!=="running");return $("div",{className:"docker-page","data-testid":"docker-status-page"},$("div",{className:"docker-node-strip"},i.map((N)=>$("button",{key:N.providerId,type:"button",className:`docker-node-tile ${y.providerId===N.providerId?"active":""}`,onClick:()=>n(N.providerId)},$("span",{className:`pulse ${N.status}`}),$("strong",null,N.name),$("code",null,N.providerId),$("span",null,N.dockerStatus?`Docker ${N.dockerStatus.ok?"ready":"degraded"}`:"等待上报")))),$("div",{className:"docker-layout"},$(du,{title:"Docker Desktop 视图",eyebrow:y.name,className:"docker-main-panel",actions:t?$(bl,{title:`Docker ${y.providerId}`,data:t,onOpen:f}):null},!t?$(jl,{title:"Docker 状态未上报",text:"provider-gateway 会在连接后周期性采集 docker info / ps / images / volume / network"}):$("div",null,$("div",{className:"docker-hero"},$("div",null,$("p",{className:"panel-eyebrow"},"Daemon"),$("h3",null,A.name||y.providerId),$("div",{className:"docker-meta"},$("span",null,A.serverVersion?`Engine ${A.serverVersion}`:"Engine --"),$("span",null,A.operatingSystem||"OS --"),$("span",null,A.architecture||"arch --"),$("span",null,`${A.cpus||0} CPU / ${Tf(A.memoryBytes)}`))),$(wl,{status:t.ok?"online":"warn"},t.ok?"Docker Ready":"Docker Degraded")),$("div",{className:"docker-metrics"},$(cl,{label:"Containers",value:c.containers??j.length,hint:`${c.running??L.length} running / ${c.stopped??U.length} stopped`,tone:"ok"}),$(cl,{label:"Images",value:c.images??F.length,hint:`${c.daemonImages??c.images??F.length} daemon images`}),$(cl,{label:"Volumes",value:c.volumes??J.length,hint:_?Q?"database volume visible":"database volume missing":"node local volumes",tone:Q?"ok":""}),$(cl,{label:"Networks",value:c.networks??w.length,hint:A.driver?`driver ${A.driver}`:"docker networks"})),_?$(gp,{volume:Q,volumeCount:J.length}):null,$("div",{className:"docker-section-head"},$("h3",null,"Containers"),$("span",null,`updated ${qu(y.dockerUpdatedAt||t.collectedAt)}`)),$("div",{className:"docker-container-table table-wrap","data-testid":"docker-container-table"},$("table",null,$("thead",null,$("tr",null,$("th",null,"状态"),$("th",null,"容器"),$("th",null,"镜像"),$("th",null,"端口"),$("th",null,"运行时间"),$("th",null,"重启策略"),$("th",null,"PID"),$("th",null,"大小"))),$("tbody",null,j.length===0?$("tr",null,$("td",{colSpan:8},"暂无容器")):j.map((N)=>$("tr",{key:`${N.id}-${N.name}`},$("td",null,$(wl,{status:vp(N.state)},N.state||"unknown")),$("td",null,$("strong",null,N.name||"--"),$("code",null,N.id||"--")),$("td",null,N.image||"--"),$("td",null,N.ports||$("span",{className:"muted"},"未发布")),$("td",null,N.runningFor||N.status||"--"),$("td",null,N.restartPolicy?$(wl,{status:N.restartPolicy==="always"?"online":"warn"},N.restartPolicy):"--"),$("td",null,N.pidMode?$("code",null,N.pidMode):"--"),$("td",null,N.size||"--")))))))),$("div",{className:"docker-side-stack"},$(r7,{title:"Images",items:F,render:(N)=>$("article",{key:`${N.id}-${N.repository}`,className:"docker-side-row"},$("strong",null,`${N.repository}:${N.tag}`),$("span",null,N.size||"--"),$("code",null,N.id||"--"))}),$(r7,{title:"Volumes",items:J,limit:J.length,render:(N)=>$("article",{key:N.name,className:`docker-side-row volume-row ${_&&x_(N)?"database-volume":""}`,"data-testid":_&&x_(N)?"database-volume-row":void 0},$("strong",null,N.name),$("span",null,_&&x_(N)?"PostgreSQL":VL(String(N.name||""))?"anonymous":"named"),$("code",null,N.mountpoint||N.driver||N.scope||"--"))}),$(r7,{title:"Networks",items:w,render:(N)=>$("article",{key:N.id||N.name,className:"docker-side-row"},$("strong",null,N.name),$("span",null,N.driver||"--"),$("code",null,N.id||"--"))}))))}function gp({volume:u,volumeCount:l}){return $("section",{className:`docker-volume-focus ${u?"ready":"missing"}`,"data-testid":"database-volume-card"},$("div",{className:"volume-focus-head"},$("span",{className:"panel-eyebrow"},"Database Named Volume"),$(wl,{status:u?"online":"warn"},u?"FOUND":"MISSING")),u?$("div",{className:"volume-focus-body"},$("strong",null,u.name),$("span",null,"PostgreSQL data volume for unidesk-database"),$("div",{className:"volume-route"},$("code",null,u.mountpoint||"/var/lib/docker/volumes/unidesk_pgdata_10gb/_data"),$("span",null,"->"),$("code",null,"unidesk-database:/var/lib/postgresql/data")),$("div",{className:"docker-meta compact"},$("span",null,`driver ${u.driver||"--"}`),$("span",null,`scope ${u.scope||"--"}`),$("span",null,`${l} volumes reported`))):$("div",{className:"volume-focus-body"},$("strong",null,"unidesk_pgdata_10gb"),$("span",null,"当前 Docker 快照没有发现数据库命名卷;请检查 provider-gateway 的 Docker volume 上报。")))}function r7({title:u,items:l,render:f,limit:r}){let n=l.slice(0,r??12),i=Math.max(0,l.length-n.length);return $(du,{title:u,eyebrow:`${l.length} items`,className:"docker-side-panel"},l.length===0?$(jl,{title:`暂无 ${u}`,text:"等待 Docker 状态采集"}):$("div",{className:"docker-side-list"},n.map(f),i>0?$("div",{className:"docker-side-more"},`+ ${i} more`):null))}function sp({microservices:u,onRaw:l,onNavigate:f}){let r=u.filter((n)=>_L(n).public===!1);return $("div",{className:"microservice-page","data-testid":"microservice-catalog-page"},$(du,{title:"用户服务目录",eyebrow:"Provider Mounted User Services"},$("div",{className:"metric-grid"},$(cl,{label:"服务总数",value:u.length,hint:"config.json 用户服务登记"}),$(cl,{label:"私有后端",value:r.length,hint:"不直接暴露公网",tone:"ok"}),$(cl,{label:"D601 服务",value:u.filter((n)=>n.providerId==="D601").length,hint:"compute-node docker"}),$(cl,{label:"集成前端",value:u.filter((n)=>n.frontend?.integrated).length,hint:"UniDesk React 页面"}))),$(du,{title:"服务映射",eyebrow:"Repo Reference + Runtime"},u.length===0?$(jl,{title:"暂无用户服务",text:"在 config.json 的 microservices 中登记用户服务的 provider、仓库引用和后端映射"}):$("div",{className:"table-wrap"},$("table",{className:"microservice-table"},$("thead",null,$("tr",null,$("th",null,"服务"),$("th",null,"Provider"),$("th",null,"代码引用"),$("th",null,"Docker 引用"),$("th",null,"后端映射"),$("th",null,"开发入口"),$("th",null,"运行态"),$("th",null,"操作"))),$("tbody",null,u.map((n)=>{let i=ZL(n),y=Wp(n),t=_L(n),_=i.availability||{},c=_.status||(i.providerStatus==="online"?"unknown":"unhealthy");return $("tr",{key:n.id,"data-testid":`microservice-row-${ef(n.id)}`},$("td",null,$("strong",null,n.name),$("code",null,n.id)),$("td",null,$("strong",null,i.providerName||n.providerId),$("code",null,n.providerId)),$("td",null,$("span",null,y.url||"--"),$("code",null,y.commitId||"--")),$("td",null,$("span",null,y.composeFile||"--"),$("code",null,`${y.composeService||"--"} / ${y.containerName||"--"}`)),$("td",null,$(wl,{status:t.public?"warn":"online"},t.public?"public":"private"),$("code",null,`${t.nodeBindHost||"--"}:${t.nodePort||"--"} -> ${t.proxyMode||"--"}`)),$("td",null,$("span",null,n.development?.sshPassthrough?"SSH 透传":"未配置"),$("code",null,n.development?.worktreePath||"--")),$("td",null,$(wl,{status:c==="healthy"?"online":c==="unknown"?"warn":"failed"},c),$("span",null,_.reason||i.providerStatus||"unknown"),$(sn,{data:i.container,empty:"容器快照未上报"})),$("td",null,$("div",{className:"microservice-actions"},n.id==="findjob"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","findjob"),"data-testid":"open-findjob-button"},"打开"):null,n.id==="pipeline"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","pipeline"),"data-testid":"open-pipeline-button"},"打开"):null,n.id==="todo-note"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","todo-note"),"data-testid":"open-todo-note-button"},"打开"):null,n.id==="met-nonlinear"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","met-nonlinear"),"data-testid":"open-met-nonlinear-button"},"打开"):null,n.id==="claudeqq"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","claudeqq"),"data-testid":"open-claudeqq-button"},"打开"):null,n.id==="baidu-netdisk"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","baidu-netdisk"),"data-testid":"open-baidu-netdisk-button"},"打开"):null,n.id==="oa-event-flow"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","oa-event-flow"),"data-testid":"open-oa-event-flow-button"},"打开"):null,n.id==="v3sctl-adapter"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","v3sctl"),"data-testid":"open-v3sctl-button"},"打开"):null,n.id==="code-queue"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","code-queue"),"data-testid":"open-code-queue-button"},"打开"):null,n.id==="project-manager"?$("button",{type:"button",className:"ghost-btn",onClick:()=>f("apps","project-manager"),"data-testid":"open-project-manager-button"},"打开"):null,$(bl,{title:`用户服务 ${n.id}`,data:n,onOpen:l}))))}))))))}function ap({nodes:u,onDispatched:l,onRaw:f}){let r=u.filter((V)=>V.status==="online"),[n,i]=bu(r[0]?.providerId||u[0]?.providerId||""),[y,t]=bu("docker.ps"),[_,c]=bu("frontend"),[A,j]=bu("operator-check"),[F,J]=bu("normal"),[Q,w]=bu(!1),[L,U]=bu(""),[N,q]=bu(!1),[W,z]=bu(null),[Z,H]=bu("");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:A,priority:F}}function D(){U(JSON.stringify(E(),null,2)),w(!0)}async function h(V){V.preventDefault(),q(!0),H("");try{let S=Q?JSON.parse(L||"{}"):E(),p=await Tu(`${gu.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:n,command:y,payload:S})});z(p),await l()}catch(S){H(Ou(S,"下发失败"))}finally{q(!1)}}return $("div",{className:"page-grid dispatch-grid"},$(du,{title:"下发任务",eyebrow:"Real WebSocket Dispatch"},$("form",{className:"dispatch-form",onSubmit:h},$("label",null,"Provider",$("select",{value:n,onChange:(V)=>i(V.target.value)},u.map((V)=>$("option",{key:V.providerId,value:V.providerId},`${V.name} / ${V.providerId}`)))),$("label",null,"Command",$("select",{value:y,onChange:(V)=>t(V.target.value)},$("option",{value:"docker.ps"},"docker.ps"),$("option",{value:"host.ssh"},"host.ssh"),$("option",{value:"microservice.http"},"microservice.http"),$("option",{value:"echo"},"echo"))),$("label",null,"来源",$("input",{value:_,onChange:(V)=>c(V.target.value)})),$("label",null,"备注",$("input",{value:A,onChange:(V)=>j(V.target.value)})),$("label",null,"优先级",$("select",{value:F,onChange:(V)=>J(V.target.value)},$("option",{value:"normal"},"normal"),$("option",{value:"low"},"low"),$("option",{value:"urgent"},"urgent"))),$("div",{className:"dispatch-actions"},$("button",{type:"button",className:"ghost-btn",onClick:D},"查看原始JSON"),$("button",{type:"submit",disabled:N||!n},N?"下发中":"下发任务")),Q?$("label",{className:"raw-editor-label"},"高级 Payload",$("textarea",{className:"raw-editor",value:L,onChange:(V)=>U(V.target.value)})):null,$(il,{error:Z,wide:!0}))),$(du,{title:"下发结果",eyebrow:"Response"},W?$("div",{className:"result-card"},$(wl,{status:W.status||"queued"},W.status||"queued"),$("dl",null,$("dt",null,"Task ID"),$("dd",null,$("code",null,W.taskId||"--")),$("dt",null,"Provider 在线"),$("dd",null,hi(W.providerOnline))),$(bl,{title:"Dispatch Response",data:W,onOpen:f})):$(jl,{title:"等待操作",text:"任务响应会以结构化结果卡展示"})))}function FL({task:u,onRaw:l}){return $("article",{className:"compact-row"},$(wl,{status:u.status}),$("div",null,$("strong",null,u.command),$("code",null,u.id)),$("span",null,Ly(u)?`已等待 ${i7(u.updatedAt)}`:`耗时 ${b0(NL(u)??0)}`),$(bl,{title:`Task ${u.id}`,data:v_(u),onOpen:l}))}function DL({task:u}){let l=NL(u),f=Ly(u);return $("div",{className:"task-duration"},$("strong",null,l===null?"--":b0(l)),$("span",null,f?`已运行 / 创建 ${qu(u.createdAt)}`:`创建 ${qu(u.createdAt)}`))}function op({task:u}){let l=String(u?.status||"").toLowerCase(),f=u?.result,r=f&&typeof f==="object"&&!Array.isArray(f)?f:{},i=["exitCode","code","signal","timeoutMs","previousStatus","mode"].filter((y)=>r[y]!==void 0&&r[y]!==null);if(l==="failed"){let y=qL(u);return $("div",{className:"task-diagnostic failed"},$("b",null,"失败原因"),$("span",{className:"diagnostic-reason"},hi(y)),i.length>0?$("div",{className:"diagnostic-meta"},i.map((t)=>$("span",{key:t,className:"data-chip"},$("b",null,t),$("span",null,hi(r[t]))))):null)}if(Ly(u))return $("div",{className:"task-diagnostic warn"},$("b",null,"等待终态"),$("span",null,`最后更新 ${i7(u.updatedAt)} 前`));return $("div",{className:"task-diagnostic ok"},$("b",null,"完成摘要"),$(sn,{data:f,empty:"无执行输出"}))}function dp({tasks:u,onRaw:l}){let f=u.filter(Ly);return $("div",{"data-testid":"pending-task-page"},$(du,{title:"待处理任务",eyebrow:`${f.length} Pending`},f.length===0?$(jl,{title:"当前无待处理任务",text:"queued / dispatched / running 会在超时后自动转为 failed;历史记录仍可在任务历史中查看"}):$("div",{className:"table-wrap","data-testid":"pending-task-table"},$("table",null,$("thead",null,$("tr",null,$("th",null,"状态"),$("th",null,"任务"),$("th",null,"Provider"),$("th",null,"已等待"),$("th",null,"载荷摘要"),$("th",null,"操作"))),$("tbody",null,f.map((r)=>$("tr",{key:r.id},$("td",null,$(wl,{status:r.status})),$("td",null,$("strong",null,r.command),$("code",null,r.id)),$("td",null,$("code",null,r.providerId)),$("td",null,i7(r.updatedAt)),$("td",null,$(sn,{data:r.payload})),$("td",null,$(bl,{title:`Pending Task ${r.id}`,data:v_(r),onOpen:l})))))))))}function ep({tasks:u,onRaw:l}){return $("div",{"data-testid":"task-history-page"},$(du,{title:"任务历史",eyebrow:`${u.length} Tasks`},u.length===0?$(jl,{title:"暂无任务",text:"下发任务后会在这里看到生命周期"}):$("div",{className:"table-wrap"},$("table",{className:"task-history-table"},$("thead",null,$("tr",null,$("th",null,"状态"),$("th",null,"任务"),$("th",null,"Provider"),$("th",null,"任务耗时"),$("th",null,"载荷摘要"),$("th",null,"诊断信息"),$("th",null,"更新时间"),$("th",null,"操作"))),$("tbody",null,u.map((f)=>$("tr",{key:f.id,"data-testid":`task-row-${ef(f.id)}`},$("td",null,$(wl,{status:f.status})),$("td",null,$("strong",null,f.command),$("code",null,f.id)),$("td",null,$("code",null,f.providerId)),$("td",null,$(DL,{task:f})),$("td",null,$(sn,{data:f.payload})),$("td",null,$(op,{task:f})),$("td",null,qu(f.updatedAt)),$("td",null,$(bl,{title:`Task ${f.id}`,data:v_(f),onOpen:l})))))))))}function um({tasks:u,onRaw:l}){let f=u.filter((r)=>["succeeded","failed"].includes(r.status));return $(du,{title:"执行结果",eyebrow:"Finished Tasks"},f.length===0?$(jl,{title:"暂无结果",text:"任务完成后展示 provider 返回的结构化摘要"}):$("div",{className:"result-grid"},f.map((r)=>$("article",{key:r.id,className:"result-card"},$("div",{className:"node-card-head"},$("strong",null,r.command),$(wl,{status:r.status})),$("code",null,r.id),$(sn,{data:r.result,empty:"无执行输出"}),$(bl,{title:`Task Result ${r.id}`,data:v_(r),onOpen:l})))))}function lm(u){if(!u||typeof u!=="object")return"--";if(u.type==="interval")return`每 ${b0(Number(u.everySeconds||0))}`;return`每天 ${u.timeOfDay||"03:00"} UTC`}function fm(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 rm(u){let l=String(u||"").toLowerCase();if(l==="succeeded")return"online";if(l==="failed")return"failed";if(l==="running"||l==="queued")return"warn";return l}function nm(u){let l=Number(u?.durationMs);if(Number.isFinite(l)&&l>=0)return b0(l/1000);let f=Q0(u?.startedAt||u?.createdAt);if(f===null)return"--";let n=Q0(u?.finishedAt)??Date.now();return b0(Math.max(0,(n-f)/1000))}function UL(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 im({schedules:u,scheduleRuns:l,nodes:f,refresh:r,onRaw:n}){let[i,y]=bu(UL(f||[])),[t,_]=bu(!1),[c,A]=bu(""),[j,F]=bu(""),J=[...l||[]].sort((W,z)=>(Q0(z.updatedAt)??0)-(Q0(W.updatedAt)??0));function Q(W,z){y((Z)=>({...Z,[W]:z}))}function w(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||f[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 L(){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 U(W){W.preventDefault(),_(!0),A(""),F("");try{let z=L(),Z=encodeURIComponent(String(z.id));await Tu(`${gu.apiBaseUrl}/schedules/${Z}`,{method:"PUT",body:JSON.stringify(z)}),F("定时任务已保存"),await r()}catch(z){A(Ou(z,"保存定时任务失败"))}finally{_(!1)}}async function N(W){if(!W?.id)return;_(!0),A(""),F("");try{await Tu(`${gu.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}`,{method:"DELETE"}),F(`已删除 ${W.id}`),await r()}catch(z){A(Ou(z,"删除定时任务失败"))}finally{_(!1)}}async function q(W){if(!W?.id)return;_(!0),A(""),F("");try{let z=await Tu(`${gu.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}/run`,{method:"POST",body:"{}"});F(`已触发 ${W.id} / ${z?.run?.id||"run"}`),await r()}catch(z){A(Ou(z,"触发定时任务失败"))}finally{_(!1)}}return $("div",{className:"page-grid scheduled-task-page","data-testid":"scheduled-task-page"},$(du,{title:"定时任务",eyebrow:`${(u||[]).length} Schedules`},(u||[]).length===0?$(jl,{title:"暂无定时任务",text:"创建 daily / dispatch / PGDATA backup 任务后会在这里展示下一次执行时间和最近结果"}):$("div",{className:"schedule-card-grid"},(u||[]).map((W)=>$("article",{key:W.id,className:"schedule-card","data-testid":`schedule-row-${ef(W.id)}`},$("div",{className:"node-card-head"},$("strong",null,W.name||W.id),$(wl,{status:W.enabled?"online":"warn"},W.enabled?"enabled":"disabled")),$("code",null,W.id),$("dl",null,$("dt",null,"计划"),$("dd",null,lm(W.schedule)),$("dt",null,"动作"),$("dd",null,fm(W.action)),$("dt",null,"下次执行"),$("dd",null,qu(W.nextRunAt)),$("dt",null,"最近执行"),$("dd",null,W.lastRunAt?`${qu(W.lastRunAt)} / ${W.lastRunId||"--"}`:"--")),$("div",{className:"dispatch-actions"},$("button",{type:"button",className:"ghost-btn",disabled:t,onClick:()=>w(W)},"编辑"),$("button",{type:"button",className:"ghost-btn",disabled:t,onClick:()=>q(W),"data-testid":`schedule-run-${ef(W.id)}`},"手动触发"),$("button",{type:"button",className:"ghost-btn danger",disabled:t,onClick:()=>N(W)},"删除"),$(bl,{title:`Schedule ${W.id}`,data:W,onOpen:n})))))),$(du,{title:i.id?"配置定时任务":"新建定时任务",eyebrow:"CRUD"},$("form",{className:"dispatch-form schedule-form",onSubmit:U},$("label",null,"ID",$("input",{value:i.id,onChange:(W)=>Q("id",W.target.value)})),$("label",null,"名称",$("input",{value:i.name,onChange:(W)=>Q("name",W.target.value)})),$("label",null,"每日执行时间 UTC",$("input",{value:i.timeOfDay,placeholder:"03:30",onChange:(W)=>Q("timeOfDay",W.target.value)})),$("label",null,"启用",$("select",{value:i.enabled?"true":"false",onChange:(W)=>Q("enabled",W.target.value==="true")},$("option",{value:"true"},"enabled"),$("option",{value:"false"},"disabled"))),$("label",null,"动作类型",$("select",{value:i.actionType,onChange:(W)=>Q("actionType",W.target.value)},$("option",{value:"pgdata_backup"},"PGDATA 备份到百度网盘"),$("option",{value:"dispatch"},"Provider Dispatch"))),i.actionType==="pgdata_backup"?[$("label",{key:"remote"},"网盘根目录",$("input",{value:i.remoteBaseDir,onChange:(W)=>Q("remoteBaseDir",W.target.value)})),$("label",{key:"staging"},"本地 staging 子目录",$("input",{value:i.stagingSubdir,onChange:(W)=>Q("stagingSubdir",W.target.value)}))]:[$("label",{key:"provider"},"Provider",$("select",{value:i.providerId,onChange:(W)=>Q("providerId",W.target.value)},(f||[]).map((W)=>$("option",{key:W.providerId,value:W.providerId},`${W.name} / ${W.providerId}`)))),$("label",{key:"command"},"Command",$("select",{value:i.command,onChange:(W)=>Q("command",W.target.value)},$("option",{value:"echo"},"echo"),$("option",{value:"docker.ps"},"docker.ps"),$("option",{value:"host.ssh"},"host.ssh"),$("option",{value:"microservice.http"},"microservice.http"))),$("label",{key:"payload",className:"raw-editor-label"},"Payload JSON",$("textarea",{className:"raw-editor",value:i.payloadJson,onChange:(W)=>Q("payloadJson",W.target.value)}))],$("label",null,"超时 ms",$("input",{value:i.timeoutMs,onChange:(W)=>Q("timeoutMs",W.target.value)})),$("label",{className:"raw-editor-label"},"描述",$("textarea",{className:"raw-editor compact",value:i.description,onChange:(W)=>Q("description",W.target.value)})),$("div",{className:"dispatch-actions"},$("button",{type:"button",className:"ghost-btn",disabled:t,onClick:()=>y(UL(f||[]))},"重置"),$("button",{type:"submit",disabled:t||!i.id},t?"保存中":"保存任务")),j?$("p",{className:"muted paragraph"},j):null,$(il,{error:c,wide:!0}))),$(du,{title:"历史执行记录",eyebrow:`${J.length} Runs`},J.length===0?$(jl,{title:"暂无执行记录",text:"定时触发或手动触发后会生成 run history"}):$("div",{className:"table-wrap"},$("table",{className:"task-history-table schedule-run-table"},$("thead",null,$("tr",null,$("th",null,"状态"),$("th",null,"任务"),$("th",null,"触发"),$("th",null,"耗时"),$("th",null,"结果摘要"),$("th",null,"更新时间"),$("th",null,"操作"))),$("tbody",null,J.map((W)=>$("tr",{key:W.id,"data-testid":`schedule-run-row-${ef(W.id)}`},$("td",null,$(wl,{status:rm(W.status)},W.status)),$("td",null,$("strong",null,W.scheduleId),$("code",null,W.id),W.taskId?$("code",null,W.taskId):null),$("td",null,W.trigger||"--"),$("td",null,nm(W)),$("td",null,$(sn,{data:W.result||W.error,empty:"无结果"})),$("td",null,qu(W.updatedAt)),$("td",null,$(bl,{title:`Schedule Run ${W.id}`,data:W,onOpen:n})))))))))}function ym({data:u}){let l=u.overview||{};return $("div",{className:"page-grid topology-grid"},$(du,{title:"公开入口",eyebrow:"Public"},$("div",{className:"endpoint-list"},$("article",null,$("b",null,"Frontend"),$("span",null,gu.frontendPublicUrl||window.location.origin),$(wl,{status:"online"},"public")),$("article",null,$("b",null,"Provider Ingress"),$("span",null,gu.providerIngressPublicUrl||"ws://public/ws/provider"),$(wl,{status:"online"},"public")))),$(du,{title:"内部服务",eyebrow:"Docker Network Only"},$("div",{className:"endpoint-list"},$("article",null,$("b",null,"backend-core API"),$("span",null,"http://backend-core:8080"),$(wl,{status:"internal"},"internal")),$("article",null,$("b",null,"database"),$("span",null,"postgres://database:5432/unidesk"),$(wl,{status:"internal"},"internal")))),$(du,{title:"运行态",eyebrow:"Runtime"},$("div",{className:"metric-grid"},$(cl,{label:"DB Ready",value:l.dbReady?"YES":"NO",hint:"internal health"}),$(cl,{label:"Online Nodes",value:l.onlineNodeCount??0,hint:"provider-gateway self-link"}))))}function tm({session:u}){return $(du,{title:"认证策略",eyebrow:"Frontend Login"},$("div",{className:"policy-grid"},$("article",null,$("span",null,"默认账号"),$("strong",null,gu.authUsername||"admin")),$("article",null,$("span",null,"当前会话"),$("strong",null,u?.user?.username||"--")),$("article",null,$("span",null,"Session TTL"),$("strong",null,`${gu.sessionTtlSeconds||0}s`)),$("article",null,$("span",null,"API 访问"),$("strong",null,"同源 Cookie 保护"))),$("p",{className:"muted paragraph"},"浏览器只访问 frontend 同源接口;frontend 容器使用 Docker 内网代理 backend-core API。"))}function _m(){return $(du,{title:"安全边界",eyebrow:"Exposure Rule"},$("div",{className:"security-board"},$("article",{className:"allow"},$("b",null,"允许公网"),$("span",null,"frontend 登录入口"),$("span",null,"provider ingress WebSocket/health")),$("article",{className:"deny"},$("b",null,"禁止公网"),$("span",null,"backend-core REST API"),$("span",null,"PostgreSQL database")),$("article",null,$("b",null,"数据库卷"),$("span",null,"named volume unidesk_pgdata_10gb"),$("span",null,"CLI stop/start 不删除数据卷"))))}function $m({activeModule:u,activeTab:l,data:f,session:r,refresh:n,onRaw:i,onNavigate:y}){if(u==="ops"&&l==="status")return $(Ep,{data:f,onRaw:i,onNavigate:y});if(u==="ops"&&l==="performance")return $(Rp,{onRaw:i});if(u==="ops"&&l==="events")return $(Op,{events:f.events,onRaw:i});if(u==="ops"&&l==="logs")return $(Hp,{logs:f.logs,onRaw:i});if(u==="nodes"&&l==="list")return $(Bp,{nodes:f.nodes,onRaw:i});if(u==="nodes"&&l==="monitor")return $(Xp,{nodes:f.nodes,systemStatuses:f.systemStatuses,tasks:f.tasks,onRaw:i,refresh:n});if(u==="nodes"&&l==="docker")return $(Ip,{nodes:f.nodes,dockerStatuses:f.dockerStatuses,onRaw:i});if(u==="nodes"&&l==="gateway")return $(bp,{nodes:f.nodes,tasks:f.tasks,onRaw:i});if(u==="nodes"&&l==="labels")return $(Vp,{nodes:f.nodes});if(u==="nodes"&&l==="heartbeats")return $(Dp,{nodes:f.nodes});if(u==="tasks"&&l==="dispatch")return $(ap,{nodes:f.nodes,onDispatched:n,onRaw:i});if(u==="tasks"&&l==="scheduled")return $(im,{schedules:f.schedules,scheduleRuns:f.scheduleRuns,nodes:f.nodes,refresh:n,onRaw:i});if(u==="tasks"&&l==="pending")return $(dp,{tasks:f.pendingTasks,onRaw:i});if(u==="tasks"&&l==="history")return $(ep,{tasks:f.tasks,onRaw:i});if(u==="tasks"&&l==="results")return $(um,{tasks:f.tasks,onRaw:i});if(u==="apps"&&l==="catalog")return $(sp,{microservices:f.microservices,onRaw:i,onNavigate:y});if(u==="apps"&&l==="todo-note")return $(aw,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&l==="findjob")return $(hQ,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&l==="pipeline")return $(xw,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&l==="met-nonlinear")return $(gQ,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&l==="claudeqq")return $(qJ,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&l==="baidu-netdisk")return $(JJ,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&l==="filebrowser")return $(xQ,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&l==="oa-event-flow")return $(lN,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&l==="v3sctl")return $(fL,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl,onNavigate:y});if(u==="apps"&&l==="code-queue")return $(pQ,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl,initialTasksData:_p});if(u==="apps"&&l==="project-manager")return $(vw,{microservices:f.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="config"&&l==="topology")return $(ym,{data:f});if(u==="config"&&l==="auth")return $(tm,{session:r});if(u==="config"&&l==="security")return $(_m);return $(jl,{title:"未找到页面",text:"请选择左侧主模块和顶部子功能标签"})}function cm({session:u,onLogout:l}){let f=j2(Dr,window.location.pathname),[r,n]=bu(f.moduleId),[i,y]=bu({...st,[f.moduleId]:f.tabId}),[t,_]=bu({overview:null,nodes:[],systemStatuses:[],dockerStatuses:[],microservices:[],events:[],tasks:[],pendingTasks:[],schedules:[],scheduleRuns:[],logs:[]}),[c,A]=bu({ok:!1,text:"连接中"}),[j,F]=bu(null),[J,Q]=bu(new Date),[w,L]=bu(null),[U,N]=bu(!1),[q,W]=bu(!1),z=gn.default.useRef(!1),Z=Dr.moduleById[r]||Dr.modules[0],H=i[r]||st[r]||Z.tabs[0].id,E=Array.isArray(t.microservices)?t.microservices:[],D=E.length===0&&r==="apps"&&H==="code-queue"?[$p]:E,h=D===E?t:{...t,microservices:D},V=r==="apps"?D.find((o)=>String(o?.id||"")===(H==="v3sctl"?"v3sctl-adapter":H)):null,S=V?ZL(V):{},p=Z.tabs.find((o)=>o.id===H)?.label||H,O=V?[{key:"microservice",label:"用户服务",value:`${p} ${S.providerStatus==="online"?"在线":S.providerStatus||"未知"}`,tone:S.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,zu)=>{o.push([ju,Tu(zu)])},x=r==="ops"&&H==="status",lu=x||r==="config"&&H==="topology",_u=x||r==="nodes"||r==="tasks"&&(H==="dispatch"||H==="scheduled"),$u=r==="apps"&&H!=="code-queue";if(lu)g("overview",`${gu.apiBaseUrl}/overview`);if(_u)g("nodes",`${gu.apiBaseUrl}/nodes`);if(r==="nodes"&&H==="monitor")g("systemStatuses",`${gu.apiBaseUrl}/nodes/system-status?limit=60`),g("tasks",`${gu.apiBaseUrl}/tasks?limit=120&summary=1`);else if(r==="nodes"&&H==="docker")g("dockerStatuses",`${gu.apiBaseUrl}/nodes/docker-status`);else if(r==="nodes"&&H==="gateway")g("tasks",`${gu.apiBaseUrl}/tasks?limit=300&summary=1`);else if(r==="tasks"&&H==="scheduled")g("schedules",`${gu.apiBaseUrl}/schedules?limit=100`),g("scheduleRuns",`${gu.apiBaseUrl}/schedules/runs?limit=100`);else if(r==="tasks"&&H==="pending")g("pendingTasks",`${gu.apiBaseUrl}/tasks?status=pending&limit=100&summary=1`);else if(r==="tasks"&&(H==="history"||H==="results"))g("tasks",`${gu.apiBaseUrl}/tasks?limit=300&summary=1`);else if(x)g("tasks",`${gu.apiBaseUrl}/tasks?limit=8&lite=1`),g("pendingTasks",`${gu.apiBaseUrl}/tasks?status=pending&limit=20&lite=1`);if($u)g("microservices",`${gu.apiBaseUrl}/microservices`);if(r==="ops"&&H==="events")g("events",`${gu.apiBaseUrl}/events?limit=100`);if(r==="ops"&&H==="logs")g("logs","/logs?limit=100");await Promise.all(o.map(async([ju,zu])=>{let Wu=await zu,P={};if(ju==="overview")P.overview=Wu;if(ju==="nodes")P.nodes=Wu.nodes||[];if(ju==="systemStatuses")P.systemStatuses=Wu.systemStatuses||[];if(ju==="dockerStatuses")P.dockerStatuses=Wu.dockerStatuses||[];if(ju==="microservices")P.microservices=Wu.microservices||[];if(ju==="events")P.events=Wu.events||[];if(ju==="tasks")P.tasks=Wu.tasks||[];if(ju==="pendingTasks")P.pendingTasks=Wu.tasks||[];if(ju==="schedules")P.schedules=Wu.schedules||[];if(ju==="scheduleRuns")P.scheduleRuns=Wu.runs||[];if(ju==="logs")P.logs=Wu.logs||[];_((e)=>({...e,...P}))})),A({ok:!0,text:"核心在线"}),F(new Date)}catch(o){if(A({ok:!1,text:Ou(o,"连接失败")}),o.status===401)l(!1)}finally{z.current=!1,W(!1)}}J0(()=>{let o=()=>{if(!iL())return;m()};o();let g=setInterval(o,cp(r,H)),x=()=>{if(iL())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=dQ(Dr,window.location.pathname);if(o&&window.location.pathname!==o)window.history.replaceState(null,"",o)},[]),J0(()=>{let o=()=>{let g=j2(Dr,window.location.pathname);n(g.moduleId),y((x)=>({...x,[g.moduleId]:g.tabId})),L(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 lu=Dr.moduleById[o]?o:Dr.fallbackTarget.moduleId,_u=Dr.moduleById[lu]?.tabs.some((ju)=>ju.id===g)?g:st[lu]||Dr.moduleById[lu]?.tabs[0]?.id||Dr.fallbackTarget.tabId;n(lu),y((ju)=>({...ju,[lu]:_u}));let $u=yc(Dr,lu,_u);if(window.location.pathname!==$u){let ju=x==="replace"?"replaceState":"pushState";window.history[ju](null,"",$u)}}function v(o,g){L({title:o,data:g})}let[T,Y]=bu(!1),{unreadCount:k,notifications:I}=Xf(),b=I.length>0?I[I.length-1]:null;return $("div",{className:`shell ${U?"rail-collapsed":""}`,"data-testid":"app-shell"},$(zp,{activeModule:r,activeTabs:i,onNavigate:X,collapsed:U,onToggle:()=>N((o)=>!o)}),$("main",{className:"workspace"},$(Kp,{connection:c,lastRefresh:j,onRefresh:m,onLogout:()=>l(!0),session:u,clock:J,activeStatusItems:O,onNotificationToggle:()=>Y((o)=>!o),unreadCount:k}),$(Tp,{module:Z,activeTab:H,onNavigate:X}),$(n7.Provider,{value:q},$($m,{activeModule:r,activeTab:H,data:h,session:u,refresh:m,onRaw:v,onNavigate:X}))),$(wp,{raw:w,onClose:()=>L(null)}),b&&$(nL,{key:b.id,notification:b}),T&&$(rL,{onClose:()=>Y(!1)}))}function Am(){let[u,l]=bu(!0),[f,r]=bu(null);async function n(){l(!0);try{let y=await Tu("/api/session");r(y.authenticated?y:null)}catch{r(null)}finally{l(!1)}}async function i(y){if(y)try{await Tu("/logout",{method:"POST"})}catch{}r(null)}if(J0(()=>{n()},[]),u)return $("main",{className:"loading-screen"},$("div",{className:"brand-mark"},"UD"),$("span",null,"加载会话"));if(!f)return $(Lp,{onLogin:r});return $(UJ,null,$(cm,{session:f,onLogout:i}))}var XL=document.getElementById("root");if(XL===null)throw Error("root element not found");JL.createRoot(XL).render($(Am));})(); diff --git a/src/components/frontend/public/style.css b/src/components/frontend/public/style.css index 643e1c67..94f680af 100644 --- a/src/components/frontend/public/style.css +++ b/src/components/frontend/public/style.css @@ -6290,3 +6290,203 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent-2); } .notification-banner-dismiss:hover { background: rgba(255,255,255,0.3); } + +.v3s-page { + display: grid; + gap: 14px; +} +.v3s-hero-panel { + position: relative; + overflow: hidden; + border-color: rgba(215, 161, 58, 0.34); + background: + radial-gradient(circle at 88% 18%, rgba(215, 161, 58, 0.16), transparent 30%), + radial-gradient(circle at 12% 84%, rgba(78, 183, 168, 0.13), transparent 34%), + linear-gradient(135deg, rgba(255,255,255,0.045), rgba(255,255,255,0.012)); +} +.v3s-hero { + display: grid; + grid-template-columns: 128px minmax(0, 1fr); + align-items: center; + gap: 18px; + margin-bottom: 16px; +} +.v3s-orb { + position: relative; + display: grid; + place-items: center; + width: 118px; + height: 118px; + border: 1px solid rgba(215, 161, 58, 0.5); + border-radius: 999px; + background: + repeating-conic-gradient(from 12deg, rgba(215,161,58,0.22) 0 8deg, transparent 8deg 19deg), + radial-gradient(circle, rgba(78,183,168,0.22), rgba(0,0,0,0.18) 62%); + box-shadow: 0 0 34px rgba(78,183,168,0.18), inset 0 0 24px rgba(0,0,0,0.32); + text-transform: uppercase; + letter-spacing: 0.22em; + color: var(--accent); + font-weight: 800; +} +.v3s-orb::before, +.v3s-orb::after { + content: ""; + position: absolute; + inset: 12px; + border: 1px dashed rgba(78,183,168,0.38); + border-radius: inherit; +} +.v3s-orb::after { + inset: 28px; + border-style: solid; + border-color: rgba(255,255,255,0.12); +} +.v3s-hero-copy h2 { + max-width: 860px; + margin: 0 0 8px; + color: var(--text); + font-size: 22px; + line-height: 1.2; + letter-spacing: 0.08em; + text-transform: none; +} +.v3s-route-strip { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px; + margin-top: 12px; +} +.v3s-route-strip span { + padding: 5px 8px; + border: 1px solid rgba(215,161,58,0.5); + border-radius: 999px; + background: rgba(215,161,58,0.12); + color: var(--accent); + font-size: 10px; + font-weight: 800; + letter-spacing: 0.16em; +} +.v3s-route-strip code { + max-width: 100%; + padding: 5px 8px; + border: 1px solid var(--line-soft); + border-radius: 999px; + background: rgba(0,0,0,0.24); + color: var(--text); + overflow-wrap: anywhere; + white-space: normal; +} +.v3s-control-plane-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 8px; + margin-top: 12px; +} +.v3s-control-plane-card { + min-height: 96px; + padding: 12px; + border: 1px solid rgba(255,255,255,0.1); + background: linear-gradient(135deg, rgba(0,0,0,0.22), rgba(78,183,168,0.07)); +} +.v3s-control-plane-card span { + color: var(--muted); + font-size: 10px; + letter-spacing: 0.14em; + text-transform: uppercase; +} +.v3s-control-plane-card strong { + display: block; + margin-top: 8px; + color: var(--text); + font-size: 17px; + letter-spacing: 0.08em; +} +.v3s-control-plane-card p { + margin: 8px 0 0; + color: var(--muted); + font-size: 12px; + line-height: 1.45; + overflow-wrap: anywhere; +} +.v3s-service-panel { + border-color: rgba(78,183,168,0.25); +} +.v3s-service-summary { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 8px; + margin-bottom: 12px; +} +.v3s-service-summary > div, +.v3s-instance-card { + border: 1px solid var(--line-soft); + background: rgba(0,0,0,0.18); +} +.v3s-service-summary > div { + display: grid; + gap: 6px; + min-height: 66px; + padding: 10px; +} +.v3s-service-summary span, +.v3s-kv dt { + color: var(--muted); + font-size: 10px; + letter-spacing: 0.12em; + text-transform: uppercase; +} +.v3s-service-summary strong { + color: var(--text); + font-size: 18px; +} +.v3s-instance-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 10px; +} +.v3s-instance-card { + padding: 12px; + border-left: 3px solid rgba(78,183,168,0.7); +} +.v3s-instance-role { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + margin: 8px 0 10px; + color: var(--accent); + font-size: 11px; + letter-spacing: 0.15em; +} +.v3s-kv { + display: grid; + grid-template-columns: 76px minmax(0, 1fr); + gap: 6px 10px; + margin: 0; +} +.v3s-kv dd { + min-width: 0; + margin: 0; + color: var(--text); + overflow-wrap: anywhere; +} +.v3s-kv code { + white-space: normal; +} + +@media (max-width: 780px) { + .v3s-hero { + grid-template-columns: 1fr; + } + .v3s-orb { + width: 96px; + height: 96px; + } + .v3s-service-summary { + grid-template-columns: 1fr 1fr; + } + .v3s-control-plane-grid { + grid-template-columns: 1fr; + } +} diff --git a/src/components/frontend/src/app.tsx b/src/components/frontend/src/app.tsx index 1e11ae39..68feedc2 100644 --- a/src/components/frontend/src/app.tsx +++ b/src/components/frontend/src/app.tsx @@ -13,6 +13,7 @@ import { PipelinePage } from "./pipeline"; import { ProjectManagerPage } from "./project-manager"; import { TodoNotePage } from "./todo-note"; import { TopStatusBar } from "./top-status"; +import { V3sCtlPage } from "./v3sctl"; import { LoadingTitle } from "./loading-indicator"; import { errorMessage, requestJson } from "./unidesk-error"; import { UniDeskErrorBanner } from "./unidesk-error-banner"; @@ -44,14 +45,21 @@ const fastCodeQueueService = { name: "Code Queue", providerId: "D601", description: "Code Queue", - repository: { containerName: "code-queue-backend" }, + repository: { containerName: "v3s:code-queue" }, backend: { - nodeBaseUrl: "http://host.docker.internal:4222", - nodeBindHost: "127.0.0.1", + nodeBaseUrl: "v3s://code-queue", + nodeBindHost: "v3s://unidesk/code-queue", nodePort: 4222, + proxyMode: "v3sctl-adapter-http", public: false, }, + deployment: { + mode: "v3sctl-managed", + adapterServiceId: "v3sctl-adapter", + v3sServiceId: "code-queue", + }, runtime: { + orchestrator: "v3sctl", providerStatus: "loading", providerName: "D601", }, @@ -1640,6 +1648,7 @@ function MicroserviceCatalogPage({ microservices, onRaw, onNavigate }: AnyRecord service.id === "claudeqq" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "claudeqq"), "data-testid": "open-claudeqq-button" }, "打开") : null, service.id === "baidu-netdisk" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "baidu-netdisk"), "data-testid": "open-baidu-netdisk-button" }, "打开") : null, service.id === "oa-event-flow" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "oa-event-flow"), "data-testid": "open-oa-event-flow-button" }, "打开") : null, + service.id === "v3sctl-adapter" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "v3sctl"), "data-testid": "open-v3sctl-button" }, "打开") : null, service.id === "code-queue" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "code-queue"), "data-testid": "open-code-queue-button" }, "打开") : null, service.id === "project-manager" ? h("button", { type: "button", className: "ghost-btn", onClick: () => onNavigate("apps", "project-manager"), "data-testid": "open-project-manager-button" }, "打开") : null, h(RawButton, { title: `用户服务 ${service.id}`, data: service, onOpen: onRaw }), @@ -2146,6 +2155,7 @@ function WorkArea({ activeModule, activeTab, data, session, refresh, onRaw, onNa if (activeModule === "apps" && activeTab === "baidu-netdisk") return h(BaiduNetdiskPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl }); if (activeModule === "apps" && activeTab === "filebrowser") return h(FileBrowserPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl }); if (activeModule === "apps" && activeTab === "oa-event-flow") return h(OaEventFlowPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl }); + if (activeModule === "apps" && activeTab === "v3sctl") return h(V3sCtlPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl, onNavigate }); if (activeModule === "apps" && activeTab === "code-queue") return h(CodeQueuePage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl, initialTasksData: initialCodeQueueOverview }); if (activeModule === "apps" && activeTab === "project-manager") return h(ProjectManagerPage, { microservices: data.microservices, onRaw, apiBaseUrl: cfg.apiBaseUrl }); if (activeModule === "config" && activeTab === "topology") return h(TopologyPage, { data }); @@ -2175,7 +2185,7 @@ function Shell({ session, onLogout }: AnyRecord) { : microservices; const effectiveData = effectiveMicroservices === microservices ? data : { ...data, microservices: effectiveMicroservices }; const activeService = activeModule === "apps" - ? effectiveMicroservices.find((service: any) => String(service?.id || "") === activeTab) + ? effectiveMicroservices.find((service: any) => String(service?.id || "") === (activeTab === "v3sctl" ? "v3sctl-adapter" : activeTab)) : null; const activeServiceRuntime = activeService ? microserviceRuntime(activeService) : {}; const activeTabTitle = module.tabs.find((tab: any) => tab.id === activeTab)?.label || activeTab; diff --git a/src/components/frontend/src/code-queue-entry.tsx b/src/components/frontend/src/code-queue-entry.tsx index 20bb2965..da963ddf 100644 --- a/src/components/frontend/src/code-queue-entry.tsx +++ b/src/components/frontend/src/code-queue-entry.tsx @@ -30,15 +30,22 @@ const standaloneCodeQueueService = { id: "code-queue", name: "Code Queue", providerId: "D601", - description: "Code Queue 独立入口,使用 summary 首屏和按需全量加载保持信息完整。", - repository: { containerName: "code-queue-backend" }, + description: "Code Queue 独立入口,使用 v3sctl-adapter 单一路径访问 active service。", + repository: { containerName: "v3s:code-queue" }, backend: { - nodeBaseUrl: "http://host.docker.internal:4222", - nodeBindHost: "127.0.0.1", + nodeBaseUrl: "v3s://code-queue", + nodeBindHost: "v3s://unidesk/code-queue", nodePort: 4222, + proxyMode: "v3sctl-adapter-http", public: false, }, + deployment: { + mode: "v3sctl-managed", + adapterServiceId: "v3sctl-adapter", + v3sServiceId: "code-queue", + }, runtime: { + orchestrator: "v3sctl", providerStatus: "online", providerName: "D601", }, diff --git a/src/components/frontend/src/code-queue.tsx b/src/components/frontend/src/code-queue.tsx index 1cb40ab5..cda23150 100644 --- a/src/components/frontend/src/code-queue.tsx +++ b/src/components/frontend/src/code-queue.tsx @@ -148,7 +148,7 @@ function microserviceBackend(service: any): AnyRecord { } function codexApi(apiBaseUrl: string, path: string): string { - return `${apiBaseUrl}/code-queue-direct${path}`; + return `${apiBaseUrl}/microservices/code-queue/proxy${path}`; } function oaCodeQueueEventsApi(apiBaseUrl: string): string { diff --git a/src/components/frontend/src/index.ts b/src/components/frontend/src/index.ts index 4c431ffd..a7e234a6 100644 --- a/src/components/frontend/src/index.ts +++ b/src/components/frontend/src/index.ts @@ -66,58 +66,6 @@ const baiduNetdiskDocsFallbackLinks = [ { href: "/docs/reference/deployment.md", section: "配置与文档 DEPLOY", label: "UniDesk 部署与重建流程" }, { href: "/docs/reference/cli.md", section: "配置与文档 CLI", label: "UniDesk CLI 验证命令" }, ]; -const codeQueueOverviewCache = new Map(); -const codeQueueOverviewRefreshes = new Map>(); -const codeQueueOverviewCacheTtlMs = 10_000; -const defaultCodeQueueOverviewPath = "/api/tasks/overview?limit=24&transcriptLimit=3&compact=1&afterSeq=0&preferId="; - -function codeQueueOverviewCacheKey(pathWithQuery: string): string { - return pathWithQuery; -} - -function cachedCodeQueueOverview(pathWithQuery: string, maxAgeMs = codeQueueOverviewCacheTtlMs): { payload: JsonValue; text: string } | null { - const cached = codeQueueOverviewCache.get(codeQueueOverviewCacheKey(pathWithQuery)); - if (!cached || Date.now() - cached.at > maxAgeMs) return null; - return { payload: cached.payload, text: cached.text }; -} - -function invalidateCodeQueueOverviewCache(): void { - codeQueueOverviewCache.clear(); -} - -async function refreshCodeQueueOverview(pathWithQuery: string, timeoutMs = 800): Promise { - const existing = codeQueueOverviewRefreshes.get(pathWithQuery); - if (existing !== undefined) return existing; - const refresh = refreshCodeQueueOverviewUncached(pathWithQuery, timeoutMs) - .finally(() => { - codeQueueOverviewRefreshes.delete(pathWithQuery); - }); - codeQueueOverviewRefreshes.set(pathWithQuery, refresh); - return refresh; -} - -async function refreshCodeQueueOverviewUncached(pathWithQuery: string, timeoutMs = 800): Promise { - const started = performance.now(); - try { - 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" }, - }); - const text = await response.text(); - const payload = text ? JSON.parse(text) as unknown : null; - const ok = response.ok && typeof payload === "object" && payload !== null; - recordOperationPerformance("frontend", "code_queue_initial_overview", performance.now() - started, ok, pathWithQuery); - if (!ok) return null; - codeQueueOverviewCache.set(codeQueueOverviewCacheKey(pathWithQuery), { at: Date.now(), payload: payload as JsonValue, text }); - return payload as JsonValue; - } catch (error) { - const message = error instanceof Error ? error.message : String(error); - recordOperationPerformance("frontend", "code_queue_initial_overview", performance.now() - started, false, message); - return null; - } -} - function renderIndexHtml(extraRootAttributes = ""): string { const docsFallback = `