diff --git a/docker-compose.yml b/docker-compose.yml index 837a4d0a..a3b3284a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -115,7 +115,7 @@ services: HOST: "0.0.0.0" PORT: "4222" DATABASE_URL: "postgres://${UNIDESK_DATABASE_USER}:${UNIDESK_DATABASE_PASSWORD}@database:5432/${UNIDESK_DATABASE_NAME}" - CODEX_QUEUE_STATE_PATH: "/var/lib/unidesk/codex-queue/state.json" + CODEX_QUEUE_DATA_DIR: "/var/lib/unidesk/codex-queue" CODEX_QUEUE_WORKDIR: "/root/unidesk" CODEX_QUEUE_CODEX_HOME: "/var/lib/unidesk/codex-queue/codex-home" CODEX_QUEUE_SOURCE_CODEX_CONFIG: "/root/.codex/config.toml" diff --git a/docs/reference/arch.md b/docs/reference/arch.md index 813275db..890888ee 100644 --- a/docs/reference/arch.md +++ b/docs/reference/arch.md @@ -26,6 +26,10 @@ - Includes frontend gateway, task scheduler, project management, provider ingress, and other stateless modules - Instances can scale horizontally; failure recovery requires no state synchronization - Only the frontend gateway and provider ingress are public; core REST APIs and PostgreSQL remain on the Docker internal network + - Frontend Time Zone Policy + - All UniDesk frontend timestamps, dates, clocks, update times, heartbeat times, Trace times, Gantt axis labels, export date stamps, and `datetime-local` values must render as Beijing time. + - Beijing time means IANA timezone `Asia/Shanghai` / UTC+8, regardless of the browser timezone, host system timezone, container timezone, or server-side `project.timezone` value. + - Frontend code must use the shared formatter and input conversion helpers in `src/components/frontend/src/time.ts`; raw ISO/UTC timestamps may appear only inside explicitly opened raw JSON views. - PostgreSQL Database - Deployed as a Docker container with a 10 GB named volume - Stores all task metadata, node heartbeats, resource labels, and business state diff --git a/docs/reference/deployment.md b/docs/reference/deployment.md index 021706ff..673a5fd5 100644 --- a/docs/reference/deployment.md +++ b/docs/reference/deployment.md @@ -9,7 +9,7 @@ - `frontend` 是唯一公开 Web 控制台,提供登录、从 TSX 转译出的 React 应用资产和到 backend-core 的同源代理。 - `provider-gateway` 是当前主 server 的本机计算节点代理,通过 WebSocket 主动连到 provider ingress,挂载 `/var/run/docker.sock` 作为自动任务执行主路径,使用 `pid: "host"` 读取节点级进程资源,并周期性上报系统资源指标、进程占用与 Docker daemon 状态;维护用 Host SSH / WSL SSH 私钥目录只读挂载到 `/run/host-ssh`,不得作为自动任务调度主路径。 - `todo-note` 是主 server 承载的 Todo Note 纯后端用户服务,容器名 `todo-note-backend`,只在 Compose 内网暴露 `4211/tcp`,使用主 PostgreSQL 存储迁移后的 Todo Note 数据。 -- `codex-queue` 是主 server 承载的 Codex app-server 队列用户服务,容器名 `codex-queue-backend`,仅在 Compose 内网暴露 `4222/tcp` 给本机 provider-gateway 私有代理访问,任务状态优先写入主 PostgreSQL 并保留 `.state/codex-queue/state.json` fallback 快照,浏览器只能通过 UniDesk frontend 同源代理查看运行输出、追加 prompt、打断和重试。 +- `codex-queue` 是主 server 承载的 Codex app-server 队列用户服务,容器名 `codex-queue-backend`,仅在 Compose 内网暴露 `4222/tcp` 给本机 provider-gateway 私有代理访问,任务、queue、未读状态、控制状态和通知 outbox 一律写入主 PostgreSQL,不保留本地状态文件 fallback,浏览器只能通过 UniDesk frontend 同源代理查看运行输出、追加 prompt、打断和重试。 - `project-manager` 是主 server 承载的项目管理用户服务,容器名 `project-manager-backend`,仅在 Compose 内网暴露 `4233/tcp`,项目清单写入主 PostgreSQL,浏览器只能通过 UniDesk frontend 同源代理执行增删改查、Excel 导入和 Excel 导出。 ## Public Exposure Boundary diff --git a/docs/reference/e2e.md b/docs/reference/e2e.md index c1ab4428..c4d021fc 100644 --- a/docs/reference/e2e.md +++ b/docs/reference/e2e.md @@ -40,7 +40,7 @@ Typical targeted commands: - 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`、`用户服务 / Codex Queue`、`用户服务 / FindJob`、`用户服务 / Pipeline` and `用户服务 / MET Nonlinear` to verify 主 server Todo Note/Codex Queue、D601、仓库引用、私有后端映射、Todo Note 迁移清单和树形任务、Codex 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/codex-queue/` 验证页面存在 `app-shell`、左侧主模块边栏、顶部状态栏、顶部子标签和 `codex-queue-page`,防止用户服务 deep link 退化成缺 shell 的 standalone 页面;同时 `态势总览` 这类非用户服务页面应落在自己的模块前缀下,例如 `/ops/status/`。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`、`用户服务 / Codex Queue`、`用户服务 / FindJob`、`用户服务 / Pipeline` and `用户服务 / MET Nonlinear` to verify 主 server Todo Note/Codex Queue、D601、仓库引用、私有后端映射、Todo Note 迁移清单和树形任务、Codex 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/codex-queue/` 验证页面存在 `app-shell`、左侧主模块边栏、顶部状态栏、顶部子标签和 `codex-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 Codex 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 Codex 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 Codex 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. diff --git a/docs/reference/frontend.md b/docs/reference/frontend.md index 000751d6..4b50b669 100644 --- a/docs/reference/frontend.md +++ b/docs/reference/frontend.md @@ -8,6 +8,10 @@ frontend 应用源码必须使用 TypeScript + React,禁止在 `src/components `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 消息网关工作台,`codex-queue.tsx` 承载 Codex Queue 控制台;新增用户服务也必须按同样规则新增独立页面模块,并由 `app.tsx` 只做导入和路由分发。 +## Time Zone Contract + +frontend 所有默认可见的时间、日期、时钟、更新时间、心跳时间、Trace 时间、Gantt 时间轴刻度、导出文件日期和 `datetime-local` 输入值都必须按北京时间显示,即使用 IANA 时区 `Asia/Shanghai` / UTC+8。禁止依赖浏览器本地时区、服务器系统时区或裸 `Date.toLocaleString()` 默认值;新增页面必须复用 `src/components/frontend/src/time.ts` 的统一格式化和输入转换函数。原始 JSON 中的 ISO 时间戳只能在用户显式点击 `查看原始JSON` 后作为原始数据出现,默认结构化控件不得把 UTC/本地时区混入北京时间显示。 + ## Layout 左侧边栏只切换主模块:运行总览、资源节点、任务调度、用户服务、系统配置。顶部标签只切换当前主模块内的子功能;例如资源节点下的节点清单、资源标签、心跳状态只属于资源节点,用户服务下的服务目录、Todo Note、FindJob、Pipeline、MET Nonlinear、Codex Queue 只属于用户服务,和运行总览、任务调度、系统配置没有重复或共享语义。桌面端左侧边栏必须支持收起,只保留模块 code 和展开按钮,以便最大化主面板空间;移动端左侧边栏会转为顶部横向主模块条,但高度必须在不同主模块之间保持一致,并保持窄条、单行、不换行;主内容区无论内容多少都必须从顶部向下排列,空状态也不得上下居中制造大块留白。 @@ -65,7 +69,9 @@ frontend shell 必须把左侧主模块与顶部子标签编译为统一的 URL - `Todo Note` 子标签必须把主 server `todo-note-backend` 后端渲染为 UniDesk React 控件,包括迁移清单、树形任务、筛选、提醒、拖放/移动、撤销/重做、字号控制和显式原始 JSON 按钮。 - `FindJob` 子标签必须把 D601 findjob 后端渲染为 UniDesk React 控件,包括岗位指标、岗位预览、草稿报告和显式原始 JSON 按钮。 - `ClaudeQQ` 子标签必须把 D601 ClaudeQQ 后端渲染为 UniDesk React 控件,包括 NapCat 容器登录二维码、NapCat HTTP/WS 状态、事件缓存、QQ 事件订阅表、订阅创建表单、消息推送表单、主用户私聊账号 `645275593` 标记、最近 QQ 事件、已发送记录和显式原始 JSON 按钮。 - - `Codex Queue` 子标签必须把主 server `codex-queue-backend` 后端渲染为 UniDesk React 控件,包括多 queue lane、queue 内串行、queue 间并行、任务 ID/复制任务 ID、引用按钮、任务耗时、任务提交/批量提交、引用任务 ID、创建成功提示、清空输入、模型下拉、显式入队份数、默认模型 `gpt-5.5`、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、运行中追加 prompt、打断、手动重试和显式原始 JSON 按钮;Codex CLI-like 输出流必须始终保留任务的初始 `Submitted prompt` 和运行中 `Steer prompt`;整个 agent loop 消息流统一命名为专有名词 `Trace`,`Trace` 包含 assistant message、user prompt、system event 和 tool call;Codex 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”也必须从 Codex Queue output archive 分页补齐早期 trace,不得把 preview 的 `hasMore=false` 当成完整历史;即使热状态为控制体积裁剪了早期 raw output,也要从结构化 `basePrompt/displayPrompt/promptHistory` 和 archive 合成完整用户输入与 agent trace,并且初始 prompt 默认显示注入前 prompt 而不是引用注入全文;当初始 prompt 含引用注入时,引用内容必须默认折叠,但必须在初始消息和 Prompt 全量面板提供可展开的“最终传入 Codex 的真实完整 prompt”;多轮引用注入必须按上游/最早上下文在前、直接引用在后的顺序排列,每一轮必须有明确 `Reference Round N/M` 分割线和时间范围,不能用固定 6 轮截断引用链;点击队列引用按钮必须自动把该任务 ID 写入提交表单的引用输入框,引用任务 ID 创建新任务时必须自动注入 `bun scripts/cli.ts codex task ` 的提示;连续执行同一 prompt 应通过入队份数一次性生成多条任务,避免快速连点造成操作员误判。 + - `Codex Queue` 子标签必须把主 server `codex-queue-backend` 后端渲染为 UniDesk React 控件,包括多 queue lane、queue 内串行、queue 间并行、任务 ID/复制任务 ID、引用按钮、任务耗时、任务提交/批量提交、引用任务 ID、创建成功提示、清空输入、模型下拉、显式入队份数、默认模型 `gpt-5.5`、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、运行中追加 prompt、打断、手动重试和显式原始 JSON 按钮;Codex CLI-like 输出流必须始终保留任务的初始 `Submitted prompt` 和运行中 `Steer prompt`;整个 agent loop 消息流统一命名为专有名词 `Trace`,`Trace` 包含 assistant message、user prompt、system event 和 tool call;Codex 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”也必须从 Codex 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 应通过入队份数一次性生成多条任务,避免快速连点造成操作员误判。 + - `Codex Queue` 前端改进必须在同一任务内重建并上线公网 frontend,不能只修改源码或本地 bundle;重建 frontend 是无状态 WebUI 替换,不会导致 Codex Queue 长期任务失败。已结束未读任务只能在 task card 边角显示类似未读消息的 `codex-unread-badge` 圆点和“标为已读”操作,不得把整张卡片改成红色/琥珀色失败态边框、背景或胶囊标签;状态栏的“结束未读”提示也不得使用失败态红色。 + - `Codex Queue` 前端必须把 PostgreSQL-backed backend API 作为 task、queue、readAt/未读状态和 attempt 状态的唯一数据来源;不得用 `localStorage`、`sessionStorage` 或 IndexedDB 持久化这些业务状态,也不得在后端标记已读失败时伪造本地成功。前端允许保留 React 内存态、请求 in-flight guard 和本轮页面缓存,但刷新页面或切换设备后的状态必须完全由后端 PostgreSQL 数据恢复。 - `Codex Queue` 的 queue/session 左侧边栏必须采用顶部对齐和内容高度优先布局:列表、分组和 task card 都不得用居中、space-between、stretch 或隐式等高网格去拉满侧栏高度;item 少时允许下半部分留空,不能把单个 item 拉高来铺满。提交任务时必须立即锁定 prompt、引用 ID、queue、模型、工作目录、最大尝试和入队份数等输入控件,显示等待状态,并用前端 in-flight guard 阻止重复点击造成重复入队;当解析到多个待入队任务时必须显式要求用户勾选批量确认,防止 `---` 分隔或入队份数误操作导致错误传入多个任务。Trace 面板的主滚动条使用全站细窄现代滚动条;工具调用块内部的横向滚动必须可滚动但隐藏横向滚动条,避免移动端阅读被滚动条占用。公共 `TraceView` 的自动滚动必须采用 follow-tail 语义:只有当前滚动位置在底部附近时才跟随新增输出;用户手动向上滚动后立即暂停自动滚动,异步刷新不得把视图拉回底部,直到用户再次滚动到最底部才恢复自动跟随。 - 用户服务页面不得 iframe 业务旧前端、Todo Note 原 Vite 前端或 Pipeline 自身 WebUI,不得把用户服务后端端口暴露为浏览器直连 URL,也不得把业务 API 的 JSON 裸铺在页面上。 - `Pipeline` 子标签是 D601 `/home/ubuntu/pipeline` 的 UniDesk host UI。 diff --git a/docs/reference/microservices.md b/docs/reference/microservices.md index 2f85f8ed..64dfef2f 100644 --- a/docs/reference/microservices.md +++ b/docs/reference/microservices.md @@ -30,7 +30,7 @@ UniDesk 用户服务是挂载到 UniDesk 核心服务上的、面向用户使用 ## Main Server User Services -主 server 只承载对统一入口、状态迁移或控制面自动化有明确必要的用户服务。该类服务仍遵守不暴露公网端口、前端统一 React 控件化展示的规则;业务持久状态优先写入主 PostgreSQL,控制队列这类运行态可使用 `.state/` 文件并必须提供 `/logs` 与结构化状态端点。 +主 server 只承载对统一入口、状态迁移或控制面自动化有明确必要的用户服务。该类服务仍遵守不暴露公网端口、前端统一 React 控件化展示的规则;业务持久状态必须写入主 PostgreSQL;`.state/` 只能保存日志归档、缓存或可重建工件,不能作为任务、队列、未读、通知 outbox 等权威状态来源。 ### Todo Note On Main Server @@ -72,18 +72,19 @@ Project Manager 在 UniDesk 语境中按纯后端服务管理:不得将 `4233` - Provider:`main-server`,由本机 provider-gateway 通过 `microservice.http` 访问同一 Compose 网络内的 `http://codex-queue:4222`。 - 代码引用:`https://github.com/pikasTech/unidesk` 与配置中的 `repository.commitId`;服务源码位于 `src/components/microservices/codex-queue`,属于 UniDesk 自有控制面组件。 - 部署引用:UniDesk 根仓库 `docker-compose.yml` 中的 `codex-queue` service,Dockerfile 为 `src/components/microservices/codex-queue/Dockerfile`,容器名为 `codex-queue-backend`。 +- 上线纪律:Codex Queue 相关的前端或后端改进必须在同一任务内正式上线并验证公网 frontend 或 live API,不能只停留在源码、构建产物或“后续再上线”。重建 `frontend` 只替换无状态 WebUI 容器,不会触碰 `codex-queue-backend`、PostgreSQL 队列或运行中 Codex thread,不能以“可能影响长期任务”为由延迟前端上线;`codex-queue-backend` 本身带有 restart-recovery,允许按 `server rebuild codex-queue` 或 Compose 重启/替换,停止、重启或重建后必须从持久化状态恢复运行中和排队任务。 - Codex 认证:容器只从主 server 的 `/root/.codex/config.toml` 同步 Codex provider 配置到 `.state/codex-queue/codex-home`,并通过运行时环境透传 `OPENAI_API_KEY`、`CRS_OAI_KEY` 等 provider 所需变量;这些 provider 环境变量必须由 `writeComposeEnv` 写入 `.state/docker-compose.env` 并由 Compose 注入,确保 `server rebuild codex-queue` 的外部 Docker job runner、自重建和容器重启后不会丢失认证。新增 provider 的 `env_key` 时必须增加同类运行时透传和 Compose env 持久化,禁止把 Codex 或 MiniMax 密钥写入仓库文件。Codex Queue 开发容器必须只读挂载 host 的 root SSH 目录到 `/root/.ssh`(默认 `${UNIDESK_HOST_ROOT_SSH_DIR:-/root/.ssh}`),让容器内 `git push`、`ssh -T git@github.com` 与 host 使用同一套 GitHub SSH key/known_hosts;不得把私钥复制进镜像或仓库。 - Develop-ready 镜像:Codex Queue 镜像必须在启动前预装 UniDesk/Pipeline 调试所需工具,至少包含 `codex`、`bun`、`node`、`npm`/`npx`、`git`、`rg`、`curl`、`python3`/`pip3`、`docker`、`docker compose`、`docker-compose`、`jq`、`ssh`、`rsync`、`make`、`gcc`/`g++`、`tar`、`gzip` 和 `unzip`;不得依赖 Codex 任务运行时再 `apt-get install` 这些基础环境。 - 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 `。`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 必须自动重新调度。 -- 稳定性与重启恢复:Codex Queue 的第一目标是长期稳定可用;部署修复或运维排障时不得因为担心容器重启会打断任务而拒绝重启、重建或替换 `codex-queue-backend`。容器重启、服务进程重启和镜像替换后,队列、`promptHistory`、running/judging/retry_wait 任务和 active session 元数据必须从 PostgreSQL 与 fallback 快照恢复,并在已有 `codexThreadId` 可用时用 `thread/resume` 和 continuation prompt 无缝继续当前任务;如果原 app-server turn 已丢失,也必须把当前任务恢复到可 retry/continue 的状态,不能错误推进下一个任务或永久卡住。主 server 侧重建必须走 `server rebuild codex-queue`,该 job 受 `.state/locks/server-compose.lock` 串行化约束,并且必须在 build 后执行 no-deps force-recreate 与 post-up health validation;禁止在 job 中先手工 `docker rm` 再依赖后续命令补救,因为中断窗口会让容器消失并触发 frontend `direct microservice proxy failed`。重启后出现 active task 丢失、手动 steer/interrupt 记录丢失、running 任务卡死、误判完成、跳过当前任务、容器消失或阻塞队列,均属于 Codex Queue 的 P0 核心缺陷,必须先修复并补充 restart-recovery 验收,不能把“避免重启”作为交付策略。 -- 完成判定:app-server `turn/completed` 的 `turn.status=completed|interrupted|failed` 只代表 Codex turn 已结束;即使 `completed` 也必须把原始任务、assistant 最终回复、command/file-change 事件、stderr tail 和 recent events 组成 execution record 交给 judge 判断是否真的完成。配置了 `UNIDESK_CODEX_QUEUE_MINIMAX_API_KEY` 时使用 MiniMax `MiniMax-M2.7` 判定 `complete|retry|fail`,否则使用 fallback 规则。MiniMax 返回必须先做 JSON 去噪,支持去除 Markdown fence、`json` 标签和从夹杂文本中提取平衡 JSON object;如果去噪后仍无法解析,服务必须把解析错误和上一轮去噪前原始回答反馈给 MiniMax 做 JSON repair 重试,重试次数由 `UNIDESK_CODEX_QUEUE_MINIMAX_JUDGE_REPAIR_ATTEMPTS` 控制,默认 `2`,耗尽后才进入 fallback,并在 fallback 原因中保留 MiniMax 失败信息。 -- Retry/推进语义:`retry` 不是新开一个独立任务或完全新 session;只要已有 `codexThreadId`,服务必须 `thread/resume` 原 thread 并 append 一个继续执行 prompt。只有 judge 判定 `complete` 后,队列 worker 才把当前任务标为成功并推进下一个 queued/retry_wait 任务。 -- Judge 探针:`GET|POST /api/judge/probe` 使用同一套 judge 逻辑跑内置 synthetic execution records,覆盖正常完成、正常结束但只给计划、传输中断和用户打断四类样本,返回 `hits`、`total`、`hitRate`、每例 `expected` 与 `decision`;该接口不得回显 MiniMax API key。 +- 稳定性与重启恢复:Codex Queue 的第一目标是长期稳定可用;部署修复或运维排障时不得因为担心容器重启会打断任务而拒绝重启、重建或替换 `codex-queue-backend`。容器重启、服务进程重启和镜像替换后,队列、`promptHistory`、running/judging/retry_wait 任务和 active session 元数据必须从 PostgreSQL 恢复,并在已有 `codexThreadId` 可用时用 `thread/resume` 和 continuation prompt 无缝继续当前任务;如果原 app-server turn 已丢失,也必须把当前任务恢复到可 retry/continue 的状态,不能错误推进下一个任务或永久卡住。主 server 侧重建必须走 `server rebuild codex-queue`,该 job 受 `.state/locks/server-compose.lock` 串行化约束,并且必须在 build 后执行 no-deps force-recreate 与 post-up health validation;禁止在 job 中先手工 `docker rm` 再依赖后续命令补救,因为中断窗口会让容器消失并触发 frontend `direct microservice proxy failed`。重启后出现 active task 丢失、手动 steer/interrupt 记录丢失、running 任务卡死、误判完成、跳过当前任务、容器消失或阻塞队列,均属于 Codex Queue 的 P0 核心缺陷,必须先修复并补充 restart-recovery 验收,不能把“避免重启”作为交付策略。 +- 完成判定:app-server `turn/completed` 的 `turn.status=completed|interrupted|failed` 只代表 Codex turn 已结束;即使 `completed` 也必须把原始任务、assistant 最终回复、command/file-change 事件、stderr tail 和 recent events 组成 execution record 交给 judge 判断是否真的完成。配置了 `UNIDESK_CODEX_QUEUE_MINIMAX_API_KEY` 且 MiniMax 可用时,MiniMax `MiniMax-M2.7` 对 `complete|retry|fail` 的判定是权威结果;任何非 LLM 判断,包括字符串匹配、正则、硬编码 safety override,都不得覆盖、降级或提升一次成功的 MiniMax 判定。非 LLM/fallback 判断只允许在 MiniMax 未配置、额度/限流/网络/超时不可用,或 JSON 去噪与 repair 全部耗尽后启用。MiniMax 返回必须先做 JSON 去噪,支持去除 Markdown fence、`json` 标签和从夹杂文本中提取平衡 JSON object;如果去噪后仍无法解析,服务必须把解析错误和上一轮去噪前原始回答反馈给 MiniMax 做 JSON repair 重试,重试次数由 `UNIDESK_CODEX_QUEUE_MINIMAX_JUDGE_REPAIR_ATTEMPTS` 控制,默认 `2`,耗尽后才进入 fallback,并在 fallback 原因中保留 MiniMax 失败信息。 +- Retry/推进语义:`retry` 不是新开一个独立任务或完全新 session;只要已有 `codexThreadId`,服务必须 `thread/resume` 原 thread 并 append 一个继续执行 prompt。continuation/judge feedback prompt 只应携带本轮缺口、恢复原因、验收要求和有界原始任务摘要,禁止重新注入完整引用上下文、历史 transcript 或长 JSON;服务重启恢复类 feedback 尤其必须保持短 prompt,依赖现有 thread 上文继续。只有 judge 判定 `complete` 后,队列 worker 才把当前任务标为成功并推进下一个 queued/retry_wait 任务。非 LLM/fallback 判定产生的 `retry` 最多累计 `3` 次;达到上限后当前任务必须转为 `failed` 并记录原因,worker 继续推进后续 queued/retry_wait 任务,避免 fallback safety override 或硬编码判断造成无限循环。 +- Judge 探针:`GET|POST /api/judge/probe` 使用同一套 judge 逻辑跑内置 synthetic execution records,覆盖正常完成、正常结束但只给计划、未上线/未部署的服务或 WebUI 改动、传输中断和用户打断等样本,返回 `hits`、`total`、`hitRate`、每例 `expected` 与 `decision`;该接口不得回显 MiniMax API key。 - 模型选择:默认 Codex 模型是 `gpt-5.5`,内置模型队列包含 `gpt-5.5`、`gpt-5.4-mini`、`gpt-5.4`;`gpt-5.5` 的默认 reasoning effort 必须是 `xhigh`,可通过 `CODEX_QUEUE_MODEL_REASONING_EFFORTS` 追加或覆盖模型级默认值;每个入队任务可通过前端模型下拉菜单或 API 覆盖 `model`、`cwd`、`reasoningEffort` 和 `maxAttempts`,`maxAttempts` 上限为 `99`。Judge 判定 `retry` 或非用户取消类 `fail` 时必须继续已有 `codexThreadId`,不能新建 session;重试间隔使用指数退避,从 `1s` 开始,最大 `10min`。429、Too Many Requests、exceeded retry limit、overloaded、stream disconnected 等服务/限流错误一律判定为 `retry`,不能当作完成。 -- 状态与日志:默认工作目录为容器内 `/root/unidesk`,该路径映射主 server 的 `~/unidesk`;同时保留 `/workspace` 映射以兼容历史任务。队列任务的权威持久化优先写入主 PostgreSQL 表 `unidesk_codex_queue_tasks`,包含状态索引字段和 task 热状态;`.state/codex-queue/state.json` 仅作为本地恢复快照和 PostgreSQL 不可用时的 fallback,服务启动时必须合并 PG 与文件快照并把 running/judging 任务恢复为 retry_wait。Codex CLI-like output/Trace 的完整记录必须同步写入 `.state/codex-queue/output-archive/*.jsonl`,`/api/tasks//transcript` 与 `/api/tasks//output` 必须从 archive 分页重建完整历史,不得因为热状态裁剪而丢失早期 trace;热 task JSON 只保留可配置窗口(默认 600 条 output、400 条 event)以保证 `/health`、`/api/tasks` 和 PostgreSQL flush 不被长任务拖死。WebUI 必须支持多 queue 查看、显式创建 queue、提交时下拉选择 queue,并支持把已创建且非 active 的任务移动到其他 queue;queue 内串行,queue 间并行。Codex Queue 镜像必须内置 Playwright Chromium 浏览器与系统依赖,保证队列任务能直接执行公网 frontend Playwright 回归,不得只在宿主机临时安装。日志写入 UniDesk `logs/{YYYYMMDD}/..._codex-queue.jsonl`,`/logs` 端点返回最近结构化日志。`/health` 的 `queue.storage`、`queue.devReady` 和 `/api/dev-ready` 必须暴露 PostgreSQL 是否已配置/可用、develop-ready 自检、必需工具、Docker socket、`docker compose`、默认工作目录、Codex config 状态和 `/root/.ssh` 共享 SSH key 状态。Codex CLI-like 输出可能很大,服务必须节流状态持久化,禁止对每个 output delta 同步重写完整 state 导致 `/health` 和控制 API 卡死;容器 healthcheck 必须使用带超时的 HTTP 探针,不能留下堆积的无超时探针进程。 -- ClaudeQQ 通知:Codex Queue 可通过 backend-core 的 `claudeqq` 用户服务代理调用 `POST /api/push/text`,在每个任务进入 `succeeded`、`failed` 或 `canceled` 终态后向配置目标发送最终 response,并附带 task id、queue、状态、模型、attempt、当前 running/queued/retry_wait 数和任务总耗时;当所有 queue 进入 `0 running / 0 queued` 空闲态时,必须单独发送一次空闲提醒。通知由 `CODEX_QUEUE_NOTIFY_CLAUDEQQ_ENABLED` 控制,目标由 `CODEX_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE=private|group`、`CODEX_QUEUE_NOTIFY_CLAUDEQQ_USER_ID`、`CODEX_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID` 配置,默认私聊 `645275593`;代理基址、最终 response 最大字符数、单次超时和发送尝试次数分别由 `CODEX_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL`、`CODEX_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS`、`CODEX_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS` 和 `CODEX_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS` 配置。通知必须异步发送,失败或重试只能写 warn 日志,不能阻塞队列继续推进;`/health` 的 `queue.notifications.claudeqq` 必须暴露非敏感配置与是否已配置目标。 +- 状态与日志:默认工作目录为容器内 `/root/unidesk`,该路径映射主 server 的 `~/unidesk`;同时保留 `/workspace` 映射以兼容历史任务。Codex Queue 的任务、queue、`readAt`/未读状态、attempt、judge、`promptHistory`、active session 元数据、控制状态和 ClaudeQQ 通知 outbox 一律以主 PostgreSQL 为权威,分别写入 `unidesk_codex_queue_tasks`、`unidesk_codex_queue_queues` 与 `unidesk_codex_queue_notifications`;`DATABASE_URL` 是必需配置,服务不得在 PostgreSQL 缺失或不可用时进入文件存储模式。`.state/codex-queue/state.json` 不再作为任务或 queue 状态存储,不得重新引入本地 JSON fallback;服务启动必须以 PostgreSQL 为唯一来源恢复队列,并把 running/judging 任务恢复为 retry_wait。WebUI 不得用 browser `localStorage`、`sessionStorage` 或 IndexedDB 持久化 task/queue/readAt/unread 等业务状态;浏览器只能保留临时 UI 内存缓存,刷新后必须重新从后端读取 PostgreSQL 权威数据。Codex CLI-like output/Trace 的完整记录可以使用 append-only 文件作为日志型归档,但任务状态、未读状态和列表摘要不得依赖这些文件作为权威来源;`/api/tasks//transcript` 与 `/api/tasks//output` 必须能分页重建完整历史,不得因为热状态裁剪而丢失早期 trace。热 task JSON 只保留可配置窗口(默认 600 条 output、400 条 event)以保证 `/health`、`/api/tasks` 和 PostgreSQL flush 不被长任务拖死。WebUI 必须支持多 queue 查看、显式创建 queue、提交时下拉选择 queue,并支持把已创建且非 active 的任务移动到其他 queue;queue 内串行,queue 间并行。Codex Queue 镜像必须内置 Playwright Chromium 浏览器与系统依赖,保证队列任务能直接执行公网 frontend Playwright 回归,不得只在宿主机临时安装。日志写入 UniDesk `logs/{YYYYMMDD}/..._codex-queue.jsonl`,`/logs` 端点返回最近结构化日志。`/health` 的 `queue.storage.primary` 必须恒为 `postgres`,并通过 `queue.storage.postgresReady`、`queue.devReady` 和 `/api/dev-ready` 暴露 PostgreSQL 可用性、develop-ready 自检、必需工具、Docker socket、`docker compose`、默认工作目录、Codex config 状态和 `/root/.ssh` 共享 SSH key 状态。Codex CLI-like 输出可能很大,服务必须节流状态持久化,禁止对每个 output delta 同步重写完整 state 导致 `/health` 和控制 API 卡死;容器 healthcheck 必须使用带超时的 HTTP 探针,不能留下堆积的无超时探针进程。 +- ClaudeQQ 通知:Codex Queue 可通过 backend-core 的 `claudeqq` 用户服务代理调用 `POST /api/push/text`,在每个任务进入 `succeeded`、`failed` 或 `canceled` 终态后向配置目标发送最终 response,并附带 task id、queue、状态、模型、attempt、当前 running/queued/retry_wait 数和任务总耗时;当所有 queue 进入 `0 running / 0 queued` 空闲态时,必须单独发送一次空闲提醒。通知由 `CODEX_QUEUE_NOTIFY_CLAUDEQQ_ENABLED` 控制,目标由 `CODEX_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE=private|group`、`CODEX_QUEUE_NOTIFY_CLAUDEQQ_USER_ID`、`CODEX_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID` 配置,默认私聊 `645275593`;代理基址、最终 response 最大字符数、单次超时和发送尝试次数分别由 `CODEX_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL`、`CODEX_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS`、`CODEX_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS` 和 `CODEX_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS` 配置。任务终态和队列空闲通知必须先写入 PostgreSQL outbox 表 `unidesk_codex_queue_notifications` 再异步发送;不得使用 `.state/codex-queue/claudeqq-notifications.json`、`CODEX_QUEUE_NOTIFY_CLAUDEQQ_OUTBOX_PATH` 或任何本地 JSON 作为通知权威存储。发送失败、NapCat 离线、代理 502 或容器重启时不能丢通知,必须按 `CODEX_QUEUE_NOTIFY_CLAUDEQQ_RETRY_INTERVAL_MS` 指数退避重试并跨进程/容器重启保留。`/health` 的 `queue.notifications.claudeqq` 必须暴露非敏感配置、目标配置状态和 PostgreSQL outbox 统计;`GET /api/notifications/claudeqq` 返回 outbox 明细,`POST /api/notifications/claudeqq/drain` 手动触发发送,`POST /api/notifications/claudeqq/backfill` 可按 `since` 补入某次故障窗口内已终态任务,确保 QQ/NapCat 超时或离线不会让任务完成通知永久丢失。 - 代理路径:只允许 `/health`、`/logs` 和 `/api/` 前缀;允许方法为 `GET`、`HEAD`、`POST`、`DELETE`。Codex Queue 只在 Compose 内网暴露 `4222/tcp`,不得映射或开放到公网。 - UniDesk 前端:`用户服务 / Codex Queue` React 页面负责展示队列卡片、任务 ID、复制任务 ID、引用按钮、任务耗时、默认模型、模型下拉、显式入队份数、引用任务 ID、清空输入、创建成功提示、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、追加 prompt、打断和手动重试控件;整个 agent loop 消息流统一命名为专有名词 `Trace`,`Trace` 包含 assistant message、user prompt、system event 和 tool call;Codex Queue 与 Pipeline/OpenCode messages 必须共用 `src/components/frontend/src/trace.tsx` 的 Trace 公共组件、统一 Trace item 接口和 codex/opencode port 适配层;连续 read/edit/run 工具调用只是在 Trace 内折叠为可展开工具调用组,汇总格式至少包含 `xx read, xx edit, xx run`,并展示读取文件、编辑文件、运行命令和耗时摘要;最近 3 个工具调用保持展开,工具调用内容不得自动换行且必须在工具调用块内部横向滚动,工具调用组展开后不得再增加额外左侧缩进;message 与 prompt 必须自动换行,普通 message 不显示左侧项目符号缩进且永不折叠;点击队列卡片引用按钮必须自动把该任务 ID 写入提交表单的引用任务 ID 输入框;引用任务 ID 创建新任务时必须自动注入 `bun scripts/cli.ts codex task ` 的提示,让 Codex 读取初始 prompt、最后消息和工具摘要后继续;连续执行同一 prompt 应使用 `入队份数` 一次性生成多条队列任务,而不是依赖快速连点按钮;原始任务 JSON 只能通过显式 `查看原始JSON` 打开。 @@ -175,7 +176,7 @@ ClaudeQQ 在 UniDesk 语境中按消息网关后端服务管理:不得直接 - `bun scripts/cli.ts microservice proxy met-nonlinear '/api/projects?root=projects&limit=500'` 与 `bun scripts/cli.ts microservice proxy met-nonlinear '/api/projects/config?path=projects/' --raw`:验证项目库文件树输入和结构化项目详情;详情应包含 config、progress、data、model、metrics 字段,供前端渲染训练状态、模型参数量和指标。 - `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 codex-queue` 与 `bun scripts/cli.ts microservice proxy codex-queue /api/tasks`:验证主 server Codex Queue 后端、PostgreSQL 优先持久化、文件 fallback 快照和本机 provider-gateway 私有代理链路;写入、追加 prompt 和打断由 frontend 同源代理或直接 HTTP API 发起。 +- `bun scripts/cli.ts microservice health codex-queue` 与 `bun scripts/cli.ts microservice proxy codex-queue /api/tasks`:验证主 server Codex Queue 后端、PostgreSQL 强制持久化和本机 provider-gateway 私有代理链路;写入、追加 prompt、打断和 readAt/未读状态都必须由 backend 写入 PostgreSQL,frontend 不得用本地存储伪造成功状态。 - `bun scripts/cli.ts --main-server-ip 74.48.78.17 microservice health findjob`:在计算节点或其他非主 server 主机上通过公网 frontend remote CLI 进行同一验证,不需要主 server SSH key。 `debug dispatch D601 microservice.http --payload-json ...` 仅用于开发调试 provider-gateway 代理能力;正式验收和用户入口应优先使用 `microservice` 命令与 frontend 用户服务页面。 @@ -200,7 +201,7 @@ ClaudeQQ 在 UniDesk 语境中按消息网关后端服务管理:不得直接 - 运行 `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 codex-queue` 与 `bun scripts/cli.ts microservice proxy codex-queue /api/tasks`,确认真实链路经过 backend-core、WebSocket、main-server provider-gateway 和主 server `codex-queue-backend` 后端,并且 `/health` 的 `queue.storage.primary` 为 `postgres` 或在 PG 不可用时显式显示 fallback 原因;再通过公网 frontend 提交一个 `gpt-5.5` 小任务,确认队列串行推进、输出实时更新、结束后有 judge 判定,且运行中可追加 prompt 或打断。Codex Queue 的重启恢复必须作为验收项:运行中任务存在时重启或重建 `codex-queue-backend` 后,任务必须从持久化状态恢复到可继续执行状态,不能丢失 active task、`promptHistory` 或后续 queued 任务。批量验收必须通过公网 frontend 设置 `入队份数=5` 或使用多段 prompt 分隔,一次性入队 5 条任务,并确认 5 条任务按顺序进入 running/judging/succeeded,而不是只运行第一条。 +- 运行 `bun scripts/cli.ts microservice health codex-queue` 与 `bun scripts/cli.ts microservice proxy codex-queue /api/tasks`,确认真实链路经过 backend-core、WebSocket、main-server provider-gateway 和主 server `codex-queue-backend` 后端,并且 `/health` 的 `queue.storage.primary=postgres`、`queue.storage.postgresReady=true`,不得出现 file fallback;`queue.notifications.claudeqq.outbox.storage=postgres` 且暴露 pending/failed/sent 统计。再通过公网 frontend 提交一个 `gpt-5.5` 小任务,确认队列串行推进、输出实时更新、结束后有 judge 判定,且运行中可追加 prompt 或打断。Codex Queue 的重启恢复必须作为验收项:运行中任务存在时重启或重建 `codex-queue-backend` 后,任务必须从 PostgreSQL 恢复到可继续执行状态,不能丢失 active task、`promptHistory`、后续 queued 任务、readAt/未读状态或已入 outbox 的 ClaudeQQ 通知;ClaudeQQ/NapCat 离线期间结束的任务必须能在 `/api/notifications/claudeqq` 中看到 pending/failed,并在登录恢复后通过 `POST /api/notifications/claudeqq/drain` 发送。批量验收必须通过公网 frontend 设置 `入队份数=5` 或使用多段 prompt 分隔,一次性入队 5 条任务,并确认 5 条任务按顺序进入 running/judging/succeeded,而不是只运行第一条。 - 在 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。 - 在 D601 上用 `bun scripts/cli.ts ssh D601 ...` 调试 `~/met_nonlinear`,确认 `curl http://127.0.0.1:3288/health` 可用;最终验收必须回到公网 UniDesk frontend,通过项目库选择、Fork、加入待启动队列和启动队列完成,不要把 MET Nonlinear 后端、Docker build 或训练任务部署到主 server。 diff --git a/scripts/src/e2e.ts b/scripts/src/e2e.ts index 4f162ccf..27ee250d 100644 --- a/scripts/src/e2e.ts +++ b/scripts/src/e2e.ts @@ -1524,16 +1524,11 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2 codexInitialPromptFullMetrics.initialFullHasReference = initialFullText.includes("# Codex Queue 已解析引用上下文") || initialFullText.includes("引用 Codex Queue"); codexInitialPromptFullMetrics.initialFullHasCurrentTask = initialFullText.includes("# 本次任务") || initialFullText.includes("本次任务:"); codexInitialPromptFullMetrics.initialFullChars = initialFullText.length; - await page.waitForSelector('[data-testid="codex-final-prompt-full"]', { timeout: 10000 }); - codexInitialPromptFullMetrics.panelDefaultOpen = await page.getByTestId("codex-final-prompt-full").evaluate((element) => (element as HTMLDetailsElement).open); - await page.locator('[data-testid="codex-final-prompt-full"] summary').click(); - await page.waitForFunction(() => (document.querySelector('[data-testid="codex-final-prompt-full"]') as HTMLDetailsElement | null)?.open === true, undefined, { timeout: 5000 }); - const panelFullText = await page.getByTestId("codex-task-final-prompt-full").innerText({ timeout: 5000 }); - codexInitialPromptFullMetrics.panelExpanded = await page.getByTestId("codex-final-prompt-full").evaluate((element) => (element as HTMLDetailsElement).open); - codexInitialPromptFullMetrics.panelFullMatchesInitial = panelFullText === initialFullText; - codexInitialPromptFullMetrics.panelFullHasReference = panelFullText.includes("# Codex Queue 已解析引用上下文") || panelFullText.includes("引用 Codex Queue"); - codexInitialPromptFullMetrics.panelFullHasCurrentTask = panelFullText.includes("# 本次任务") || panelFullText.includes("本次任务:"); - codexInitialPromptFullMetrics.panelFullChars = panelFullText.length; + codexInitialPromptFullMetrics.legacyPromptPanelMissing = await page.evaluate(() => + document.querySelector(".codex-prompt-panel") === null + && document.querySelector('[data-testid="codex-task-prompt-detail"]') === null + && document.querySelector('[data-testid="codex-final-prompt-full"]') === null, + ); } } if (wants("frontend:codex-queue-trace-full-load")) { @@ -2101,11 +2096,7 @@ async function frontendCheck(config: UniDeskConfig, urls: PublicUrls, checks: E2 && codexInitialPromptFullMetrics.initialExpanded === true && codexInitialPromptFullMetrics.initialFullHasReference === true && codexInitialPromptFullMetrics.initialFullHasCurrentTask === true - && codexInitialPromptFullMetrics.panelDefaultOpen === false - && codexInitialPromptFullMetrics.panelExpanded === true - && codexInitialPromptFullMetrics.panelFullMatchesInitial === true - && codexInitialPromptFullMetrics.panelFullHasReference === true - && codexInitialPromptFullMetrics.panelFullHasCurrentTask === true + && codexInitialPromptFullMetrics.legacyPromptPanelMissing === true ), { codexInitialPromptFullMetrics }); addSelectedCheck(checks, options, "frontend:codex-queue-trace-full-load", diff --git a/src/components/frontend/public/app.js b/src/components/frontend/public/app.js index 091b07a1..ee7d3c56 100644 --- a/src/components/frontend/public/app.js +++ b/src/components/frontend/public/app.js @@ -1,84 +1,86 @@ -(()=>{var dH=Object.create;var{getPrototypeOf:eH,defineProperty:NQ,getOwnPropertyNames:fE}=Object;var uE=Object.prototype.hasOwnProperty;function _E(f){return this[f]}var yE,$E,rf=(f,u,_)=>{var y=f!=null&&typeof f==="object";if(y){var $=u?yE??=new WeakMap:$E??=new WeakMap,l=$.get(f);if(l)return l}_=f!=null?dH(eH(f)):{};let j=u||!f||!f.__esModule?NQ(_,"default",{value:f,enumerable:!0}):_;for(let J of fE(f))if(!uE.call(j,J))NQ(j,J,{get:_E.bind(f,J),enumerable:!0});if(y)$.set(f,j);return j};var Mu=(f,u)=>()=>(u||f((u={exports:{}}).exports,u),u.exports);var pf=((f)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(f,{get:(u,_)=>(typeof require<"u"?require:u)[_]}):f)(function(f){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+f+'" is not supported')});var RQ=Mu((bf)=>{var M$=Symbol.for("react.element"),lE=Symbol.for("react.portal"),jE=Symbol.for("react.fragment"),JE=Symbol.for("react.strict_mode"),FE=Symbol.for("react.profiler"),QE=Symbol.for("react.provider"),AE=Symbol.for("react.context"),UE=Symbol.for("react.forward_ref"),WE=Symbol.for("react.suspense"),zE=Symbol.for("react.memo"),GE=Symbol.for("react.lazy"),LQ=Symbol.iterator;function KE(f){if(f===null||typeof f!=="object")return null;return f=LQ&&f[LQ]||f["@@iterator"],typeof f==="function"?f:null}var wQ={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},DQ=Object.assign,TQ={};function J3(f,u,_){this.props=f,this.context=u,this.refs=TQ,this.updater=_||wQ}J3.prototype.isReactComponent={};J3.prototype.setState=function(f,u){if(typeof f!=="object"&&typeof f!=="function"&&f!=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,f,u,"setState")};J3.prototype.forceUpdate=function(f){this.updater.enqueueForceUpdate(this,f,"forceUpdate")};function MQ(){}MQ.prototype=J3.prototype;function w2(f,u,_){this.props=f,this.context=u,this.refs=TQ,this.updater=_||wQ}var D2=w2.prototype=new MQ;D2.constructor=w2;DQ(D2,J3.prototype);D2.isPureReactComponent=!0;var YQ=Array.isArray,SQ=Object.prototype.hasOwnProperty,T2={current:null},rQ={key:!0,ref:!0,__self:!0,__source:!0};function PQ(f,u,_){var y,$={},l=null,j=null;if(u!=null)for(y in u.ref!==void 0&&(j=u.ref),u.key!==void 0&&(l=""+u.key),u)SQ.call(u,y)&&!rQ.hasOwnProperty(y)&&($[y]=u[y]);var J=arguments.length-2;if(J===1)$.children=_;else if(1{xQ.exports=RQ()});var mQ=Mu((y0)=>{function r2(f,u){var _=f.length;f.push(u);f:for(;0<_;){var y=_-1>>>1,$=f[y];if(0>>1;yf8(J,_))F<$&&0>f8(A,J)?(f[y]=A,f[F]=_,y=F):(f[y]=J,f[j]=_,y=j);else if(F<$&&0>f8(A,_))f[y]=A,f[F]=_,y=F;else break f}}return u}function f8(f,u){var _=f.sortIndex-u.sortIndex;return _!==0?_:f.id-u.id}if(typeof performance==="object"&&typeof performance.now==="function")P2=performance,y0.unstable_now=function(){return P2.now()};else u8=Date,C2=u8.now(),y0.unstable_now=function(){return u8.now()-C2};var P2,u8,C2,w1=[],G_=[],VE=1,tu=null,fu=3,l8=!1,Uy=!1,r$=!1,bQ=typeof setTimeout==="function"?setTimeout:null,hQ=typeof clearTimeout==="function"?clearTimeout:null,vQ=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function R2(f){for(var u=F1(G_);u!==null;){if(u.callback===null)$8(G_);else if(u.startTime<=f)$8(G_),u.sortIndex=u.expirationTime,r2(w1,u);else break;u=F1(G_)}}function v2(f){if(r$=!1,R2(f),!Uy)if(F1(w1)!==null)Uy=!0,h2(b2);else{var u=F1(G_);u!==null&&I2(v2,u.startTime-f)}}function b2(f,u){Uy=!1,r$&&(r$=!1,hQ(P$),P$=-1),l8=!0;var _=fu;try{R2(u);for(tu=F1(w1);tu!==null&&(!(tu.expirationTime>u)||f&&!pQ());){var y=tu.callback;if(typeof y==="function"){tu.callback=null,fu=tu.priorityLevel;var $=y(tu.expirationTime<=u);u=y0.unstable_now(),typeof $==="function"?tu.callback=$:tu===F1(w1)&&$8(w1),R2(u)}else $8(w1);tu=F1(w1)}if(tu!==null)var l=!0;else{var j=F1(G_);j!==null&&I2(v2,j.startTime-u),l=!1}return l}finally{tu=null,fu=_,l8=!1}}var j8=!1,_8=null,P$=-1,IQ=5,cQ=-1;function pQ(){return y0.unstable_now()-cQf||125y?(f.sortIndex=_,r2(G_,f),F1(w1)===null&&f===F1(G_)&&(r$?(hQ(P$),P$=-1):r$=!0,I2(v2,_-y))):(f.sortIndex=$,r2(w1,f),Uy||l8||(Uy=!0,h2(b2))),f};y0.unstable_shouldYield=pQ;y0.unstable_wrapCallback=function(f){var u=fu;return function(){var _=fu;fu=u;try{return f.apply(this,arguments)}finally{fu=_}}}});var iQ=Mu((Gr,kQ)=>{kQ.exports=mQ()});var nW=Mu((xu)=>{var OE=I0(),Cu=iQ();function Ff(f){for(var u="https://reactjs.org/docs/error-decoder.html?invariant="+f,_=1;_"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),F9=Object.prototype.hasOwnProperty,XE=/^[: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]*$/,gQ={},nQ={};function NE(f){if(F9.call(nQ,f))return!0;if(F9.call(gQ,f))return!1;if(XE.test(f))return nQ[f]=!0;return gQ[f]=!0,!1}function LE(f,u,_,y){if(_!==null&&_.type===0)return!1;switch(typeof u){case"function":case"symbol":return!0;case"boolean":if(y)return!1;if(_!==null)return!_.acceptsBooleans;return f=f.toLowerCase().slice(0,5),f!=="data-"&&f!=="aria-";default:return!1}}function YE(f,u,_,y){if(u===null||typeof u>"u"||LE(f,u,_,y))return!0;if(y)return!1;if(_!==null)switch(_.type){case 3:return!u;case 4:return u===!1;case 5:return isNaN(u);case 6:return isNaN(u)||1>u}return!1}function Ku(f,u,_,y,$,l,j){this.acceptsBooleans=u===2||u===3||u===4,this.attributeName=y,this.attributeNamespace=$,this.mustUseProperty=_,this.propertyName=f,this.type=u,this.sanitizeURL=l,this.removeEmptyString=j}var s0={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(f){s0[f]=new Ku(f,0,!1,f,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(f){var u=f[0];s0[u]=new Ku(u,1,!1,f[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(f){s0[f]=new Ku(f,2,!1,f.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(f){s0[f]=new Ku(f,2,!1,f,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(f){s0[f]=new Ku(f,3,!1,f.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(f){s0[f]=new Ku(f,3,!0,f,null,!1,!1)});["capture","download"].forEach(function(f){s0[f]=new Ku(f,4,!1,f,null,!1,!1)});["cols","rows","size","span"].forEach(function(f){s0[f]=new Ku(f,6,!1,f,null,!1,!1)});["rowSpan","start"].forEach(function(f){s0[f]=new Ku(f,5,!1,f.toLowerCase(),null,!1,!1)});var _7=/[\-:]([a-z])/g;function y7(f){return f[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(f){var u=f.replace(_7,y7);s0[u]=new Ku(u,1,!1,f,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(f){var u=f.replace(_7,y7);s0[u]=new Ku(u,1,!1,f,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(f){var u=f.replace(_7,y7);s0[u]=new Ku(u,1,!1,f,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(f){s0[f]=new Ku(f,1,!1,f.toLowerCase(),null,!1,!1)});s0.xlinkHref=new Ku("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(f){s0[f]=new Ku(f,1,!1,f.toLowerCase(),null,!0,!0)});function $7(f,u,_,y){var $=s0.hasOwnProperty(u)?s0[u]:null;if($!==null?$.type!==0:y||!(2J||$[j]!==l[J]){var F=` -`+$[j].replace(" at new "," at ");return f.displayName&&F.includes("")&&(F=F.replace("",f.displayName)),F}while(1<=j&&0<=J);break}}}finally{p2=!1,Error.prepareStackTrace=_}return(f=f?f.displayName||f.name:"")?c$(f):""}function BE(f){switch(f.tag){case 5:return c$(f.type);case 16:return c$("Lazy");case 13:return c$("Suspense");case 19:return c$("SuspenseList");case 0:case 2:case 15:return f=m2(f.type,!1),f;case 11:return f=m2(f.type.render,!1),f;case 1:return f=m2(f.type,!0),f;default:return""}}function W9(f){if(f==null)return null;if(typeof f==="function")return f.displayName||f.name||null;if(typeof f==="string")return f;switch(f){case U3:return"Fragment";case A3:return"Portal";case Q9:return"Profiler";case l7:return"StrictMode";case A9:return"Suspense";case U9:return"SuspenseList"}if(typeof f==="object")switch(f.$$typeof){case dA:return(f.displayName||"Context")+".Consumer";case aA:return(f._context.displayName||"Context")+".Provider";case j7:var u=f.render;return f=f.displayName,f||(f=u.displayName||u.name||"",f=f!==""?"ForwardRef("+f+")":"ForwardRef"),f;case J7:return u=f.displayName||null,u!==null?u:W9(f.type)||"Memo";case Z_:u=f._payload,f=f._init;try{return W9(f(u))}catch(_){}}return null}function wE(f){var u=f.type;switch(f.tag){case 24:return"Cache";case 9:return(u.displayName||"Context")+".Consumer";case 10:return(u._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return f=u.render,f=f.displayName||f.name||"",u.displayName||(f!==""?"ForwardRef("+f+")":"ForwardRef");case 7:return"Fragment";case 5:return u;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return W9(u);case 8:return u===l7?"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 u==="function")return u.displayName||u.name||null;if(typeof u==="string")return u}return null}function M_(f){switch(typeof f){case"boolean":case"number":case"string":case"undefined":return f;case"object":return f;default:return""}}function fU(f){var u=f.type;return(f=f.nodeName)&&f.toLowerCase()==="input"&&(u==="checkbox"||u==="radio")}function DE(f){var u=fU(f)?"checked":"value",_=Object.getOwnPropertyDescriptor(f.constructor.prototype,u),y=""+f[u];if(!f.hasOwnProperty(u)&&typeof _<"u"&&typeof _.get==="function"&&typeof _.set==="function"){var{get:$,set:l}=_;return Object.defineProperty(f,u,{configurable:!0,get:function(){return $.call(this)},set:function(j){y=""+j,l.call(this,j)}}),Object.defineProperty(f,u,{enumerable:_.enumerable}),{getValue:function(){return y},setValue:function(j){y=""+j},stopTracking:function(){f._valueTracker=null,delete f[u]}}}}function F8(f){f._valueTracker||(f._valueTracker=DE(f))}function uU(f){if(!f)return!1;var u=f._valueTracker;if(!u)return!0;var _=u.getValue(),y="";return f&&(y=fU(f)?f.checked?"true":"false":f.value),f=y,f!==_?(u.setValue(f),!0):!1}function P8(f){if(f=f||(typeof document<"u"?document:void 0),typeof f>"u")return null;try{return f.activeElement||f.body}catch(u){return f.body}}function z9(f,u){var _=u.checked;return q0({},u,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:_!=null?_:f._wrapperState.initialChecked})}function sQ(f,u){var _=u.defaultValue==null?"":u.defaultValue,y=u.checked!=null?u.checked:u.defaultChecked;_=M_(u.value!=null?u.value:_),f._wrapperState={initialChecked:y,initialValue:_,controlled:u.type==="checkbox"||u.type==="radio"?u.checked!=null:u.value!=null}}function _U(f,u){u=u.checked,u!=null&&$7(f,"checked",u,!1)}function G9(f,u){_U(f,u);var _=M_(u.value),y=u.type;if(_!=null)if(y==="number"){if(_===0&&f.value===""||f.value!=_)f.value=""+_}else f.value!==""+_&&(f.value=""+_);else if(y==="submit"||y==="reset"){f.removeAttribute("value");return}u.hasOwnProperty("value")?K9(f,u.type,_):u.hasOwnProperty("defaultValue")&&K9(f,u.type,M_(u.defaultValue)),u.checked==null&&u.defaultChecked!=null&&(f.defaultChecked=!!u.defaultChecked)}function oQ(f,u,_){if(u.hasOwnProperty("value")||u.hasOwnProperty("defaultValue")){var y=u.type;if(!(y!=="submit"&&y!=="reset"||u.value!==void 0&&u.value!==null))return;u=""+f._wrapperState.initialValue,_||u===f.value||(f.value=u),f.defaultValue=u}_=f.name,_!==""&&(f.name=""),f.defaultChecked=!!f._wrapperState.initialChecked,_!==""&&(f.name=_)}function K9(f,u,_){if(u!=="number"||P8(f.ownerDocument)!==f)_==null?f.defaultValue=""+f._wrapperState.initialValue:f.defaultValue!==""+_&&(f.defaultValue=""+_)}var p$=Array.isArray;function X3(f,u,_,y){if(f=f.options,u){u={};for(var $=0;$<_.length;$++)u["$"+_[$]]=!0;for(_=0;_"+u.valueOf().toString()+"";for(u=Q8.firstChild;f.firstChild;)f.removeChild(f.firstChild);for(;u.firstChild;)f.appendChild(u.firstChild)}});function l6(f,u){if(u){var _=f.firstChild;if(_&&_===f.lastChild&&_.nodeType===3){_.nodeValue=u;return}}f.textContent=u}var s$={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},TE=["Webkit","ms","Moz","O"];Object.keys(s$).forEach(function(f){TE.forEach(function(u){u=u+f.charAt(0).toUpperCase()+f.substring(1),s$[u]=s$[f]})});function jU(f,u,_){return u==null||typeof u==="boolean"||u===""?"":_||typeof u!=="number"||u===0||s$.hasOwnProperty(f)&&s$[f]?(""+u).trim():u+"px"}function JU(f,u){f=f.style;for(var _ in u)if(u.hasOwnProperty(_)){var y=_.indexOf("--")===0,$=jU(_,u[_],y);_==="float"&&(_="cssFloat"),y?f.setProperty(_,$):f[_]=$}}var ME=q0({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 H9(f,u){if(u){if(ME[f]&&(u.children!=null||u.dangerouslySetInnerHTML!=null))throw Error(Ff(137,f));if(u.dangerouslySetInnerHTML!=null){if(u.children!=null)throw Error(Ff(60));if(typeof u.dangerouslySetInnerHTML!=="object"||!("__html"in u.dangerouslySetInnerHTML))throw Error(Ff(61))}if(u.style!=null&&typeof u.style!=="object")throw Error(Ff(62))}}function E9(f,u){if(f.indexOf("-")===-1)return typeof u.is==="string";switch(f){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 V9=null;function F7(f){return f=f.target||f.srcElement||window,f.correspondingUseElement&&(f=f.correspondingUseElement),f.nodeType===3?f.parentNode:f}var O9=null,N3=null,L3=null;function eQ(f){if(f=N6(f)){if(typeof O9!=="function")throw Error(Ff(280));var u=f.stateNode;u&&(u=J4(u),O9(f.stateNode,f.type,u))}}function FU(f){N3?L3?L3.push(f):L3=[f]:N3=f}function QU(){if(N3){var f=N3,u=L3;if(L3=N3=null,eQ(f),u)for(f=0;f>>=0,f===0?32:31-(cE(f)/pE|0)|0}var A8=64,U8=4194304;function m$(f){switch(f&-f){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 f&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return f&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return f}}function v8(f,u){var _=f.pendingLanes;if(_===0)return 0;var y=0,$=f.suspendedLanes,l=f.pingedLanes,j=_&268435455;if(j!==0){var J=j&~$;J!==0?y=m$(J):(l&=j,l!==0&&(y=m$(l)))}else j=_&~$,j!==0?y=m$(j):l!==0&&(y=m$(l));if(y===0)return 0;if(u!==0&&u!==y&&(u&$)===0&&($=y&-y,l=u&-u,$>=l||$===16&&(l&4194240)!==0))return u;if((y&4)!==0&&(y|=_&16),u=f.entangledLanes,u!==0)for(f=f.entanglements,u&=y;0_;_++)u.push(f);return u}function O6(f,u,_){f.pendingLanes|=u,u!==536870912&&(f.suspendedLanes=0,f.pingedLanes=0),f=f.eventTimes,u=31-z1(u),f[u]=_}function gE(f,u){var _=f.pendingLanes&~u;f.pendingLanes=u,f.suspendedLanes=0,f.pingedLanes=0,f.expiredLanes&=u,f.mutableReadLanes&=u,f.entangledLanes&=u,u=f.entanglements;var y=f.eventTimes;for(f=f.expirationTimes;0<_;){var $=31-z1(_),l=1<<$;u[$]=0,y[$]=-1,f[$]=-1,_&=~l}}function A7(f,u){var _=f.entangledLanes|=u;for(f=f.entanglements;_;){var y=31-z1(_),$=1<=a$),FA=String.fromCharCode(32),QA=!1;function TU(f,u){switch(f){case"keyup":return VV.indexOf(u.keyCode)!==-1;case"keydown":return u.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function MU(f){return f=f.detail,typeof f==="object"&&"data"in f?f.data:null}var W3=!1;function XV(f,u){switch(f){case"compositionend":return MU(u);case"keypress":if(u.which!==32)return null;return QA=!0,FA;case"textInput":return f=u.data,f===FA&&QA?null:f;default:return null}}function NV(f,u){if(W3)return f==="compositionend"||!Z7&&TU(f,u)?(f=wU(),N8=z7=V_=null,W3=!1,f):null;switch(f){case"paste":return null;case"keypress":if(!(u.ctrlKey||u.altKey||u.metaKey)||u.ctrlKey&&u.altKey){if(u.char&&1=u)return{node:_,offset:u-f};f=y}f:{for(;_;){if(_.nextSibling){_=_.nextSibling;break f}_=_.parentNode}_=void 0}_=WA(_)}}function CU(f,u){return f&&u?f===u?!0:f&&f.nodeType===3?!1:u&&u.nodeType===3?CU(f,u.parentNode):("contains"in f)?f.contains(u):f.compareDocumentPosition?!!(f.compareDocumentPosition(u)&16):!1:!1}function RU(){for(var f=window,u=P8();u instanceof f.HTMLIFrameElement;){try{var _=typeof u.contentWindow.location.href==="string"}catch(y){_=!1}if(_)f=u.contentWindow;else break;u=P8(f.document)}return u}function q7(f){var u=f&&f.nodeName&&f.nodeName.toLowerCase();return u&&(u==="input"&&(f.type==="text"||f.type==="search"||f.type==="tel"||f.type==="url"||f.type==="password")||u==="textarea"||f.contentEditable==="true")}function rV(f){var u=RU(),_=f.focusedElem,y=f.selectionRange;if(u!==_&&_&&_.ownerDocument&&CU(_.ownerDocument.documentElement,_)){if(y!==null&&q7(_)){if(u=y.start,f=y.end,f===void 0&&(f=u),"selectionStart"in _)_.selectionStart=u,_.selectionEnd=Math.min(f,_.value.length);else if(f=(u=_.ownerDocument||document)&&u.defaultView||window,f.getSelection){f=f.getSelection();var $=_.textContent.length,l=Math.min(y.start,$);y=y.end===void 0?l:Math.min(y.end,$),!f.extend&&l>y&&($=y,y=l,l=$),$=zA(_,l);var j=zA(_,y);$&&j&&(f.rangeCount!==1||f.anchorNode!==$.node||f.anchorOffset!==$.offset||f.focusNode!==j.node||f.focusOffset!==j.offset)&&(u=u.createRange(),u.setStart($.node,$.offset),f.removeAllRanges(),l>y?(f.addRange(u),f.extend(j.node,j.offset)):(u.setEnd(j.node,j.offset),f.addRange(u)))}}u=[];for(f=_;f=f.parentNode;)f.nodeType===1&&u.push({element:f,left:f.scrollLeft,top:f.scrollTop});typeof _.focus==="function"&&_.focus();for(_=0;_=document.documentMode,z3=null,w9=null,e$=null,D9=!1;function GA(f,u,_){var y=_.window===_?_.document:_.nodeType===9?_:_.ownerDocument;D9||z3==null||z3!==P8(y)||(y=z3,("selectionStart"in y)&&q7(y)?y={start:y.selectionStart,end:y.selectionEnd}:(y=(y.ownerDocument&&y.ownerDocument.defaultView||window).getSelection(),y={anchorNode:y.anchorNode,anchorOffset:y.anchorOffset,focusNode:y.focusNode,focusOffset:y.focusOffset}),e$&&U6(e$,y)||(e$=y,y=I8(w9,"onSelect"),0Z3||(f.current=x9[Z3],x9[Z3]=null,Z3--)}function $0(f,u){Z3++,x9[Z3]=f.current,f.current=u}var S_={},$u=P_(S_),Ou=P_(!1),Vy=S_;function T3(f,u){var _=f.type.contextTypes;if(!_)return S_;var y=f.stateNode;if(y&&y.__reactInternalMemoizedUnmaskedChildContext===u)return y.__reactInternalMemoizedMaskedChildContext;var $={},l;for(l in _)$[l]=u[l];return y&&(f=f.stateNode,f.__reactInternalMemoizedUnmaskedChildContext=u,f.__reactInternalMemoizedMaskedChildContext=$),$}function Xu(f){return f=f.childContextTypes,f!==null&&f!==void 0}function p8(){Q0(Ou),Q0($u)}function OA(f,u,_){if($u.current!==S_)throw Error(Ff(168));$0($u,u),$0(Ou,_)}function kU(f,u,_){var y=f.stateNode;if(u=u.childContextTypes,typeof y.getChildContext!=="function")return _;y=y.getChildContext();for(var $ in y)if(!($ in u))throw Error(Ff(108,wE(f)||"Unknown",$));return q0({},_,y)}function m8(f){return f=(f=f.stateNode)&&f.__reactInternalMemoizedMergedChildContext||S_,Vy=$u.current,$0($u,f),$0(Ou,Ou.current),!0}function XA(f,u,_){var y=f.stateNode;if(!y)throw Error(Ff(169));_?(f=kU(f,u,Vy),y.__reactInternalMemoizedMergedChildContext=f,Q0(Ou),Q0($u),$0($u,f)):Q0(Ou),$0(Ou,_)}var n1=null,F4=!1,e2=!1;function iU(f){n1===null?n1=[f]:n1.push(f)}function pV(f){F4=!0,iU(f)}function C_(){if(!e2&&n1!==null){e2=!0;var f=0,u=af;try{var _=n1;for(af=1;f<_.length;f++){var y=_[f];do y=y(!0);while(y!==null)}n1=null,F4=!1}catch($){throw n1!==null&&(n1=n1.slice(f+1)),ZU(Q7,C_),$}finally{af=u,e2=!1}}return null}var q3=[],H3=0,k8=null,i8=0,su=[],ou=0,Oy=null,t1=1,s1="";function zy(f,u){q3[H3++]=i8,q3[H3++]=k8,k8=f,i8=u}function gU(f,u,_){su[ou++]=t1,su[ou++]=s1,su[ou++]=Oy,Oy=f;var y=t1;f=s1;var $=32-z1(y)-1;y&=~(1<<$),_+=1;var l=32-z1(u)+$;if(30>=j,$-=j,t1=1<<32-z1(u)+$|_<<$|y,s1=l+f}else t1=1<D?(x=N,N=null):x=N.sibling;var c=W(G,N,Z[D],V);if(c===null){N===null&&(N=x);break}f&&N&&c.alternate===null&&u(G,N),H=l(c,H,D),M===null?L=c:M.sibling=c,M=c,N=x}if(D===Z.length)return _(G,N),U0&&zy(G,D),L;if(N===null){for(;DD?(x=N,N=null):x=N.sibling;var v=W(G,N,c.value,V);if(v===null){N===null&&(N=x);break}f&&N&&v.alternate===null&&u(G,N),H=l(v,H,D),M===null?L=v:M.sibling=v,M=v,N=x}if(c.done)return _(G,N),U0&&zy(G,D),L;if(N===null){for(;!c.done;D++,c=Z.next())c=z(G,c.value,V),c!==null&&(H=l(c,H,D),M===null?L=c:M.sibling=c,M=c);return U0&&zy(G,D),L}for(N=y(G,N);!c.done;D++,c=Z.next())c=K(N,G,D,c.value,V),c!==null&&(f&&c.alternate!==null&&N.delete(c.key===null?D:c.key),H=l(c,H,D),M===null?L=c:M.sibling=c,M=c);return f&&N.forEach(function(C){return u(G,C)}),U0&&zy(G,D),L}function O(G,H,Z,V){if(typeof Z==="object"&&Z!==null&&Z.type===U3&&Z.key===null&&(Z=Z.props.children),typeof Z==="object"&&Z!==null){switch(Z.$$typeof){case J8:f:{for(var L=Z.key,M=H;M!==null;){if(M.key===L){if(L=Z.type,L===U3){if(M.tag===7){_(G,M.sibling),H=$(M,Z.props.children),H.return=G,G=H;break f}}else if(M.elementType===L||typeof L==="object"&&L!==null&&L.$$typeof===Z_&&YA(L)===M.type){_(G,M.sibling),H=$(M,Z.props),H.ref=b$(G,M,Z),H.return=G,G=H;break f}_(G,M);break}else u(G,M);M=M.sibling}Z.type===U3?(H=Ey(Z.props.children,G.mode,V,Z.key),H.return=G,G=H):(V=r8(Z.type,Z.key,Z.props,null,G.mode,V),V.ref=b$(G,H,Z),V.return=G,G=V)}return j(G);case A3:f:{for(M=Z.key;H!==null;){if(H.key===M)if(H.tag===4&&H.stateNode.containerInfo===Z.containerInfo&&H.stateNode.implementation===Z.implementation){_(G,H.sibling),H=$(H,Z.children||[]),H.return=G,G=H;break f}else{_(G,H);break}else u(G,H);H=H.sibling}H=J9(Z,G.mode,V),H.return=G,G=H}return j(G);case Z_:return M=Z._init,O(G,H,M(Z._payload),V)}if(p$(Z))return q(G,H,Z,V);if(C$(Z))return E(G,H,Z,V);H8(G,Z)}return typeof Z==="string"&&Z!==""||typeof Z==="number"?(Z=""+Z,H!==null&&H.tag===6?(_(G,H.sibling),H=$(H,Z),H.return=G,G=H):(_(G,H),H=j9(Z,G.mode,V),H.return=G,G=H),j(G)):_(G,H)}return O}var S3=sU(!0),oU=sU(!1),g8=P_(null),n8=null,E3=null,O7=null;function X7(){O7=E3=n8=null}function N7(f){var u=g8.current;Q0(g8),f._currentValue=u}function h9(f,u,_){for(;f!==null;){var y=f.alternate;if((f.childLanes&u)!==u?(f.childLanes|=u,y!==null&&(y.childLanes|=u)):y!==null&&(y.childLanes&u)!==u&&(y.childLanes|=u),f===_)break;f=f.return}}function B3(f,u){n8=f,O7=E3=null,f=f.dependencies,f!==null&&f.firstContext!==null&&((f.lanes&u)!==0&&(Vu=!0),f.firstContext=null)}function eu(f){var u=f._currentValue;if(O7!==f)if(f={context:f,memoizedValue:u,next:null},E3===null){if(n8===null)throw Error(Ff(308));E3=f,n8.dependencies={lanes:0,firstContext:f}}else E3=E3.next=f;return u}var Zy=null;function L7(f){Zy===null?Zy=[f]:Zy.push(f)}function aU(f,u,_,y){var $=u.interleaved;return $===null?(_.next=_,L7(u)):(_.next=$.next,$.next=_),u.interleaved=_,e1(f,y)}function e1(f,u){f.lanes|=u;var _=f.alternate;_!==null&&(_.lanes|=u),_=f;for(f=f.return;f!==null;)f.childLanes|=u,_=f.alternate,_!==null&&(_.childLanes|=u),_=f,f=f.return;return _.tag===3?_.stateNode:null}var q_=!1;function Y7(f){f.updateQueue={baseState:f.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function dU(f,u){f=f.updateQueue,u.updateQueue===f&&(u.updateQueue={baseState:f.baseState,firstBaseUpdate:f.firstBaseUpdate,lastBaseUpdate:f.lastBaseUpdate,shared:f.shared,effects:f.effects})}function o1(f,u){return{eventTime:f,lane:u,tag:0,payload:null,callback:null,next:null}}function B_(f,u,_){var y=f.updateQueue;if(y===null)return null;if(y=y.shared,(gf&2)!==0){var $=y.pending;return $===null?u.next=u:(u.next=$.next,$.next=u),y.pending=u,e1(f,_)}return $=y.interleaved,$===null?(u.next=u,L7(y)):(u.next=$.next,$.next=u),y.interleaved=u,e1(f,_)}function B8(f,u,_){if(u=u.updateQueue,u!==null&&(u=u.shared,(_&4194240)!==0)){var y=u.lanes;y&=f.pendingLanes,_|=y,u.lanes=_,A7(f,_)}}function BA(f,u){var{updateQueue:_,alternate:y}=f;if(y!==null&&(y=y.updateQueue,_===y)){var $=null,l=null;if(_=_.firstBaseUpdate,_!==null){do{var j={eventTime:_.eventTime,lane:_.lane,tag:_.tag,payload:_.payload,callback:_.callback,next:null};l===null?$=l=j:l=l.next=j,_=_.next}while(_!==null);l===null?$=l=u:l=l.next=u}else $=l=u;_={baseState:y.baseState,firstBaseUpdate:$,lastBaseUpdate:l,shared:y.shared,effects:y.effects},f.updateQueue=_;return}f=_.lastBaseUpdate,f===null?_.firstBaseUpdate=u:f.next=u,_.lastBaseUpdate=u}function t8(f,u,_,y){var $=f.updateQueue;q_=!1;var{firstBaseUpdate:l,lastBaseUpdate:j}=$,J=$.shared.pending;if(J!==null){$.shared.pending=null;var F=J,A=F.next;F.next=null,j===null?l=A:j.next=A,j=F;var U=f.alternate;U!==null&&(U=U.updateQueue,J=U.lastBaseUpdate,J!==j&&(J===null?U.firstBaseUpdate=A:J.next=A,U.lastBaseUpdate=F))}if(l!==null){var z=$.baseState;j=0,U=A=F=null,J=l;do{var{lane:W,eventTime:K}=J;if((y&W)===W){U!==null&&(U=U.next={eventTime:K,lane:0,tag:J.tag,payload:J.payload,callback:J.callback,next:null});f:{var q=f,E=J;switch(W=u,K=_,E.tag){case 1:if(q=E.payload,typeof q==="function"){z=q.call(K,z,W);break f}z=q;break f;case 3:q.flags=q.flags&-65537|128;case 0:if(q=E.payload,W=typeof q==="function"?q.call(K,z,W):q,W===null||W===void 0)break f;z=q0({},z,W);break f;case 2:q_=!0}}J.callback!==null&&J.lane!==0&&(f.flags|=64,W=$.effects,W===null?$.effects=[J]:W.push(J))}else K={eventTime:K,lane:W,tag:J.tag,payload:J.payload,callback:J.callback,next:null},U===null?(A=U=K,F=z):U=U.next=K,j|=W;if(J=J.next,J===null)if(J=$.shared.pending,J===null)break;else W=J,J=W.next,W.next=null,$.lastBaseUpdate=W,$.shared.pending=null}while(1);if(U===null&&(F=z),$.baseState=F,$.firstBaseUpdate=A,$.lastBaseUpdate=U,u=$.shared.interleaved,u!==null){$=u;do j|=$.lane,$=$.next;while($!==u)}else l===null&&($.shared.lanes=0);Ny|=j,f.lanes=j,f.memoizedState=z}}function wA(f,u,_){if(f=u.effects,u.effects=null,f!==null)for(u=0;u_?_:4,f(!0);var y=u9.transition;u9.transition={};try{f(!1),u()}finally{af=_,u9.transition=y}}function KW(){return f1().memoizedState}function gV(f,u,_){var y=D_(f);if(_={lane:y,action:_,hasEagerState:!1,eagerState:null,next:null},ZW(f))qW(u,_);else if(_=aU(f,u,_,y),_!==null){var $=Gu();G1(_,f,y,$),HW(_,u,y)}}function nV(f,u,_){var y=D_(f),$={lane:y,action:_,hasEagerState:!1,eagerState:null,next:null};if(ZW(f))qW(u,$);else{var l=f.alternate;if(f.lanes===0&&(l===null||l.lanes===0)&&(l=u.lastRenderedReducer,l!==null))try{var j=u.lastRenderedState,J=l(j,_);if($.hasEagerState=!0,$.eagerState=J,K1(J,j)){var F=u.interleaved;F===null?($.next=$,L7(u)):($.next=F.next,F.next=$),u.interleaved=$;return}}catch(A){}finally{}_=aU(f,u,$,y),_!==null&&($=Gu(),G1(_,f,y,$),HW(_,u,y))}}function ZW(f){var u=f.alternate;return f===Z0||u!==null&&u===Z0}function qW(f,u){f6=o8=!0;var _=f.pending;_===null?u.next=u:(u.next=_.next,_.next=u),f.pending=u}function HW(f,u,_){if((_&4194240)!==0){var y=u.lanes;y&=f.pendingLanes,_|=y,u.lanes=_,A7(f,_)}}var a8={readContext:eu,useCallback:uu,useContext:uu,useEffect:uu,useImperativeHandle:uu,useInsertionEffect:uu,useLayoutEffect:uu,useMemo:uu,useReducer:uu,useRef:uu,useState:uu,useDebugValue:uu,useDeferredValue:uu,useTransition:uu,useMutableSource:uu,useSyncExternalStore:uu,useId:uu,unstable_isNewReconciler:!1},tV={readContext:eu,useCallback:function(f,u){return T1().memoizedState=[f,u===void 0?null:u],f},useContext:eu,useEffect:TA,useImperativeHandle:function(f,u,_){return _=_!==null&&_!==void 0?_.concat([f]):null,D8(4194308,4,AW.bind(null,u,f),_)},useLayoutEffect:function(f,u){return D8(4194308,4,f,u)},useInsertionEffect:function(f,u){return D8(4,2,f,u)},useMemo:function(f,u){var _=T1();return u=u===void 0?null:u,f=f(),_.memoizedState=[f,u],f},useReducer:function(f,u,_){var y=T1();return u=_!==void 0?_(u):u,y.memoizedState=y.baseState=u,f={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:f,lastRenderedState:u},y.queue=f,f=f.dispatch=gV.bind(null,Z0,f),[y.memoizedState,f]},useRef:function(f){var u=T1();return f={current:f},u.memoizedState=f},useState:DA,useDebugValue:P7,useDeferredValue:function(f){return T1().memoizedState=f},useTransition:function(){var f=DA(!1),u=f[0];return f=iV.bind(null,f[1]),T1().memoizedState=f,[u,f]},useMutableSource:function(){},useSyncExternalStore:function(f,u,_){var y=Z0,$=T1();if(U0){if(_===void 0)throw Error(Ff(407));_=_()}else{if(_=u(),p0===null)throw Error(Ff(349));(Xy&30)!==0||_W(y,u,_)}$.memoizedState=_;var l={value:_,getSnapshot:u};return $.queue=l,TA($W.bind(null,y,l,f),[f]),y.flags|=2048,E6(9,yW.bind(null,y,l,_,u),void 0,null),_},useId:function(){var f=T1(),u=p0.identifierPrefix;if(U0){var _=s1,y=t1;_=(y&~(1<<32-z1(y)-1)).toString(32)+_,u=":"+u+"R"+_,_=q6++,0<_&&(u+="H"+_.toString(32)),u+=":"}else _=kV++,u=":"+u+"r"+_.toString(32)+":";return f.memoizedState=u},unstable_isNewReconciler:!1},sV={readContext:eu,useCallback:WW,useContext:eu,useEffect:r7,useImperativeHandle:UW,useInsertionEffect:FW,useLayoutEffect:QW,useMemo:zW,useReducer:_9,useRef:JW,useState:function(){return _9(H6)},useDebugValue:P7,useDeferredValue:function(f){var u=f1();return GW(u,r0.memoizedState,f)},useTransition:function(){var f=_9(H6)[0],u=f1().memoizedState;return[f,u]},useMutableSource:fW,useSyncExternalStore:uW,useId:KW,unstable_isNewReconciler:!1},oV={readContext:eu,useCallback:WW,useContext:eu,useEffect:r7,useImperativeHandle:UW,useInsertionEffect:FW,useLayoutEffect:QW,useMemo:zW,useReducer:y9,useRef:JW,useState:function(){return y9(H6)},useDebugValue:P7,useDeferredValue:function(f){var u=f1();return r0===null?u.memoizedState=f:GW(u,r0.memoizedState,f)},useTransition:function(){var f=y9(H6)[0],u=f1().memoizedState;return[f,u]},useMutableSource:fW,useSyncExternalStore:uW,useId:KW,unstable_isNewReconciler:!1};function A1(f,u){if(f&&f.defaultProps){u=q0({},u),f=f.defaultProps;for(var _ in f)u[_]===void 0&&(u[_]=f[_]);return u}return u}function I9(f,u,_,y){u=f.memoizedState,_=_(y,u),_=_===null||_===void 0?u:q0({},u,_),f.memoizedState=_,f.lanes===0&&(f.updateQueue.baseState=_)}var A4={isMounted:function(f){return(f=f._reactInternals)?By(f)===f:!1},enqueueSetState:function(f,u,_){f=f._reactInternals;var y=Gu(),$=D_(f),l=o1(y,$);l.payload=u,_!==void 0&&_!==null&&(l.callback=_),u=B_(f,l,$),u!==null&&(G1(u,f,$,y),B8(u,f,$))},enqueueReplaceState:function(f,u,_){f=f._reactInternals;var y=Gu(),$=D_(f),l=o1(y,$);l.tag=1,l.payload=u,_!==void 0&&_!==null&&(l.callback=_),u=B_(f,l,$),u!==null&&(G1(u,f,$,y),B8(u,f,$))},enqueueForceUpdate:function(f,u){f=f._reactInternals;var _=Gu(),y=D_(f),$=o1(_,y);$.tag=2,u!==void 0&&u!==null&&($.callback=u),u=B_(f,$,y),u!==null&&(G1(u,f,y,_),B8(u,f,y))}};function MA(f,u,_,y,$,l,j){return f=f.stateNode,typeof f.shouldComponentUpdate==="function"?f.shouldComponentUpdate(y,l,j):u.prototype&&u.prototype.isPureReactComponent?!U6(_,y)||!U6($,l):!0}function EW(f,u,_){var y=!1,$=S_,l=u.contextType;return typeof l==="object"&&l!==null?l=eu(l):($=Xu(u)?Vy:$u.current,y=u.contextTypes,l=(y=y!==null&&y!==void 0)?T3(f,$):S_),u=new u(_,l),f.memoizedState=u.state!==null&&u.state!==void 0?u.state:null,u.updater=A4,f.stateNode=u,u._reactInternals=f,y&&(f=f.stateNode,f.__reactInternalMemoizedUnmaskedChildContext=$,f.__reactInternalMemoizedMaskedChildContext=l),u}function SA(f,u,_,y){f=u.state,typeof u.componentWillReceiveProps==="function"&&u.componentWillReceiveProps(_,y),typeof u.UNSAFE_componentWillReceiveProps==="function"&&u.UNSAFE_componentWillReceiveProps(_,y),u.state!==f&&A4.enqueueReplaceState(u,u.state,null)}function c9(f,u,_,y){var $=f.stateNode;$.props=_,$.state=f.memoizedState,$.refs={},Y7(f);var l=u.contextType;typeof l==="object"&&l!==null?$.context=eu(l):(l=Xu(u)?Vy:$u.current,$.context=T3(f,l)),$.state=f.memoizedState,l=u.getDerivedStateFromProps,typeof l==="function"&&(I9(f,u,l,_),$.state=f.memoizedState),typeof u.getDerivedStateFromProps==="function"||typeof $.getSnapshotBeforeUpdate==="function"||typeof $.UNSAFE_componentWillMount!=="function"&&typeof $.componentWillMount!=="function"||(u=$.state,typeof $.componentWillMount==="function"&&$.componentWillMount(),typeof $.UNSAFE_componentWillMount==="function"&&$.UNSAFE_componentWillMount(),u!==$.state&&A4.enqueueReplaceState($,$.state,null),t8(f,_,$,y),$.state=f.memoizedState),typeof $.componentDidMount==="function"&&(f.flags|=4194308)}function P3(f,u){try{var _="",y=u;do _+=BE(y),y=y.return;while(y);var $=_}catch(l){$=` -Error generating stack: `+l.message+` -`+l.stack}return{value:f,source:u,stack:$,digest:null}}function $9(f,u,_){return{value:f,source:null,stack:_!=null?_:null,digest:u!=null?u:null}}function p9(f,u){try{console.error(u.value)}catch(_){setTimeout(function(){throw _})}}var aV=typeof WeakMap==="function"?WeakMap:Map;function VW(f,u,_){_=o1(-1,_),_.tag=3,_.payload={element:null};var y=u.value;return _.callback=function(){e8||(e8=!0,d9=y),p9(f,u)},_}function OW(f,u,_){_=o1(-1,_),_.tag=3;var y=f.type.getDerivedStateFromError;if(typeof y==="function"){var $=u.value;_.payload=function(){return y($)},_.callback=function(){p9(f,u)}}var l=f.stateNode;return l!==null&&typeof l.componentDidCatch==="function"&&(_.callback=function(){p9(f,u),typeof y!=="function"&&(w_===null?w_=new Set([this]):w_.add(this));var j=u.stack;this.componentDidCatch(u.value,{componentStack:j!==null?j:""})}),_}function rA(f,u,_){var y=f.pingCache;if(y===null){y=f.pingCache=new aV;var $=new Set;y.set(u,$)}else $=y.get(u),$===void 0&&($=new Set,y.set(u,$));$.has(_)||($.add(_),f=UO.bind(null,f,u,_),u.then(f,f))}function PA(f){do{var u;if(u=f.tag===13)u=f.memoizedState,u=u!==null?u.dehydrated!==null?!0:!1:!0;if(u)return f;f=f.return}while(f!==null);return null}function CA(f,u,_,y,$){if((f.mode&1)===0)return f===u?f.flags|=65536:(f.flags|=128,_.flags|=131072,_.flags&=-52805,_.tag===1&&(_.alternate===null?_.tag=17:(u=o1(-1,1),u.tag=2,B_(_,u,1))),_.lanes|=1),f;return f.flags|=65536,f.lanes=$,f}var dV=u_.ReactCurrentOwner,Vu=!1;function zu(f,u,_,y){u.child=f===null?oU(u,null,_,y):S3(u,f.child,_,y)}function RA(f,u,_,y,$){_=_.render;var l=u.ref;if(B3(u,$),y=M7(f,u,_,y,l,$),_=S7(),f!==null&&!Vu)return u.updateQueue=f.updateQueue,u.flags&=-2053,f.lanes&=~$,f_(f,u,$);return U0&&_&&H7(u),u.flags|=1,zu(f,u,y,$),u.child}function xA(f,u,_,y,$){if(f===null){var l=_.type;if(typeof l==="function"&&!c7(l)&&l.defaultProps===void 0&&_.compare===null&&_.defaultProps===void 0)return u.tag=15,u.type=l,XW(f,u,l,y,$);return f=r8(_.type,null,y,u,u.mode,$),f.ref=u.ref,f.return=u,u.child=f}if(l=f.child,(f.lanes&$)===0){var j=l.memoizedProps;if(_=_.compare,_=_!==null?_:U6,_(j,y)&&f.ref===u.ref)return f_(f,u,$)}return u.flags|=1,f=T_(l,y),f.ref=u.ref,f.return=u,u.child=f}function XW(f,u,_,y,$){if(f!==null){var l=f.memoizedProps;if(U6(l,y)&&f.ref===u.ref)if(Vu=!1,u.pendingProps=y=l,(f.lanes&$)!==0)(f.flags&131072)!==0&&(Vu=!0);else return u.lanes=f.lanes,f_(f,u,$)}return m9(f,u,_,y,$)}function NW(f,u,_){var y=u.pendingProps,$=y.children,l=f!==null?f.memoizedState:null;if(y.mode==="hidden")if((u.mode&1)===0)u.memoizedState={baseLanes:0,cachePool:null,transitions:null},$0(O3,Su),Su|=_;else{if((_&1073741824)===0)return f=l!==null?l.baseLanes|_:_,u.lanes=u.childLanes=1073741824,u.memoizedState={baseLanes:f,cachePool:null,transitions:null},u.updateQueue=null,$0(O3,Su),Su|=f,null;u.memoizedState={baseLanes:0,cachePool:null,transitions:null},y=l!==null?l.baseLanes:_,$0(O3,Su),Su|=y}else l!==null?(y=l.baseLanes|_,u.memoizedState=null):y=_,$0(O3,Su),Su|=y;return zu(f,u,$,_),u.child}function LW(f,u){var _=u.ref;if(f===null&&_!==null||f!==null&&f.ref!==_)u.flags|=512,u.flags|=2097152}function m9(f,u,_,y,$){var l=Xu(_)?Vy:$u.current;if(l=T3(u,l),B3(u,$),_=M7(f,u,_,y,l,$),y=S7(),f!==null&&!Vu)return u.updateQueue=f.updateQueue,u.flags&=-2053,f.lanes&=~$,f_(f,u,$);return U0&&y&&H7(u),u.flags|=1,zu(f,u,_,$),u.child}function vA(f,u,_,y,$){if(Xu(_)){var l=!0;m8(u)}else l=!1;if(B3(u,$),u.stateNode===null)T8(f,u),EW(u,_,y),c9(u,_,y,$),y=!0;else if(f===null){var{stateNode:j,memoizedProps:J}=u;j.props=J;var F=j.context,A=_.contextType;typeof A==="object"&&A!==null?A=eu(A):(A=Xu(_)?Vy:$u.current,A=T3(u,A));var U=_.getDerivedStateFromProps,z=typeof U==="function"||typeof j.getSnapshotBeforeUpdate==="function";z||typeof j.UNSAFE_componentWillReceiveProps!=="function"&&typeof j.componentWillReceiveProps!=="function"||(J!==y||F!==A)&&SA(u,j,y,A),q_=!1;var W=u.memoizedState;j.state=W,t8(u,y,j,$),F=u.memoizedState,J!==y||W!==F||Ou.current||q_?(typeof U==="function"&&(I9(u,_,U,y),F=u.memoizedState),(J=q_||MA(u,_,J,y,W,F,A))?(z||typeof j.UNSAFE_componentWillMount!=="function"&&typeof j.componentWillMount!=="function"||(typeof j.componentWillMount==="function"&&j.componentWillMount(),typeof j.UNSAFE_componentWillMount==="function"&&j.UNSAFE_componentWillMount()),typeof j.componentDidMount==="function"&&(u.flags|=4194308)):(typeof j.componentDidMount==="function"&&(u.flags|=4194308),u.memoizedProps=y,u.memoizedState=F),j.props=y,j.state=F,j.context=A,y=J):(typeof j.componentDidMount==="function"&&(u.flags|=4194308),y=!1)}else{j=u.stateNode,dU(f,u),J=u.memoizedProps,A=u.type===u.elementType?J:A1(u.type,J),j.props=A,z=u.pendingProps,W=j.context,F=_.contextType,typeof F==="object"&&F!==null?F=eu(F):(F=Xu(_)?Vy:$u.current,F=T3(u,F));var K=_.getDerivedStateFromProps;(U=typeof K==="function"||typeof j.getSnapshotBeforeUpdate==="function")||typeof j.UNSAFE_componentWillReceiveProps!=="function"&&typeof j.componentWillReceiveProps!=="function"||(J!==z||W!==F)&&SA(u,j,y,F),q_=!1,W=u.memoizedState,j.state=W,t8(u,y,j,$);var q=u.memoizedState;J!==z||W!==q||Ou.current||q_?(typeof K==="function"&&(I9(u,_,K,y),q=u.memoizedState),(A=q_||MA(u,_,A,y,W,q,F)||!1)?(U||typeof j.UNSAFE_componentWillUpdate!=="function"&&typeof j.componentWillUpdate!=="function"||(typeof j.componentWillUpdate==="function"&&j.componentWillUpdate(y,q,F),typeof j.UNSAFE_componentWillUpdate==="function"&&j.UNSAFE_componentWillUpdate(y,q,F)),typeof j.componentDidUpdate==="function"&&(u.flags|=4),typeof j.getSnapshotBeforeUpdate==="function"&&(u.flags|=1024)):(typeof j.componentDidUpdate!=="function"||J===f.memoizedProps&&W===f.memoizedState||(u.flags|=4),typeof j.getSnapshotBeforeUpdate!=="function"||J===f.memoizedProps&&W===f.memoizedState||(u.flags|=1024),u.memoizedProps=y,u.memoizedState=q),j.props=y,j.state=q,j.context=F,y=A):(typeof j.componentDidUpdate!=="function"||J===f.memoizedProps&&W===f.memoizedState||(u.flags|=4),typeof j.getSnapshotBeforeUpdate!=="function"||J===f.memoizedProps&&W===f.memoizedState||(u.flags|=1024),y=!1)}return k9(f,u,_,y,l,$)}function k9(f,u,_,y,$,l){LW(f,u);var j=(u.flags&128)!==0;if(!y&&!j)return $&&XA(u,_,!1),f_(f,u,l);y=u.stateNode,dV.current=u;var J=j&&typeof _.getDerivedStateFromError!=="function"?null:y.render();return u.flags|=1,f!==null&&j?(u.child=S3(u,f.child,null,l),u.child=S3(u,null,J,l)):zu(f,u,J,l),u.memoizedState=y.state,$&&XA(u,_,!0),u.child}function YW(f){var u=f.stateNode;u.pendingContext?OA(f,u.pendingContext,u.pendingContext!==u.context):u.context&&OA(f,u.context,!1),B7(f,u.containerInfo)}function bA(f,u,_,y,$){return M3(),V7($),u.flags|=256,zu(f,u,_,y),u.child}var i9={dehydrated:null,treeContext:null,retryLane:0};function g9(f){return{baseLanes:f,cachePool:null,transitions:null}}function BW(f,u,_){var y=u.pendingProps,$=K0.current,l=!1,j=(u.flags&128)!==0,J;if((J=j)||(J=f!==null&&f.memoizedState===null?!1:($&2)!==0),J)l=!0,u.flags&=-129;else if(f===null||f.memoizedState!==null)$|=1;if($0(K0,$&1),f===null){if(b9(u),f=u.memoizedState,f!==null&&(f=f.dehydrated,f!==null))return(u.mode&1)===0?u.lanes=1:f.data==="$!"?u.lanes=8:u.lanes=1073741824,null;return j=y.children,f=y.fallback,l?(y=u.mode,l=u.child,j={mode:"hidden",children:j},(y&1)===0&&l!==null?(l.childLanes=0,l.pendingProps=j):l=z4(j,y,0,null),f=Ey(f,y,_,null),l.return=u,f.return=u,l.sibling=f,u.child=l,u.child.memoizedState=g9(_),u.memoizedState=i9,f):C7(u,j)}if($=f.memoizedState,$!==null&&(J=$.dehydrated,J!==null))return eV(f,u,j,y,J,$,_);if(l){l=y.fallback,j=u.mode,$=f.child,J=$.sibling;var F={mode:"hidden",children:y.children};return(j&1)===0&&u.child!==$?(y=u.child,y.childLanes=0,y.pendingProps=F,u.deletions=null):(y=T_($,F),y.subtreeFlags=$.subtreeFlags&14680064),J!==null?l=T_(J,l):(l=Ey(l,j,_,null),l.flags|=2),l.return=u,y.return=u,y.sibling=l,u.child=y,y=l,l=u.child,j=f.child.memoizedState,j=j===null?g9(_):{baseLanes:j.baseLanes|_,cachePool:null,transitions:j.transitions},l.memoizedState=j,l.childLanes=f.childLanes&~_,u.memoizedState=i9,y}return l=f.child,f=l.sibling,y=T_(l,{mode:"visible",children:y.children}),(u.mode&1)===0&&(y.lanes=_),y.return=u,y.sibling=null,f!==null&&(_=u.deletions,_===null?(u.deletions=[f],u.flags|=16):_.push(f)),u.child=y,u.memoizedState=null,y}function C7(f,u){return u=z4({mode:"visible",children:u},f.mode,0,null),u.return=f,f.child=u}function E8(f,u,_,y){return y!==null&&V7(y),S3(u,f.child,null,_),f=C7(u,u.pendingProps.children),f.flags|=2,u.memoizedState=null,f}function eV(f,u,_,y,$,l,j){if(_){if(u.flags&256)return u.flags&=-257,y=$9(Error(Ff(422))),E8(f,u,j,y);if(u.memoizedState!==null)return u.child=f.child,u.flags|=128,null;return l=y.fallback,$=u.mode,y=z4({mode:"visible",children:y.children},$,0,null),l=Ey(l,$,j,null),l.flags|=2,y.return=u,l.return=u,y.sibling=l,u.child=y,(u.mode&1)!==0&&S3(u,f.child,null,j),u.child.memoizedState=g9(j),u.memoizedState=i9,l}if((u.mode&1)===0)return E8(f,u,j,null);if($.data==="$!"){if(y=$.nextSibling&&$.nextSibling.dataset,y)var J=y.dgst;return y=J,l=Error(Ff(419)),y=$9(l,y,void 0),E8(f,u,j,y)}if(J=(j&f.childLanes)!==0,Vu||J){if(y=p0,y!==null){switch(j&-j){case 4:$=2;break;case 16:$=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:$=32;break;case 536870912:$=268435456;break;default:$=0}$=($&(y.suspendedLanes|j))!==0?0:$,$!==0&&$!==l.retryLane&&(l.retryLane=$,e1(f,$),G1(y,f,$,-1))}return I7(),y=$9(Error(Ff(421))),E8(f,u,j,y)}if($.data==="$?")return u.flags|=128,u.child=f.child,u=WO.bind(null,f),$._reactRetry=u,null;return f=l.treeContext,ru=Y_($.nextSibling),Pu=u,U0=!0,W1=null,f!==null&&(su[ou++]=t1,su[ou++]=s1,su[ou++]=Oy,t1=f.id,s1=f.overflow,Oy=u),u=C7(u,y.children),u.flags|=4096,u}function hA(f,u,_){f.lanes|=u;var y=f.alternate;y!==null&&(y.lanes|=u),h9(f.return,u,_)}function l9(f,u,_,y,$){var l=f.memoizedState;l===null?f.memoizedState={isBackwards:u,rendering:null,renderingStartTime:0,last:y,tail:_,tailMode:$}:(l.isBackwards=u,l.rendering=null,l.renderingStartTime=0,l.last=y,l.tail=_,l.tailMode=$)}function wW(f,u,_){var y=u.pendingProps,$=y.revealOrder,l=y.tail;if(zu(f,u,y.children,_),y=K0.current,(y&2)!==0)y=y&1|2,u.flags|=128;else{if(f!==null&&(f.flags&128)!==0)f:for(f=u.child;f!==null;){if(f.tag===13)f.memoizedState!==null&&hA(f,_,u);else if(f.tag===19)hA(f,_,u);else if(f.child!==null){f.child.return=f,f=f.child;continue}if(f===u)break f;for(;f.sibling===null;){if(f.return===null||f.return===u)break f;f=f.return}f.sibling.return=f.return,f=f.sibling}y&=1}if($0(K0,y),(u.mode&1)===0)u.memoizedState=null;else switch($){case"forwards":_=u.child;for($=null;_!==null;)f=_.alternate,f!==null&&s8(f)===null&&($=_),_=_.sibling;_=$,_===null?($=u.child,u.child=null):($=_.sibling,_.sibling=null),l9(u,!1,$,_,l);break;case"backwards":_=null,$=u.child;for(u.child=null;$!==null;){if(f=$.alternate,f!==null&&s8(f)===null){u.child=$;break}f=$.sibling,$.sibling=_,_=$,$=f}l9(u,!0,_,null,l);break;case"together":l9(u,!1,null,null,void 0);break;default:u.memoizedState=null}return u.child}function T8(f,u){(u.mode&1)===0&&f!==null&&(f.alternate=null,u.alternate=null,u.flags|=2)}function f_(f,u,_){if(f!==null&&(u.dependencies=f.dependencies),Ny|=u.lanes,(_&u.childLanes)===0)return null;if(f!==null&&u.child!==f.child)throw Error(Ff(153));if(u.child!==null){f=u.child,_=T_(f,f.pendingProps),u.child=_;for(_.return=u;f.sibling!==null;)f=f.sibling,_=_.sibling=T_(f,f.pendingProps),_.return=u;_.sibling=null}return u.child}function fO(f,u,_){switch(u.tag){case 3:YW(u),M3();break;case 5:eU(u);break;case 1:Xu(u.type)&&m8(u);break;case 4:B7(u,u.stateNode.containerInfo);break;case 10:var y=u.type._context,$=u.memoizedProps.value;$0(g8,y._currentValue),y._currentValue=$;break;case 13:if(y=u.memoizedState,y!==null){if(y.dehydrated!==null)return $0(K0,K0.current&1),u.flags|=128,null;if((_&u.child.childLanes)!==0)return BW(f,u,_);return $0(K0,K0.current&1),f=f_(f,u,_),f!==null?f.sibling:null}$0(K0,K0.current&1);break;case 19:if(y=(_&u.childLanes)!==0,(f.flags&128)!==0){if(y)return wW(f,u,_);u.flags|=128}if($=u.memoizedState,$!==null&&($.rendering=null,$.tail=null,$.lastEffect=null),$0(K0,K0.current),y)break;else return null;case 22:case 23:return u.lanes=0,NW(f,u,_)}return f_(f,u,_)}var DW,n9,TW,MW;DW=function(f,u){for(var _=u.child;_!==null;){if(_.tag===5||_.tag===6)f.appendChild(_.stateNode);else if(_.tag!==4&&_.child!==null){_.child.return=_,_=_.child;continue}if(_===u)break;for(;_.sibling===null;){if(_.return===null||_.return===u)return;_=_.return}_.sibling.return=_.return,_=_.sibling}};n9=function(){};TW=function(f,u,_,y){var $=f.memoizedProps;if($!==y){f=u.stateNode,qy(r1.current);var l=null;switch(_){case"input":$=z9(f,$),y=z9(f,y),l=[];break;case"select":$=q0({},$,{value:void 0}),y=q0({},y,{value:void 0}),l=[];break;case"textarea":$=Z9(f,$),y=Z9(f,y),l=[];break;default:typeof $.onClick!=="function"&&typeof y.onClick==="function"&&(f.onclick=c8)}H9(_,y);var j;_=null;for(A in $)if(!y.hasOwnProperty(A)&&$.hasOwnProperty(A)&&$[A]!=null)if(A==="style"){var J=$[A];for(j in J)J.hasOwnProperty(j)&&(_||(_={}),_[j]="")}else A!=="dangerouslySetInnerHTML"&&A!=="children"&&A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&A!=="autoFocus"&&($6.hasOwnProperty(A)?l||(l=[]):(l=l||[]).push(A,null));for(A in y){var F=y[A];if(J=$!=null?$[A]:void 0,y.hasOwnProperty(A)&&F!==J&&(F!=null||J!=null))if(A==="style")if(J){for(j in J)!J.hasOwnProperty(j)||F&&F.hasOwnProperty(j)||(_||(_={}),_[j]="");for(j in F)F.hasOwnProperty(j)&&J[j]!==F[j]&&(_||(_={}),_[j]=F[j])}else _||(l||(l=[]),l.push(A,_)),_=F;else A==="dangerouslySetInnerHTML"?(F=F?F.__html:void 0,J=J?J.__html:void 0,F!=null&&J!==F&&(l=l||[]).push(A,F)):A==="children"?typeof F!=="string"&&typeof F!=="number"||(l=l||[]).push(A,""+F):A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&($6.hasOwnProperty(A)?(F!=null&&A==="onScroll"&&F0("scroll",f),l||J===F||(l=[])):(l=l||[]).push(A,F))}_&&(l=l||[]).push("style",_);var A=l;if(u.updateQueue=A)u.flags|=4}};MW=function(f,u,_,y){_!==y&&(u.flags|=4)};function h$(f,u){if(!U0)switch(f.tailMode){case"hidden":u=f.tail;for(var _=null;u!==null;)u.alternate!==null&&(_=u),u=u.sibling;_===null?f.tail=null:_.sibling=null;break;case"collapsed":_=f.tail;for(var y=null;_!==null;)_.alternate!==null&&(y=_),_=_.sibling;y===null?u||f.tail===null?f.tail=null:f.tail.sibling=null:y.sibling=null}}function _u(f){var u=f.alternate!==null&&f.alternate.child===f.child,_=0,y=0;if(u)for(var $=f.child;$!==null;)_|=$.lanes|$.childLanes,y|=$.subtreeFlags&14680064,y|=$.flags&14680064,$.return=f,$=$.sibling;else for($=f.child;$!==null;)_|=$.lanes|$.childLanes,y|=$.subtreeFlags,y|=$.flags,$.return=f,$=$.sibling;return f.subtreeFlags|=y,f.childLanes=_,u}function uO(f,u,_){var y=u.pendingProps;switch(E7(u),u.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return _u(u),null;case 1:return Xu(u.type)&&p8(),_u(u),null;case 3:if(y=u.stateNode,r3(),Q0(Ou),Q0($u),D7(),y.pendingContext&&(y.context=y.pendingContext,y.pendingContext=null),f===null||f.child===null)q8(u)?u.flags|=4:f===null||f.memoizedState.isDehydrated&&(u.flags&256)===0||(u.flags|=1024,W1!==null&&(u7(W1),W1=null));return n9(f,u),_u(u),null;case 5:w7(u);var $=qy(Z6.current);if(_=u.type,f!==null&&u.stateNode!=null)TW(f,u,_,y,$),f.ref!==u.ref&&(u.flags|=512,u.flags|=2097152);else{if(!y){if(u.stateNode===null)throw Error(Ff(166));return _u(u),null}if(f=qy(r1.current),q8(u)){y=u.stateNode,_=u.type;var l=u.memoizedProps;switch(y[M1]=u,y[G6]=l,f=(u.mode&1)!==0,_){case"dialog":F0("cancel",y),F0("close",y);break;case"iframe":case"object":case"embed":F0("load",y);break;case"video":case"audio":for($=0;$",f=f.removeChild(f.firstChild)):typeof y.is==="string"?f=j.createElement(_,{is:y.is}):(f=j.createElement(_),_==="select"&&(j=f,y.multiple?j.multiple=!0:y.size&&(j.size=y.size))):f=j.createElementNS(f,_),f[M1]=u,f[G6]=y,DW(f,u,!1,!1),u.stateNode=f;f:{switch(j=E9(_,y),_){case"dialog":F0("cancel",f),F0("close",f),$=y;break;case"iframe":case"object":case"embed":F0("load",f),$=y;break;case"video":case"audio":for($=0;$C3&&(u.flags|=128,y=!0,h$(l,!1),u.lanes=4194304)}else{if(!y)if(f=s8(j),f!==null){if(u.flags|=128,y=!0,_=f.updateQueue,_!==null&&(u.updateQueue=_,u.flags|=4),h$(l,!0),l.tail===null&&l.tailMode==="hidden"&&!j.alternate&&!U0)return _u(u),null}else 2*w0()-l.renderingStartTime>C3&&_!==1073741824&&(u.flags|=128,y=!0,h$(l,!1),u.lanes=4194304);l.isBackwards?(j.sibling=u.child,u.child=j):(_=l.last,_!==null?_.sibling=j:u.child=j,l.last=j)}if(l.tail!==null)return u=l.tail,l.rendering=u,l.tail=u.sibling,l.renderingStartTime=w0(),u.sibling=null,_=K0.current,$0(K0,y?_&1|2:_&1),u;return _u(u),null;case 22:case 23:return h7(),y=u.memoizedState!==null,f!==null&&f.memoizedState!==null!==y&&(u.flags|=8192),y&&(u.mode&1)!==0?(Su&1073741824)!==0&&(_u(u),u.subtreeFlags&6&&(u.flags|=8192)):_u(u),null;case 24:return null;case 25:return null}throw Error(Ff(156,u.tag))}function _O(f,u){switch(E7(u),u.tag){case 1:return Xu(u.type)&&p8(),f=u.flags,f&65536?(u.flags=f&-65537|128,u):null;case 3:return r3(),Q0(Ou),Q0($u),D7(),f=u.flags,(f&65536)!==0&&(f&128)===0?(u.flags=f&-65537|128,u):null;case 5:return w7(u),null;case 13:if(Q0(K0),f=u.memoizedState,f!==null&&f.dehydrated!==null){if(u.alternate===null)throw Error(Ff(340));M3()}return f=u.flags,f&65536?(u.flags=f&-65537|128,u):null;case 19:return Q0(K0),null;case 4:return r3(),null;case 10:return N7(u.type._context),null;case 22:case 23:return h7(),null;case 24:return null;default:return null}}var V8=!1,yu=!1,yO=typeof WeakSet==="function"?WeakSet:Set,Hf=null;function V3(f,u){var _=f.ref;if(_!==null)if(typeof _==="function")try{_(null)}catch(y){L0(f,u,y)}else _.current=null}function t9(f,u,_){try{_()}catch(y){L0(f,u,y)}}var IA=!1;function $O(f,u){if(S9=b8,f=RU(),q7(f)){if("selectionStart"in f)var _={start:f.selectionStart,end:f.selectionEnd};else f:{_=(_=f.ownerDocument)&&_.defaultView||window;var y=_.getSelection&&_.getSelection();if(y&&y.rangeCount!==0){_=y.anchorNode;var{anchorOffset:$,focusNode:l}=y;y=y.focusOffset;try{_.nodeType,l.nodeType}catch(V){_=null;break f}var j=0,J=-1,F=-1,A=0,U=0,z=f,W=null;u:for(;;){for(var K;;){if(z!==_||$!==0&&z.nodeType!==3||(J=j+$),z!==l||y!==0&&z.nodeType!==3||(F=j+y),z.nodeType===3&&(j+=z.nodeValue.length),(K=z.firstChild)===null)break;W=z,z=K}for(;;){if(z===f)break u;if(W===_&&++A===$&&(J=j),W===l&&++U===y&&(F=j),(K=z.nextSibling)!==null)break;z=W,W=z.parentNode}z=K}_=J===-1||F===-1?null:{start:J,end:F}}else _=null}_=_||{start:0,end:0}}else _=null;r9={focusedElem:f,selectionRange:_},b8=!1;for(Hf=u;Hf!==null;)if(u=Hf,f=u.child,(u.subtreeFlags&1028)!==0&&f!==null)f.return=u,Hf=f;else for(;Hf!==null;){u=Hf;try{var q=u.alternate;if((u.flags&1024)!==0)switch(u.tag){case 0:case 11:case 15:break;case 1:if(q!==null){var{memoizedProps:E,memoizedState:O}=q,G=u.stateNode,H=G.getSnapshotBeforeUpdate(u.elementType===u.type?E:A1(u.type,E),O);G.__reactInternalSnapshotBeforeUpdate=H}break;case 3:var Z=u.stateNode.containerInfo;Z.nodeType===1?Z.textContent="":Z.nodeType===9&&Z.documentElement&&Z.removeChild(Z.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(Ff(163))}}catch(V){L0(u,u.return,V)}if(f=u.sibling,f!==null){f.return=u.return,Hf=f;break}Hf=u.return}return q=IA,IA=!1,q}function u6(f,u,_){var y=u.updateQueue;if(y=y!==null?y.lastEffect:null,y!==null){var $=y=y.next;do{if(($.tag&f)===f){var l=$.destroy;$.destroy=void 0,l!==void 0&&t9(u,_,l)}$=$.next}while($!==y)}}function U4(f,u){if(u=u.updateQueue,u=u!==null?u.lastEffect:null,u!==null){var _=u=u.next;do{if((_.tag&f)===f){var y=_.create;_.destroy=y()}_=_.next}while(_!==u)}}function s9(f){var u=f.ref;if(u!==null){var _=f.stateNode;switch(f.tag){case 5:f=_;break;default:f=_}typeof u==="function"?u(f):u.current=f}}function SW(f){var u=f.alternate;u!==null&&(f.alternate=null,SW(u)),f.child=null,f.deletions=null,f.sibling=null,f.tag===5&&(u=f.stateNode,u!==null&&(delete u[M1],delete u[G6],delete u[R9],delete u[IV],delete u[cV])),f.stateNode=null,f.return=null,f.dependencies=null,f.memoizedProps=null,f.memoizedState=null,f.pendingProps=null,f.stateNode=null,f.updateQueue=null}function rW(f){return f.tag===5||f.tag===3||f.tag===4}function cA(f){f:for(;;){for(;f.sibling===null;){if(f.return===null||rW(f.return))return null;f=f.return}f.sibling.return=f.return;for(f=f.sibling;f.tag!==5&&f.tag!==6&&f.tag!==18;){if(f.flags&2)continue f;if(f.child===null||f.tag===4)continue f;else f.child.return=f,f=f.child}if(!(f.flags&2))return f.stateNode}}function o9(f,u,_){var y=f.tag;if(y===5||y===6)f=f.stateNode,u?_.nodeType===8?_.parentNode.insertBefore(f,u):_.insertBefore(f,u):(_.nodeType===8?(u=_.parentNode,u.insertBefore(f,_)):(u=_,u.appendChild(f)),_=_._reactRootContainer,_!==null&&_!==void 0||u.onclick!==null||(u.onclick=c8));else if(y!==4&&(f=f.child,f!==null))for(o9(f,u,_),f=f.sibling;f!==null;)o9(f,u,_),f=f.sibling}function a9(f,u,_){var y=f.tag;if(y===5||y===6)f=f.stateNode,u?_.insertBefore(f,u):_.appendChild(f);else if(y!==4&&(f=f.child,f!==null))for(a9(f,u,_),f=f.sibling;f!==null;)a9(f,u,_),f=f.sibling}var n0=null,U1=!1;function K_(f,u,_){for(_=_.child;_!==null;)PW(f,u,_),_=_.sibling}function PW(f,u,_){if(S1&&typeof S1.onCommitFiberUnmount==="function")try{S1.onCommitFiberUnmount(y4,_)}catch(J){}switch(_.tag){case 5:yu||V3(_,u);case 6:var y=n0,$=U1;n0=null,K_(f,u,_),n0=y,U1=$,n0!==null&&(U1?(f=n0,_=_.stateNode,f.nodeType===8?f.parentNode.removeChild(_):f.removeChild(_)):n0.removeChild(_.stateNode));break;case 18:n0!==null&&(U1?(f=n0,_=_.stateNode,f.nodeType===8?d2(f.parentNode,_):f.nodeType===1&&d2(f,_),Q6(f)):d2(n0,_.stateNode));break;case 4:y=n0,$=U1,n0=_.stateNode.containerInfo,U1=!0,K_(f,u,_),n0=y,U1=$;break;case 0:case 11:case 14:case 15:if(!yu&&(y=_.updateQueue,y!==null&&(y=y.lastEffect,y!==null))){$=y=y.next;do{var l=$,j=l.destroy;l=l.tag,j!==void 0&&((l&2)!==0?t9(_,u,j):(l&4)!==0&&t9(_,u,j)),$=$.next}while($!==y)}K_(f,u,_);break;case 1:if(!yu&&(V3(_,u),y=_.stateNode,typeof y.componentWillUnmount==="function"))try{y.props=_.memoizedProps,y.state=_.memoizedState,y.componentWillUnmount()}catch(J){L0(_,u,J)}K_(f,u,_);break;case 21:K_(f,u,_);break;case 22:_.mode&1?(yu=(y=yu)||_.memoizedState!==null,K_(f,u,_),yu=y):K_(f,u,_);break;default:K_(f,u,_)}}function pA(f){var u=f.updateQueue;if(u!==null){f.updateQueue=null;var _=f.stateNode;_===null&&(_=f.stateNode=new yO),u.forEach(function(y){var $=zO.bind(null,f,y);_.has(y)||(_.add(y),y.then($,$))})}}function Q1(f,u){var _=u.deletions;if(_!==null)for(var y=0;y<_.length;y++){var $=_[y];try{var l=f,j=u,J=j;f:for(;J!==null;){switch(J.tag){case 5:n0=J.stateNode,U1=!1;break f;case 3:n0=J.stateNode.containerInfo,U1=!0;break f;case 4:n0=J.stateNode.containerInfo,U1=!0;break f}J=J.return}if(n0===null)throw Error(Ff(160));PW(l,j,$),n0=null,U1=!1;var F=$.alternate;F!==null&&(F.return=null),$.return=null}catch(A){L0($,u,A)}}if(u.subtreeFlags&12854)for(u=u.child;u!==null;)CW(u,f),u=u.sibling}function CW(f,u){var{alternate:_,flags:y}=f;switch(f.tag){case 0:case 11:case 14:case 15:if(Q1(u,f),D1(f),y&4){try{u6(3,f,f.return),U4(3,f)}catch(E){L0(f,f.return,E)}try{u6(5,f,f.return)}catch(E){L0(f,f.return,E)}}break;case 1:Q1(u,f),D1(f),y&512&&_!==null&&V3(_,_.return);break;case 5:if(Q1(u,f),D1(f),y&512&&_!==null&&V3(_,_.return),f.flags&32){var $=f.stateNode;try{l6($,"")}catch(E){L0(f,f.return,E)}}if(y&4&&($=f.stateNode,$!=null)){var l=f.memoizedProps,j=_!==null?_.memoizedProps:l,J=f.type,F=f.updateQueue;if(f.updateQueue=null,F!==null)try{J==="input"&&l.type==="radio"&&l.name!=null&&_U($,l),E9(J,j);var A=E9(J,l);for(j=0;j$&&($=j),y&=~l}if(y=$,y=w0()-y,y=(120>y?120:480>y?480:1080>y?1080:1920>y?1920:3000>y?3000:4320>y?4320:1960*jO(y/1960))-y,10f?16:f,O_===null)var y=!1;else{if(f=O_,O_=null,f4=0,(gf&6)!==0)throw Error(Ff(331));var $=gf;gf|=4;for(Hf=f.current;Hf!==null;){var l=Hf,j=l.child;if((Hf.flags&16)!==0){var J=l.deletions;if(J!==null){for(var F=0;Fw0()-v7?Hy(f,0):x7|=_),Nu(f,u)}function cW(f,u){u===0&&((f.mode&1)===0?u=1:(u=U8,U8<<=1,(U8&130023424)===0&&(U8=4194304)));var _=Gu();f=e1(f,u),f!==null&&(O6(f,u,_),Nu(f,_))}function WO(f){var u=f.memoizedState,_=0;u!==null&&(_=u.retryLane),cW(f,_)}function zO(f,u){var _=0;switch(f.tag){case 13:var{stateNode:y,memoizedState:$}=f;$!==null&&(_=$.retryLane);break;case 19:y=f.stateNode;break;default:throw Error(Ff(314))}y!==null&&y.delete(u),cW(f,_)}var pW;pW=function(f,u,_){if(f!==null)if(f.memoizedProps!==u.pendingProps||Ou.current)Vu=!0;else{if((f.lanes&_)===0&&(u.flags&128)===0)return Vu=!1,fO(f,u,_);Vu=(f.flags&131072)!==0?!0:!1}else Vu=!1,U0&&(u.flags&1048576)!==0&&gU(u,i8,u.index);switch(u.lanes=0,u.tag){case 2:var y=u.type;T8(f,u),f=u.pendingProps;var $=T3(u,$u.current);B3(u,_),$=M7(null,u,y,f,$,_);var l=S7();return u.flags|=1,typeof $==="object"&&$!==null&&typeof $.render==="function"&&$.$$typeof===void 0?(u.tag=1,u.memoizedState=null,u.updateQueue=null,Xu(y)?(l=!0,m8(u)):l=!1,u.memoizedState=$.state!==null&&$.state!==void 0?$.state:null,Y7(u),$.updater=A4,u.stateNode=$,$._reactInternals=u,c9(u,y,f,_),u=k9(null,u,y,!0,l,_)):(u.tag=0,U0&&l&&H7(u),zu(null,u,$,_),u=u.child),u;case 16:y=u.elementType;f:{switch(T8(f,u),f=u.pendingProps,$=y._init,y=$(y._payload),u.type=y,$=u.tag=KO(y),f=A1(y,f),$){case 0:u=m9(null,u,y,f,_);break f;case 1:u=vA(null,u,y,f,_);break f;case 11:u=RA(null,u,y,f,_);break f;case 14:u=xA(null,u,y,A1(y.type,f),_);break f}throw Error(Ff(306,y,""))}return u;case 0:return y=u.type,$=u.pendingProps,$=u.elementType===y?$:A1(y,$),m9(f,u,y,$,_);case 1:return y=u.type,$=u.pendingProps,$=u.elementType===y?$:A1(y,$),vA(f,u,y,$,_);case 3:f:{if(YW(u),f===null)throw Error(Ff(387));y=u.pendingProps,l=u.memoizedState,$=l.element,dU(f,u),t8(u,y,null,_);var j=u.memoizedState;if(y=j.element,l.isDehydrated)if(l={element:y,isDehydrated:!1,cache:j.cache,pendingSuspenseBoundaries:j.pendingSuspenseBoundaries,transitions:j.transitions},u.updateQueue.baseState=l,u.memoizedState=l,u.flags&256){$=P3(Error(Ff(423)),u),u=bA(f,u,y,_,$);break f}else if(y!==$){$=P3(Error(Ff(424)),u),u=bA(f,u,y,_,$);break f}else for(ru=Y_(u.stateNode.containerInfo.firstChild),Pu=u,U0=!0,W1=null,_=oU(u,null,y,_),u.child=_;_;)_.flags=_.flags&-3|4096,_=_.sibling;else{if(M3(),y===$){u=f_(f,u,_);break f}zu(f,u,y,_)}u=u.child}return u;case 5:return eU(u),f===null&&b9(u),y=u.type,$=u.pendingProps,l=f!==null?f.memoizedProps:null,j=$.children,P9(y,$)?j=null:l!==null&&P9(y,l)&&(u.flags|=32),LW(f,u),zu(f,u,j,_),u.child;case 6:return f===null&&b9(u),null;case 13:return BW(f,u,_);case 4:return B7(u,u.stateNode.containerInfo),y=u.pendingProps,f===null?u.child=S3(u,null,y,_):zu(f,u,y,_),u.child;case 11:return y=u.type,$=u.pendingProps,$=u.elementType===y?$:A1(y,$),RA(f,u,y,$,_);case 7:return zu(f,u,u.pendingProps,_),u.child;case 8:return zu(f,u,u.pendingProps.children,_),u.child;case 12:return zu(f,u,u.pendingProps.children,_),u.child;case 10:f:{if(y=u.type._context,$=u.pendingProps,l=u.memoizedProps,j=$.value,$0(g8,y._currentValue),y._currentValue=j,l!==null)if(K1(l.value,j)){if(l.children===$.children&&!Ou.current){u=f_(f,u,_);break f}}else for(l=u.child,l!==null&&(l.return=u);l!==null;){var J=l.dependencies;if(J!==null){j=l.child;for(var F=J.firstContext;F!==null;){if(F.context===y){if(l.tag===1){F=o1(-1,_&-_),F.tag=2;var A=l.updateQueue;if(A!==null){A=A.shared;var U=A.pending;U===null?F.next=F:(F.next=U.next,U.next=F),A.pending=F}}l.lanes|=_,F=l.alternate,F!==null&&(F.lanes|=_),h9(l.return,_,u),J.lanes|=_;break}F=F.next}}else if(l.tag===10)j=l.type===u.type?null:l.child;else if(l.tag===18){if(j=l.return,j===null)throw Error(Ff(341));j.lanes|=_,J=j.alternate,J!==null&&(J.lanes|=_),h9(j,_,u),j=l.sibling}else j=l.child;if(j!==null)j.return=l;else for(j=l;j!==null;){if(j===u){j=null;break}if(l=j.sibling,l!==null){l.return=j.return,j=l;break}j=j.return}l=j}zu(f,u,$.children,_),u=u.child}return u;case 9:return $=u.type,y=u.pendingProps.children,B3(u,_),$=eu($),y=y($),u.flags|=1,zu(f,u,y,_),u.child;case 14:return y=u.type,$=A1(y,u.pendingProps),$=A1(y.type,$),xA(f,u,y,$,_);case 15:return XW(f,u,u.type,u.pendingProps,_);case 17:return y=u.type,$=u.pendingProps,$=u.elementType===y?$:A1(y,$),T8(f,u),u.tag=1,Xu(y)?(f=!0,m8(u)):f=!1,B3(u,_),EW(u,y,$),c9(u,y,$,_),k9(null,u,y,!0,f,_);case 19:return wW(f,u,_);case 22:return NW(f,u,_)}throw Error(Ff(156,u.tag))};function mW(f,u){return ZU(f,u)}function GO(f,u,_,y){this.tag=f,this.key=_,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=u,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=y,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function au(f,u,_,y){return new GO(f,u,_,y)}function c7(f){return f=f.prototype,!(!f||!f.isReactComponent)}function KO(f){if(typeof f==="function")return c7(f)?1:0;if(f!==void 0&&f!==null){if(f=f.$$typeof,f===j7)return 11;if(f===J7)return 14}return 2}function T_(f,u){var _=f.alternate;return _===null?(_=au(f.tag,u,f.key,f.mode),_.elementType=f.elementType,_.type=f.type,_.stateNode=f.stateNode,_.alternate=f,f.alternate=_):(_.pendingProps=u,_.type=f.type,_.flags=0,_.subtreeFlags=0,_.deletions=null),_.flags=f.flags&14680064,_.childLanes=f.childLanes,_.lanes=f.lanes,_.child=f.child,_.memoizedProps=f.memoizedProps,_.memoizedState=f.memoizedState,_.updateQueue=f.updateQueue,u=f.dependencies,_.dependencies=u===null?null:{lanes:u.lanes,firstContext:u.firstContext},_.sibling=f.sibling,_.index=f.index,_.ref=f.ref,_}function r8(f,u,_,y,$,l){var j=2;if(y=f,typeof f==="function")c7(f)&&(j=1);else if(typeof f==="string")j=5;else f:switch(f){case U3:return Ey(_.children,$,l,u);case l7:j=8,$|=8;break;case Q9:return f=au(12,_,u,$|2),f.elementType=Q9,f.lanes=l,f;case A9:return f=au(13,_,u,$),f.elementType=A9,f.lanes=l,f;case U9:return f=au(19,_,u,$),f.elementType=U9,f.lanes=l,f;case eA:return z4(_,$,l,u);default:if(typeof f==="object"&&f!==null)switch(f.$$typeof){case aA:j=10;break f;case dA:j=9;break f;case j7:j=11;break f;case J7:j=14;break f;case Z_:j=16,y=null;break f}throw Error(Ff(130,f==null?f:typeof f,""))}return u=au(j,_,u,$),u.elementType=f,u.type=y,u.lanes=l,u}function Ey(f,u,_,y){return f=au(7,f,y,u),f.lanes=_,f}function z4(f,u,_,y){return f=au(22,f,y,u),f.elementType=eA,f.lanes=_,f.stateNode={isHidden:!1},f}function j9(f,u,_){return f=au(6,f,null,u),f.lanes=_,f}function J9(f,u,_){return u=au(4,f.children!==null?f.children:[],f.key,u),u.lanes=_,u.stateNode={containerInfo:f.containerInfo,pendingChildren:null,implementation:f.implementation},u}function ZO(f,u,_,y,$){this.tag=u,this.containerInfo=f,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=i2(0),this.expirationTimes=i2(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=i2(0),this.identifierPrefix=y,this.onRecoverableError=$,this.mutableSourceEagerHydrationData=null}function p7(f,u,_,y,$,l,j,J,F){return f=new ZO(f,u,_,J,F),u===1?(u=1,l===!0&&(u|=8)):u=0,l=au(3,null,null,u),f.current=l,l.stateNode=f,l.memoizedState={element:y,isDehydrated:_,cache:null,transitions:null,pendingSuspenseBoundaries:null},Y7(l),f}function qO(f,u,_){var y=3{function tW(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=="function")return;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(tW)}catch(f){console.error(f)}}tW(),sW.exports=nW()});var aW=Mu((n7)=>{var oW=g7();n7.createRoot=oW.createRoot,n7.hydrateRoot=oW.hydrateRoot;var XO});var UG=Mu((p4)=>{var SN=I0(),rN=Symbol.for("react.element"),PN=Symbol.for("react.fragment"),CN=Object.prototype.hasOwnProperty,RN=SN.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,xN={key:!0,ref:!0,__self:!0,__source:!0};function AG(f,u,_){var y,$={},l=null,j=null;_!==void 0&&(l=""+_),u.key!==void 0&&(l=""+u.key),u.ref!==void 0&&(j=u.ref);for(y in u)CN.call(u,y)&&!xN.hasOwnProperty(y)&&($[y]=u[y]);if(f&&f.defaultProps)for(y in u=f.defaultProps,u)$[y]===void 0&&($[y]=u[y]);return{$$typeof:rN,type:f,key:l,ref:j,props:$,_owner:RN.current}}p4.Fragment=PN;p4.jsx=AG;p4.jsxs=AG});var zG=Mu((br,WG)=>{WG.exports=UG()});var kK=Mu((mK)=>{var F$=I0();function eB(f,u){return f===u&&(f!==0||1/f===1/u)||f!==f&&u!==u}var fw=typeof Object.is==="function"?Object.is:eB,uw=F$.useState,_w=F$.useEffect,yw=F$.useLayoutEffect,$w=F$.useDebugValue;function lw(f,u){var _=u(),y=uw({inst:{value:_,getSnapshot:u}}),$=y[0].inst,l=y[1];return yw(function(){$.value=_,$.getSnapshot=u,YF($)&&l({inst:$})},[f,_,u]),_w(function(){return YF($)&&l({inst:$}),f(function(){YF($)&&l({inst:$})})},[f]),$w(_),_}function YF(f){var u=f.getSnapshot;f=f.value;try{var _=u();return!fw(f,_)}catch(y){return!0}}function jw(f,u){return u()}var Jw=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?jw:lw;mK.useSyncExternalStore=F$.useSyncExternalStore!==void 0?F$.useSyncExternalStore:Jw});var gK=Mu((Sb,iK)=>{iK.exports=kK()});var tK=Mu((nK)=>{var R5=I0(),Fw=gK();function Qw(f,u){return f===u&&(f!==0||1/f===1/u)||f!==f&&u!==u}var Aw=typeof Object.is==="function"?Object.is:Qw,Uw=Fw.useSyncExternalStore,Ww=R5.useRef,zw=R5.useEffect,Gw=R5.useMemo,Kw=R5.useDebugValue;nK.useSyncExternalStoreWithSelector=function(f,u,_,y,$){var l=Ww(null);if(l.current===null){var j={hasValue:!1,value:null};l.current=j}else j=l.current;l=Gw(function(){function F(K){if(!A){if(A=!0,U=K,K=y(K),$!==void 0&&j.hasValue){var q=j.value;if($(q,K))return z=q}return z=K}if(q=z,Aw(U,K))return q;var E=y(K);if($!==void 0&&$(q,E))return U=K,q;return U=K,z=E}var A=!1,U,z,W=_===void 0?null:_;return[function(){return F(u())},W===null?void 0:function(){return F(W())}]},[u,_,y,$]);var J=Uw(f,l[0],l[1]);return zw(function(){j.hasValue=!0,j.value=J},[J]),Kw(J),J}});var oK=Mu((Pb,sK)=>{sK.exports=tK()});var Pl=rf(I0(),1),OH=rf(aW(),1);var O4=rf(I0(),1);class v3 extends Error{unideskRequestError=!0;meta;constructor(f,u){super(f);this.name="UniDeskRequestError",this.meta=u}}function NO(f){return new Promise((u)=>setTimeout(u,f))}function w6(f,u="操作失败"){return f instanceof Error?f.message:String(f||u)}function H4(f,u=500){if(f===null||f===void 0)return"";let _=typeof f==="string"?f:JSON.stringify(f),y=String(_||"").replace(/\s+/gu," ").trim();return y.length>u?`${y.slice(0,u)}...`:y}function LO(f){try{let u=typeof location<"u"&&location.origin?location.origin:"http://localhost";return new URL(f,u).toString()}catch{return f}}function dW(f){return String(f.method||"GET").toUpperCase()}function YO(f){if(f===null||f===void 0)return!1;if(typeof f!=="object")return!1;if(typeof Blob<"u"&&f instanceof Blob)return!1;if(typeof FormData<"u"&&f instanceof FormData)return!1;if(typeof URLSearchParams<"u"&&f instanceof URLSearchParams)return!1;if(typeof ArrayBuffer<"u"&&f instanceof ArrayBuffer)return!1;return!0}function eW(f){let u=new Headers(f.headers||{}),_=YO(f.body)?JSON.stringify(f.body):f.body;if(_&&!u.has("content-type")&&typeof _==="string")u.set("content-type","application/json");return{...f,credentials:f.credentials||"same-origin",body:_,headers:u}}function fz(f){if(f?.error&&typeof f.error==="object"&&typeof f.error.message==="string")return f.error.message;if(typeof f?.error==="string")return f.error;if(typeof f?.message==="string")return f.message;if(typeof f?.detail==="string")return f.detail;return""}function BO(f,u){if(!f||typeof f!=="object"||Array.isArray(f))return!1;return u.some((_)=>_!==!1&&f[_]===!1)}function Y6(f,u,_,y,$={}){return{kind:f,method:_,url:LO(u),occurredAt:y.toISOString(),...$}}function B6(f,u){if(!f)return"请求失败";return`HTTP ${f}${u?` ${u}`:""}`}function uz(f){try{return{body:f?JSON.parse(f):null,parseError:""}}catch(u){return{body:{text:f},parseError:w6(u,"parse failed")}}}async function wf(f,u={},_=0){let{failureFields:y=["ok"],strictJson:$=!1,retryInvalidJson:l=0,retryDelayMs:j=120,invalidJsonPrefix:J="服务返回了无效 JSON",invalidJsonPreview:F=!1,responsePreviewLength:A=500,...U}=u,z=dW(U),W=new Date,K;try{K=await fetch(f,eW(U))}catch(O){let G=w6(O,"网络请求失败");throw new v3(G,Y6("network",f,z,W,{upstreamMessage:G}))}let q=await K.text(),E=uz(q);if(E.parseError){if($&&z==="GET"&&_=300)?B6(f.meta.status,f.meta.statusText):"应用请求失败",l=f.meta.status?B6(f.meta.status):"",j=(F)=>!F||F===$||F===l,J=!j(f.message)?f.message:j(f.meta.upstreamMessage)?"":f.meta.upstreamMessage||"";return{title:$,message:J,status:f.meta.status,statusText:f.meta.statusText,method:f.meta.method,url:f.meta.url,occurredAt:wO(f.meta.occurredAt),responsePreview:f.meta.responsePreview,parseError:f.meta.parseError,structured:!0}}let y=w6(f,u).split(/\r?\n/u);return{title:y[0]||u,message:y.slice(1).join(` -`),structured:y.length>1}}function DO(f,u="操作失败"){let _=t7(f,u),y=[_.title];if(_.message)y.push(`原因: ${_.message}`);if(_.method||_.url)y.push(`请求: ${[_.method,_.url].filter(Boolean).join(" ")}`);if(_.status)y.push(`状态: ${B6(_.status,_.statusText)}`);if(_.occurredAt)y.push(`时间: ${_.occurredAt}`);if(_.parseError)y.push(`解析错误: ${_.parseError}`);if(_.responsePreview&&_.responsePreview!==_.message)y.push(`响应预览: ${_.responsePreview}`);return y.filter(Boolean).join(` -`)}function Mf(f,u="操作失败"){return yz(f)?DO(f,u):w6(f,u)}var $z=rf(I0(),1);var R_=$z.default.createElement;function D6(f,u){return u?[R_("dt",{key:`${f}-label`},f),R_("dd",{key:f},u)]:null}function H0({error:f,wide:u=!1,fallback:_="操作失败",className:y=""}){if(!f)return null;let $=t7(f,_),l=[D6("请求",[$.method,$.url].filter(Boolean).join(" ")),D6("状态",$.status?`HTTP ${$.status}${$.statusText?` ${$.statusText}`:""}`:""),D6("时间",$.occurredAt),D6("解析错误",$.parseError),D6("响应预览",$.responsePreview)].filter(Boolean);return R_("div",{className:`form-error unidesk-error${u?" wide":""}${y?` ${y}`:""}`,role:"alert","data-testid":"unidesk-error"},R_("div",{className:"unidesk-error-title"},R_("strong",null,$.title),$.status?R_("span",{className:"unidesk-error-code"},`HTTP ${$.status}`):null),$.message?R_("pre",{className:"unidesk-error-message"},$.message):null,l.length>0?R_("dl",{className:"unidesk-error-details"},l):null)}var i=O4.default.createElement,{useEffect:TO}=O4.default,E4=O4.default.useState,wy={label:"主用户私聊账号",userId:645275593};function T6(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return u.toLocaleString("zh-CN",{hour12:!1})}function MO(f){return f.toLocaleTimeString("zh-CN",{hour12:!1})}function s7(f){let u=Number(f);return Number.isFinite(u)?u.toLocaleString("zh-CN"):"--"}async function __(f,u={}){return wf(f,{failureFields:["ok","success"],...u})}function V4({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return i("span",{className:`status-badge ${_}`},u||f||"unknown")}function b3({label:f,value:u,hint:_,tone:y}){return i("article",{className:`metric-card ${y||""}`},i("div",{className:"metric-label"},f),i("div",{className:"metric-value"},u),i("div",{className:"metric-hint"},_))}function h3({title:f,eyebrow:u,actions:_,children:y,className:$}){return i("section",{className:`panel ${$||""}`},i("div",{className:"panel-head"},i("div",null,u?i("p",{className:"panel-eyebrow"},u):null,i("h2",null,f)),_?i("div",{className:"panel-actions"},_):null),i("div",{className:"panel-body"},y))}function M6({title:f,data:u,onOpen:_,testId:y}){return i("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:($)=>{$?.stopPropagation?.(),_(f,u)}},"查看原始JSON")}function S6({title:f,text:u}){return i("div",{className:"empty-state"},i("strong",null,f),i("span",null,u))}function SO(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function rO(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function PO(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function x_(f,u){return`${f}/microservices/claudeqq/proxy${u}`}function CO(f){return Array.isArray(f?.events)?f.events.slice(0,80):[]}function RO(f){return Array.isArray(f?.subscriptions)?f.subscriptions.slice(0,50):[]}function xO(f){return Array.isArray(f?.messages)?f.messages.slice(0,30):[]}function lz(f){let u=f?.text??f?.message??f?.raw?.raw_message;if(typeof u!=="string")return"--";return u.length>180?`${u.slice(0,177)}...`:u}function jz(f){let u=f?.groupId??f?.group_id??(f?.message_type==="group"?f?.target_id:void 0),_=f?.userId??f?.user_id??(f?.message_type==="private"?f?.target_id:void 0);if(u)return`群 ${u}`;if(_)return`私聊 ${_}`;return"--"}function Jz({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((T)=>T.id==="claudeqq")||null,[$,l]=E4({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}),[j,J]=E4({targetType:"private",targetId:String(wy.userId),message:""}),[F,A]=E4({name:"unidesk-callback",targetUrl:"",eventTypes:"message",secret:""}),[U,z]=E4("");async function W(){if(!y)return;l((T)=>({...T,loading:!0,error:""}));try{let[T,Y,R,m,p]=await Promise.all([__(`${_}/microservices/claudeqq/health`),__(x_(_,"/api/server/status")),__(x_(_,"/api/events/recent?limit=60")),__(x_(_,"/api/events/subscriptions")),__(x_(_,"/api/messages/sent?limit=20"))]);if(l((n)=>({...n,loading:!1,error:"",health:T,status:Y,events:R,subscriptions:m,sent:p,refreshedAt:new Date})),!$.qrcodeFetched)K(!1)}catch(T){l((Y)=>({...Y,loading:!1,error:Mf(T,"ClaudeQQ 加载失败")}))}}async function K(T=!0){if(!y)return;l((Y)=>({...Y,qrLoading:!0,error:T?"":Y.error}));try{let Y=await __(x_(_,"/api/napcat/login")),R=Y?.napcat?.qrcode||Y?.qrcode||null;l((m)=>({...m,qrLoading:!1,error:"",napcatLogin:Y,napcatQrcode:R,qrcodeFetched:!0,qrcodeRefreshedAt:new Date}))}catch(Y){l((R)=>({...R,qrLoading:!1,error:T||!R.napcatQrcode?Mf(Y,"NapCat 二维码加载失败"):R.error}))}}async function q(T){T.preventDefault(),z("");let Y=Number(j.targetId);if(!Number.isFinite(Y)||Y<=0||j.message.trim().length===0){l((R)=>({...R,error:"请填写 QQ 目标和消息内容"}));return}try{await __(x_(_,"/api/push/text"),{method:"POST",body:JSON.stringify({userId:j.targetType==="private"?Y:void 0,groupId:j.targetType==="group"?Y:void 0,message:j.message})}),J((R)=>({...R,targetType:"private",targetId:String(wy.userId),message:""})),z("消息推送请求已提交"),await W()}catch(R){l((m)=>({...m,error:Mf(R,"发送失败")}))}}async function E(T){if(T.preventDefault(),z(""),F.targetUrl.trim().length===0){l((Y)=>({...Y,error:"请填写订阅回调 URL"}));return}try{await __(x_(_,"/api/events/subscriptions"),{method:"POST",body:JSON.stringify({name:F.name,targetUrl:F.targetUrl,eventTypes:F.eventTypes.split(",").map((Y)=>Y.trim()).filter(Boolean),secret:F.secret||void 0,enabled:!0})}),z("事件订阅已创建"),await W()}catch(Y){l((R)=>({...R,error:Mf(Y,"订阅失败")}))}}async function O(T){if(!T)return;z("");try{await __(x_(_,`/api/events/subscriptions/${encodeURIComponent(T)}`),{method:"DELETE"}),z("事件订阅已删除"),await W()}catch(Y){l((R)=>({...R,error:Mf(Y,"删除订阅失败")}))}}if(TO(()=>{if(!y)return;W();return},[y?.id,y?.runtime?.providerStatus]),!y)return i(S6,{title:"ClaudeQQ 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=claudeqq"});let G=SO(y),H=PO(y),Z=rO(y),V=$.health||{},L=$.status||{},M=$.napcatLogin||{},N=V.napcat||L.napcat||{},D={...M.napcat||{},...N,qrcode:$.napcatQrcode||{},webui:N.webui||M.napcat?.webui},x=M.login||{},c=$.napcatQrcode||{},v=CO($.events),C=RO($.subscriptions),P=xO($.sent),w=Boolean(D.httpConnected||x.ready),r=String(D.loginState||x.state||(w?"logged_in":"unknown")),S=Boolean(c.available&&c.dataUrl);return i("div",{className:"claudeqq-page","data-testid":"claudeqq-page"},i(h3,{title:"ClaudeQQ 工作台",eyebrow:"D601 QQ Event Gateway",actions:i("div",{className:"panel-actions"},i("button",{type:"button",className:"ghost-btn",onClick:W,disabled:$.loading,"data-testid":"claudeqq-refresh-button"},$.loading?"刷新中":"刷新"),i(M6,{title:"ClaudeQQ 用户服务",data:y,onOpen:u,testId:"raw-claudeqq-service"}))},i("div",{className:"findjob-hero"},i("div",null,i("div",{className:"node-version-line"},i(V4,{status:G.providerStatus==="online"?"online":"warn"},G.providerStatus||"unknown"),i("span",null,y.providerId),i("span",null,Z.public?"公网暴露":"仅 UniDesk frontend 代理访问")),i("p",{className:"muted paragraph"},y.description)),i("div",{className:"microservice-ref-card"},i("span",null,"Repo"),i("strong",null,H.url||"--"),i("code",null,H.commitId||"--")),i("div",{className:"microservice-ref-card"},i("span",null,"D601 Docker"),i("strong",null,`${Z.nodeBindHost||"--"}:${Z.nodePort||"--"}`),i("code",null,`${H.composeFile||"--"} / ${H.composeService||"--"}`))),i(H0,{error:$.error,wide:!0}),U?i("div",{className:"form-success wide"},U):null),i("div",{className:"metric-grid"},i(b3,{label:"Health",value:V.ok||V.status==="ok"?"OK":"--",hint:"D601 /health",tone:V.ok||V.status==="ok"?"ok":"warn"}),i(b3,{label:"NapCat HTTP",value:D.httpConnected||D.http?.connected?"OK":"离线",hint:`${D.httpHost||V.napcat?.httpHost||"--"}:${D.httpPort||V.napcat?.httpPort||"--"}`}),i(b3,{label:"NapCat WS",value:D.wsConnected||D.ws?.connected?"OK":"离线",hint:`${D.wsHost||V.napcat?.wsHost||"--"}:${D.wsPort||V.napcat?.wsPort||"--"}`}),i(b3,{label:"事件缓存",value:s7($.events?.count??v.length),hint:"recent QQ events"}),i(b3,{label:"订阅",value:s7($.subscriptions?.count??C.length),hint:"webhook subscribers"}),i(b3,{label:"已发送",value:s7($.sent?.count??P.length),hint:"sent message log"})),i("div",{className:"findjob-grid"},i(h3,{title:"NapCat 容器登录",eyebrow:"QR Login",className:"claudeqq-login-panel",actions:i("div",{className:"panel-actions inline-actions"},i("button",{type:"button",className:"ghost-btn",onClick:()=>K(!0),disabled:$.qrLoading,"data-testid":"claudeqq-napcat-refresh"},$.qrLoading?"刷新中":"手动刷新二维码"),i(M6,{title:"NapCat Login",data:$.napcatLogin,onOpen:u,testId:"raw-claudeqq-napcat-login"}))},i("div",{className:"claudeqq-login-card","data-testid":"claudeqq-napcat-login"},i("div",{className:"claudeqq-qr-frame"},S?i("img",{src:c.dataUrl,alt:"NapCat QQ 登录二维码","data-testid":"claudeqq-napcat-qrcode"}):i(S6,{title:"等待二维码",text:"NapCat 容器启动后会把登录二维码写入 cache/qrcode.png"})),i("div",{className:"claudeqq-login-copy"},i("div",{className:"node-version-line"},i(V4,{status:w?"online":S?"warn":"unknown"},w?"已登录":S?"待扫码":"等待二维码"),i("span",null,r),i("span",null,"D601 containerized")),i("p",{className:"muted paragraph"},w?"NapCat 已登录,ClaudeQQ 可通过容器内 HTTP/WS 链路收发 QQ 消息。":"用手机 QQ 扫描二维码授权登录。二维码只在首次加载或手动刷新时更新,D601 的 NapCat 端口仍只绑定 127.0.0.1。"),i("div",{className:"microservice-ref-card"},i("span",null,"NapCat WebUI"),i("strong",null,D.webui?.url||"http://napcat:6099/webui"),i("code",null,"local-only / proxied QR login")),i("div",{className:"microservice-ref-card"},i("span",null,"QR Source"),i("strong",null,c.modifiedAt?T6(c.modifiedAt):$.qrcodeRefreshedAt?T6($.qrcodeRefreshedAt):"--"),i("code",null,c.file||"/napcat/cache/qrcode.png"))))),i(h3,{title:"消息推送",eyebrow:"Push API"},i("div",{className:"microservice-ref-card"},i("span",null,wy.label),i("strong",null,String(wy.userId)),i("code",null,"private userId / 默认推送测试目标")),i("form",{className:"stack-form",onSubmit:q,"data-testid":"claudeqq-push-form"},i("label",null,"目标类型",i("select",{value:j.targetType,onChange:(T)=>J((Y)=>({...Y,targetType:T.target.value}))},i("option",{value:"private"},"私聊 userId"),i("option",{value:"group"},"群 groupId"))),i("label",null,"QQ ID",i("input",{value:j.targetId,onChange:(T)=>J((Y)=>({...Y,targetId:T.target.value})),placeholder:String(wy.userId)})),i("label",null,"消息内容",i("textarea",{value:j.message,onChange:(T)=>J((Y)=>({...Y,message:T.target.value})),rows:4,placeholder:"通过 ClaudeQQ 推送一条 QQ 消息"})),i("button",{type:"submit",className:"primary-btn"},"发送 QQ 消息")),i("p",{className:"muted paragraph"},`主 server 和其他用户服务可通过 UniDesk 同源代理调用 /api/push/text;当前人工推送测试默认使用 ${wy.label} ${wy.userId},不需要暴露 D601 后端端口。`)),i(h3,{title:"QQ 事件订阅",eyebrow:"Webhook Subscription"},i("form",{className:"stack-form",onSubmit:E,"data-testid":"claudeqq-subscription-form"},i("label",null,"订阅名称",i("input",{value:F.name,onChange:(T)=>A((Y)=>({...Y,name:T.target.value}))})),i("label",null,"回调 URL",i("input",{value:F.targetUrl,onChange:(T)=>A((Y)=>({...Y,targetUrl:T.target.value})),placeholder:"http://host.docker.internal:18080/..."})),i("label",null,"事件类型",i("input",{value:F.eventTypes,onChange:(T)=>A((Y)=>({...Y,eventTypes:T.target.value})),placeholder:"message,notice"})),i("label",null,"签名密钥",i("input",{value:F.secret,onChange:(T)=>A((Y)=>({...Y,secret:T.target.value})),placeholder:"可选,生成 x-claudeqq-signature"})),i("button",{type:"submit",className:"primary-btn"},"创建订阅")),C.length===0?i(S6,{title:"暂无订阅",text:"可以为 main server 或其他用户服务注册 HTTP webhook"}):i("div",{className:"table-wrap","data-testid":"claudeqq-subscription-table"},i("table",null,i("thead",null,i("tr",null,i("th",null,"名称"),i("th",null,"状态"),i("th",null,"事件"),i("th",null,"回调"),i("th",null,"最近投递"),i("th",null,"操作"))),i("tbody",null,C.map((T)=>i("tr",{key:T.id},i("td",null,i("strong",null,T.name||T.id),i("code",null,T.id||"--")),i("td",null,i(V4,{status:T.enabled?"online":"warn"},T.enabled?"enabled":"disabled")),i("td",null,Array.isArray(T.eventTypes)?T.eventTypes.join(", "):"message"),i("td",null,T.targetUrl||"--"),i("td",null,T.lastDelivery?`${T.lastDelivery.ok?"OK":"FAIL"} ${T6(T.lastDelivery.at)}`:"--"),i("td",null,i("button",{type:"button",className:"ghost-btn",onClick:()=>O(T.id)},"删除"))))))),i("div",{className:"panel-actions inline-actions"},i(M6,{title:"ClaudeQQ Subscriptions",data:$.subscriptions,onOpen:u,testId:"raw-claudeqq-subscriptions"}))),i(h3,{title:"最近 QQ 事件",eyebrow:$.refreshedAt?`Updated ${MO($.refreshedAt)}`:"Event Stream"},v.length===0?i(S6,{title:"暂无事件",text:"等待 NapCat WebSocket 上报 QQ 消息事件,或通过订阅 API 消费后续事件"}):i("div",{className:"table-wrap","data-testid":"claudeqq-event-list"},i("table",null,i("thead",null,i("tr",null,i("th",null,"时间"),i("th",null,"类型"),i("th",null,"会话"),i("th",null,"消息"),i("th",null,"ID"))),i("tbody",null,v.map((T)=>i("tr",{key:T.id},i("td",null,T6(T.receivedAt||T.timestamp)),i("td",null,i(V4,{status:T.postType||T.eventType},T.postType||T.eventType||"--")),i("td",null,jz(T)),i("td",null,lz(T)),i("td",null,i("code",null,T.messageId||T.id||"--"))))))),i("div",{className:"panel-actions inline-actions"},i(M6,{title:"ClaudeQQ Events",data:$.events,onOpen:u,testId:"raw-claudeqq-events"}))),i(h3,{title:"已发送消息",eyebrow:`${P.length} Sent`},P.length===0?i(S6,{title:"暂无发送记录",text:"发送日志来自 ClaudeQQ bot_workspace/messages/sent_messages.jsonl"}):i("div",{className:"table-wrap"},i("table",null,i("thead",null,i("tr",null,i("th",null,"时间"),i("th",null,"目标"),i("th",null,"消息"),i("th",null,"结果"))),i("tbody",null,P.map((T,Y)=>i("tr",{key:T.id||Y},i("td",null,T6(T.timestamp||T.sentAt||T.createdAt)),i("td",null,jz(T)),i("td",null,lz(T)),i("td",null,T.status||T.messageId||T.message_id||"--")))))),i("div",{className:"panel-actions inline-actions"},i(M6,{title:"ClaudeQQ Sent Messages",data:$.sent,onOpen:u,testId:"raw-claudeqq-sent"})))))}var S4=rf(I0(),1);var $j=rf(I0(),1),Lf=$j.default.createElement,{useEffect:vO,useRef:Fz}=$j.default;function bO(f,u){return Yz(f.toTrace(u))}function Zz(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return u.toLocaleString("zh-CN",{hour12:!1})}function hO(f){let u=Number(f);if(!Number.isFinite(u)||u<0)return"--";let _=Math.floor(u/1000),y=Math.floor(_/3600),$=Math.floor(_%3600/60),l=_%60;if(y>0)return`${y}h ${String($).padStart(2,"0")}m`;if($>0)return`${$}m ${String(l).padStart(2,"0")}s`;return`${l}s`}function Dy(f){let u=Number(f);return Number.isFinite(u)&&u>=0?u:null}function qz(f,u=180){let _=String(f||"").replace(/\s+/gu," ").trim();return _.length>u?`${_.slice(0,u-1)}…`:_}function IO(f){if(!f)return 0;return f.split(/\r?\n/u).length}function fj(f){return{ran:"Ran",explored:"Explored",edited:"Edited",toolGroup:"Tool calls",plan:"Plan",message:"Message",system:"System",error:"Error"}[f]||"Message"}function uj(f){let u=Number(f||0);return Number.isFinite(u)&&u>0?`… +${Math.floor(u)} lines`:""}function cO(f){return(Array.isArray(f)?f:[]).reduce((u,_)=>Math.max(u,Number(_?.seq??0)),0)}function Qz(f){return["explored","edited","ran"].includes(String(f?.kind||""))}function Hz(f){let u={read:0,edit:0,run:0};for(let _ of f){let y=String(_?.kind||"");if(y==="explored")u.read+=1;else if(y==="edited")u.edit+=1;else if(y==="ran")u.run+=1}return u}function Ez(f){let u=Hz(f);return`${u.read} read, ${u.edit} edit, ${u.run} run`}function Vz(f){return f.replace(/^['"`([{<]+/u,"").replace(/['"`)\]}>.,;:]+$/u,"").replace(/:\d+(?::\d+)?$/u,"").trim()}function Az(f){let _=String(f||"").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)||[],y=[];for(let $ of _){let l=Vz($);if(l.length<2||l.includes("..."))continue;if(/^(http|https|status|method)$/iu.test(l))continue;if(!y.includes(l))y.push(l)}return y}function o7(f,u=4){if(f.length===0)return"--";let _=f.slice(0,u).join(", ");return f.length>u?`${_} +${f.length-u}`:_}function Uz(f){let u="";for(let _ of f){if(_.length===0)continue;if(u.length>0&&!u.endsWith(` +(()=>{var oE=Object.create;var{getPrototypeOf:aE,defineProperty:YQ,getOwnPropertyNames:dE}=Object;var eE=Object.prototype.hasOwnProperty;function fH(f){return this[f]}var uH,_H,Sf=(f,u,_)=>{var y=f!=null&&typeof f==="object";if(y){var l=u?uH??=new WeakMap:_H??=new WeakMap,$=l.get(f);if($)return $}_=f!=null?oE(aE(f)):{};let j=u||!f||!f.__esModule?YQ(_,"default",{value:f,enumerable:!0}):_;for(let J of dE(f))if(!eE.call(j,J))YQ(j,J,{get:fH.bind(f,J),enumerable:!0});if(y)l.set(f,j);return j};var Pu=(f,u)=>()=>(u||f((u={exports:{}}).exports,u),u.exports);var pf=((f)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(f,{get:(u,_)=>(typeof require<"u"?require:u)[_]}):f)(function(f){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+f+'" is not supported')});var vQ=Pu((bf)=>{var T3=Symbol.for("react.element"),yH=Symbol.for("react.portal"),lH=Symbol.for("react.fragment"),$H=Symbol.for("react.strict_mode"),jH=Symbol.for("react.profiler"),JH=Symbol.for("react.provider"),FH=Symbol.for("react.context"),QH=Symbol.for("react.forward_ref"),AH=Symbol.for("react.suspense"),UH=Symbol.for("react.memo"),WH=Symbol.for("react.lazy"),BQ=Symbol.iterator;function GH(f){if(f===null||typeof f!=="object")return null;return f=BQ&&f[BQ]||f["@@iterator"],typeof f==="function"?f:null}var TQ={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},rQ=Object.assign,MQ={};function ll(f,u,_){this.props=f,this.context=u,this.refs=MQ,this.updater=_||TQ}ll.prototype.isReactComponent={};ll.prototype.setState=function(f,u){if(typeof f!=="object"&&typeof f!=="function"&&f!=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,f,u,"setState")};ll.prototype.forceUpdate=function(f){this.updater.enqueueForceUpdate(this,f,"forceUpdate")};function PQ(){}PQ.prototype=ll.prototype;function D2(f,u,_){this.props=f,this.context=u,this.refs=MQ,this.updater=_||TQ}var w2=D2.prototype=new PQ;w2.constructor=D2;rQ(w2,ll.prototype);w2.isPureReactComponent=!0;var DQ=Array.isArray,SQ=Object.prototype.hasOwnProperty,T2={current:null},CQ={key:!0,ref:!0,__self:!0,__source:!0};function RQ(f,u,_){var y,l={},$=null,j=null;if(u!=null)for(y in u.ref!==void 0&&(j=u.ref),u.key!==void 0&&($=""+u.key),u)SQ.call(u,y)&&!CQ.hasOwnProperty(y)&&(l[y]=u[y]);var J=arguments.length-2;if(J===1)l.children=_;else if(1{bQ.exports=vQ()});var tQ=Pu(($0)=>{function C2(f,u){var _=f.length;f.push(u);f:for(;0<_;){var y=_-1>>>1,l=f[y];if(0>>1;y<$;){var j=2*(y+1)-1,J=f[j],F=j+1,A=f[F];if(0>o6(J,_))Fo6(A,J)?(f[y]=A,f[F]=_,y=F):(f[y]=J,f[j]=_,y=j);else if(Fo6(A,_))f[y]=A,f[F]=_,y=F;else break f}}return u}function o6(f,u){var _=f.sortIndex-u.sortIndex;return _!==0?_:f.id-u.id}if(typeof performance==="object"&&typeof performance.now==="function")R2=performance,$0.unstable_now=function(){return R2.now()};else a6=Date,x2=a6.now(),$0.unstable_now=function(){return a6.now()-x2};var R2,a6,x2,Y1=[],U_=[],OH=1,tu=null,uu=3,u8=!1,Uy=!1,M3=!1,kQ=typeof setTimeout==="function"?setTimeout:null,mQ=typeof clearTimeout==="function"?clearTimeout:null,pQ=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function v2(f){for(var u=F1(U_);u!==null;){if(u.callback===null)f8(U_);else if(u.startTime<=f)f8(U_),u.sortIndex=u.expirationTime,C2(Y1,u);else break;u=F1(U_)}}function h2(f){if(M3=!1,v2(f),!Uy)if(F1(Y1)!==null)Uy=!0,c2(I2);else{var u=F1(U_);u!==null&&p2(h2,u.startTime-f)}}function I2(f,u){Uy=!1,M3&&(M3=!1,mQ(P3),P3=-1),u8=!0;var _=uu;try{v2(u);for(tu=F1(Y1);tu!==null&&(!(tu.expirationTime>u)||f&&!nQ());){var y=tu.callback;if(typeof y==="function"){tu.callback=null,uu=tu.priorityLevel;var l=y(tu.expirationTime<=u);u=$0.unstable_now(),typeof l==="function"?tu.callback=l:tu===F1(Y1)&&f8(Y1),v2(u)}else f8(Y1);tu=F1(Y1)}if(tu!==null)var $=!0;else{var j=F1(U_);j!==null&&p2(h2,j.startTime-u),$=!1}return $}finally{tu=null,uu=_,u8=!1}}var _8=!1,d6=null,P3=-1,iQ=5,gQ=-1;function nQ(){return $0.unstable_now()-gQf||125y?(f.sortIndex=_,C2(U_,f),F1(Y1)===null&&f===F1(U_)&&(M3?(mQ(P3),P3=-1):M3=!0,p2(h2,_-y))):(f.sortIndex=l,C2(Y1,f),Uy||u8||(Uy=!0,c2(I2))),f};$0.unstable_shouldYield=nQ;$0.unstable_wrapCallback=function(f){var u=uu;return function(){var _=uu;uu=u;try{return f.apply(this,arguments)}finally{uu=_}}}});var oQ=Pu((GP,sQ)=>{sQ.exports=tQ()});var dW=Pu((bu)=>{var XH=c0(),xu=oQ();function Ff(f){for(var u="https://reactjs.org/docs/error-decoder.html?invariant="+f,_=1;_"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),A9=Object.prototype.hasOwnProperty,NH=/^[: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]*$/,aQ={},dQ={};function LH(f){if(A9.call(dQ,f))return!0;if(A9.call(aQ,f))return!1;if(NH.test(f))return dQ[f]=!0;return aQ[f]=!0,!1}function YH(f,u,_,y){if(_!==null&&_.type===0)return!1;switch(typeof u){case"function":case"symbol":return!0;case"boolean":if(y)return!1;if(_!==null)return!_.acceptsBooleans;return f=f.toLowerCase().slice(0,5),f!=="data-"&&f!=="aria-";default:return!1}}function BH(f,u,_,y){if(u===null||typeof u>"u"||YH(f,u,_,y))return!0;if(y)return!1;if(_!==null)switch(_.type){case 3:return!u;case 4:return u===!1;case 5:return isNaN(u);case 6:return isNaN(u)||1>u}return!1}function Ku(f,u,_,y,l,$,j){this.acceptsBooleans=u===2||u===3||u===4,this.attributeName=y,this.attributeNamespace=l,this.mustUseProperty=_,this.propertyName=f,this.type=u,this.sanitizeURL=$,this.removeEmptyString=j}var t0={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(f){t0[f]=new Ku(f,0,!1,f,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(f){var u=f[0];t0[u]=new Ku(u,1,!1,f[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(f){t0[f]=new Ku(f,2,!1,f.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(f){t0[f]=new Ku(f,2,!1,f,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(f){t0[f]=new Ku(f,3,!1,f.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(f){t0[f]=new Ku(f,3,!0,f,null,!1,!1)});["capture","download"].forEach(function(f){t0[f]=new Ku(f,4,!1,f,null,!1,!1)});["cols","rows","size","span"].forEach(function(f){t0[f]=new Ku(f,6,!1,f,null,!1,!1)});["rowSpan","start"].forEach(function(f){t0[f]=new Ku(f,5,!1,f.toLowerCase(),null,!1,!1)});var l7=/[\-:]([a-z])/g;function $7(f){return f[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(f){var u=f.replace(l7,$7);t0[u]=new Ku(u,1,!1,f,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(f){var u=f.replace(l7,$7);t0[u]=new Ku(u,1,!1,f,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(f){var u=f.replace(l7,$7);t0[u]=new Ku(u,1,!1,f,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(f){t0[f]=new Ku(f,1,!1,f.toLowerCase(),null,!1,!1)});t0.xlinkHref=new Ku("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(f){t0[f]=new Ku(f,1,!1,f.toLowerCase(),null,!0,!0)});function j7(f,u,_,y){var l=t0.hasOwnProperty(u)?t0[u]:null;if(l!==null?l.type!==0:y||!(2J||l[j]!==$[J]){var F=` +`+l[j].replace(" at new "," at ");return f.displayName&&F.includes("")&&(F=F.replace("",f.displayName)),F}while(1<=j&&0<=J);break}}}finally{m2=!1,Error.prepareStackTrace=_}return(f=f?f.displayName||f.name:"")?I3(f):""}function DH(f){switch(f.tag){case 5:return I3(f.type);case 16:return I3("Lazy");case 13:return I3("Suspense");case 19:return I3("SuspenseList");case 0:case 2:case 15:return f=i2(f.type,!1),f;case 11:return f=i2(f.type.render,!1),f;case 1:return f=i2(f.type,!0),f;default:return""}}function z9(f){if(f==null)return null;if(typeof f==="function")return f.displayName||f.name||null;if(typeof f==="string")return f;switch(f){case Fl:return"Fragment";case Jl:return"Portal";case U9:return"Profiler";case J7:return"StrictMode";case W9:return"Suspense";case G9:return"SuspenseList"}if(typeof f==="object")switch(f.$$typeof){case yU:return(f.displayName||"Context")+".Consumer";case _U:return(f._context.displayName||"Context")+".Provider";case F7:var u=f.render;return f=f.displayName,f||(f=u.displayName||u.name||"",f=f!==""?"ForwardRef("+f+")":"ForwardRef"),f;case Q7:return u=f.displayName||null,u!==null?u:z9(f.type)||"Memo";case G_:u=f._payload,f=f._init;try{return z9(f(u))}catch(_){}}return null}function wH(f){var u=f.type;switch(f.tag){case 24:return"Cache";case 9:return(u.displayName||"Context")+".Consumer";case 10:return(u._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return f=u.render,f=f.displayName||f.name||"",u.displayName||(f!==""?"ForwardRef("+f+")":"ForwardRef");case 7:return"Fragment";case 5:return u;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return z9(u);case 8:return u===J7?"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 u==="function")return u.displayName||u.name||null;if(typeof u==="string")return u}return null}function D_(f){switch(typeof f){case"boolean":case"number":case"string":case"undefined":return f;case"object":return f;default:return""}}function $U(f){var u=f.type;return(f=f.nodeName)&&f.toLowerCase()==="input"&&(u==="checkbox"||u==="radio")}function TH(f){var u=$U(f)?"checked":"value",_=Object.getOwnPropertyDescriptor(f.constructor.prototype,u),y=""+f[u];if(!f.hasOwnProperty(u)&&typeof _<"u"&&typeof _.get==="function"&&typeof _.set==="function"){var{get:l,set:$}=_;return Object.defineProperty(f,u,{configurable:!0,get:function(){return l.call(this)},set:function(j){y=""+j,$.call(this,j)}}),Object.defineProperty(f,u,{enumerable:_.enumerable}),{getValue:function(){return y},setValue:function(j){y=""+j},stopTracking:function(){f._valueTracker=null,delete f[u]}}}}function l8(f){f._valueTracker||(f._valueTracker=TH(f))}function jU(f){if(!f)return!1;var u=f._valueTracker;if(!u)return!0;var _=u.getValue(),y="";return f&&(y=$U(f)?f.checked?"true":"false":f.value),f=y,f!==_?(u.setValue(f),!0):!1}function T8(f){if(f=f||(typeof document<"u"?document:void 0),typeof f>"u")return null;try{return f.activeElement||f.body}catch(u){return f.body}}function K9(f,u){var _=u.checked;return E0({},u,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:_!=null?_:f._wrapperState.initialChecked})}function fA(f,u){var _=u.defaultValue==null?"":u.defaultValue,y=u.checked!=null?u.checked:u.defaultChecked;_=D_(u.value!=null?u.value:_),f._wrapperState={initialChecked:y,initialValue:_,controlled:u.type==="checkbox"||u.type==="radio"?u.checked!=null:u.value!=null}}function JU(f,u){u=u.checked,u!=null&&j7(f,"checked",u,!1)}function Z9(f,u){JU(f,u);var _=D_(u.value),y=u.type;if(_!=null)if(y==="number"){if(_===0&&f.value===""||f.value!=_)f.value=""+_}else f.value!==""+_&&(f.value=""+_);else if(y==="submit"||y==="reset"){f.removeAttribute("value");return}u.hasOwnProperty("value")?q9(f,u.type,_):u.hasOwnProperty("defaultValue")&&q9(f,u.type,D_(u.defaultValue)),u.checked==null&&u.defaultChecked!=null&&(f.defaultChecked=!!u.defaultChecked)}function uA(f,u,_){if(u.hasOwnProperty("value")||u.hasOwnProperty("defaultValue")){var y=u.type;if(!(y!=="submit"&&y!=="reset"||u.value!==void 0&&u.value!==null))return;u=""+f._wrapperState.initialValue,_||u===f.value||(f.value=u),f.defaultValue=u}_=f.name,_!==""&&(f.name=""),f.defaultChecked=!!f._wrapperState.initialChecked,_!==""&&(f.name=_)}function q9(f,u,_){if(u!=="number"||T8(f.ownerDocument)!==f)_==null?f.defaultValue=""+f._wrapperState.initialValue:f.defaultValue!==""+_&&(f.defaultValue=""+_)}var c3=Array.isArray;function Hl(f,u,_,y){if(f=f.options,u){u={};for(var l=0;l<_.length;l++)u["$"+_[l]]=!0;for(_=0;_"+u.valueOf().toString()+"";for(u=$8.firstChild;f.firstChild;)f.removeChild(f.firstChild);for(;u.firstChild;)f.appendChild(u.firstChild)}});function l$(f,u){if(u){var _=f.firstChild;if(_&&_===f.lastChild&&_.nodeType===3){_.nodeValue=u;return}}f.textContent=u}var t3={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},rH=["Webkit","ms","Moz","O"];Object.keys(t3).forEach(function(f){rH.forEach(function(u){u=u+f.charAt(0).toUpperCase()+f.substring(1),t3[u]=t3[f]})});function UU(f,u,_){return u==null||typeof u==="boolean"||u===""?"":_||typeof u!=="number"||u===0||t3.hasOwnProperty(f)&&t3[f]?(""+u).trim():u+"px"}function WU(f,u){f=f.style;for(var _ in u)if(u.hasOwnProperty(_)){var y=_.indexOf("--")===0,l=UU(_,u[_],y);_==="float"&&(_="cssFloat"),y?f.setProperty(_,l):f[_]=l}}var MH=E0({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 V9(f,u){if(u){if(MH[f]&&(u.children!=null||u.dangerouslySetInnerHTML!=null))throw Error(Ff(137,f));if(u.dangerouslySetInnerHTML!=null){if(u.children!=null)throw Error(Ff(60));if(typeof u.dangerouslySetInnerHTML!=="object"||!("__html"in u.dangerouslySetInnerHTML))throw Error(Ff(61))}if(u.style!=null&&typeof u.style!=="object")throw Error(Ff(62))}}function O9(f,u){if(f.indexOf("-")===-1)return typeof u.is==="string";switch(f){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 X9=null;function A7(f){return f=f.target||f.srcElement||window,f.correspondingUseElement&&(f=f.correspondingUseElement),f.nodeType===3?f.parentNode:f}var N9=null,Vl=null,Ol=null;function lA(f){if(f=X$(f)){if(typeof N9!=="function")throw Error(Ff(280));var u=f.stateNode;u&&(u=y4(u),N9(f.stateNode,f.type,u))}}function GU(f){Vl?Ol?Ol.push(f):Ol=[f]:Vl=f}function zU(){if(Vl){var f=Vl,u=Ol;if(Ol=Vl=null,lA(f),u)for(f=0;f>>=0,f===0?32:31-(pH(f)/kH|0)|0}var j8=64,J8=4194304;function p3(f){switch(f&-f){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 f&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return f&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return f}}function S8(f,u){var _=f.pendingLanes;if(_===0)return 0;var y=0,l=f.suspendedLanes,$=f.pingedLanes,j=_&268435455;if(j!==0){var J=j&~l;J!==0?y=p3(J):($&=j,$!==0&&(y=p3($)))}else j=_&~l,j!==0?y=p3(j):$!==0&&(y=p3($));if(y===0)return 0;if(u!==0&&u!==y&&(u&l)===0&&(l=y&-y,$=u&-u,l>=$||l===16&&($&4194240)!==0))return u;if((y&4)!==0&&(y|=_&16),u=f.entangledLanes,u!==0)for(f=f.entanglements,u&=y;0_;_++)u.push(f);return u}function V$(f,u,_){f.pendingLanes|=u,u!==536870912&&(f.suspendedLanes=0,f.pingedLanes=0),f=f.eventTimes,u=31-G1(u),f[u]=_}function nH(f,u){var _=f.pendingLanes&~u;f.pendingLanes=u,f.suspendedLanes=0,f.pingedLanes=0,f.expiredLanes&=u,f.mutableReadLanes&=u,f.entangledLanes&=u,u=f.entanglements;var y=f.eventTimes;for(f=f.expirationTimes;0<_;){var l=31-G1(_),$=1<=o3),GA=String.fromCharCode(32),zA=!1;function CU(f,u){switch(f){case"keyup":return OV.indexOf(u.keyCode)!==-1;case"keydown":return u.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function RU(f){return f=f.detail,typeof f==="object"&&"data"in f?f.data:null}var Ql=!1;function NV(f,u){switch(f){case"compositionend":return RU(u);case"keypress":if(u.which!==32)return null;return zA=!0,GA;case"textInput":return f=u.data,f===GA&&zA?null:f;default:return null}}function LV(f,u){if(Ql)return f==="compositionend"||!E7&&CU(f,u)?(f=PU(),H8=K7=q_=null,Ql=!1,f):null;switch(f){case"paste":return null;case"keypress":if(!(u.ctrlKey||u.altKey||u.metaKey)||u.ctrlKey&&u.altKey){if(u.char&&1=u)return{node:_,offset:u-f};f=y}f:{for(;_;){if(_.nextSibling){_=_.nextSibling;break f}_=_.parentNode}_=void 0}_=qA(_)}}function hU(f,u){return f&&u?f===u?!0:f&&f.nodeType===3?!1:u&&u.nodeType===3?hU(f,u.parentNode):("contains"in f)?f.contains(u):f.compareDocumentPosition?!!(f.compareDocumentPosition(u)&16):!1:!1}function IU(){for(var f=window,u=T8();u instanceof f.HTMLIFrameElement;){try{var _=typeof u.contentWindow.location.href==="string"}catch(y){_=!1}if(_)f=u.contentWindow;else break;u=T8(f.document)}return u}function H7(f){var u=f&&f.nodeName&&f.nodeName.toLowerCase();return u&&(u==="input"&&(f.type==="text"||f.type==="search"||f.type==="tel"||f.type==="url"||f.type==="password")||u==="textarea"||f.contentEditable==="true")}function SV(f){var u=IU(),_=f.focusedElem,y=f.selectionRange;if(u!==_&&_&&_.ownerDocument&&hU(_.ownerDocument.documentElement,_)){if(y!==null&&H7(_)){if(u=y.start,f=y.end,f===void 0&&(f=u),"selectionStart"in _)_.selectionStart=u,_.selectionEnd=Math.min(f,_.value.length);else if(f=(u=_.ownerDocument||document)&&u.defaultView||window,f.getSelection){f=f.getSelection();var l=_.textContent.length,$=Math.min(y.start,l);y=y.end===void 0?$:Math.min(y.end,l),!f.extend&&$>y&&(l=y,y=$,$=l),l=EA(_,$);var j=EA(_,y);l&&j&&(f.rangeCount!==1||f.anchorNode!==l.node||f.anchorOffset!==l.offset||f.focusNode!==j.node||f.focusOffset!==j.offset)&&(u=u.createRange(),u.setStart(l.node,l.offset),f.removeAllRanges(),$>y?(f.addRange(u),f.extend(j.node,j.offset)):(u.setEnd(j.node,j.offset),f.addRange(u)))}}u=[];for(f=_;f=f.parentNode;)f.nodeType===1&&u.push({element:f,left:f.scrollLeft,top:f.scrollTop});typeof _.focus==="function"&&_.focus();for(_=0;_=document.documentMode,Al=null,T9=null,d3=null,r9=!1;function HA(f,u,_){var y=_.window===_?_.document:_.nodeType===9?_:_.ownerDocument;r9||Al==null||Al!==T8(y)||(y=Al,("selectionStart"in y)&&H7(y)?y={start:y.selectionStart,end:y.selectionEnd}:(y=(y.ownerDocument&&y.ownerDocument.defaultView||window).getSelection(),y={anchorNode:y.anchorNode,anchorOffset:y.anchorOffset,focusNode:y.focusNode,focusOffset:y.focusOffset}),d3&&A$(d3,y)||(d3=y,y=x8(T9,"onSelect"),0Gl||(f.current=b9[Gl],b9[Gl]=null,Gl--)}function j0(f,u){Gl++,b9[Gl]=f.current,f.current=u}var w_={},$u=r_(w_),Xu=r_(!1),Vy=w_;function Bl(f,u){var _=f.type.contextTypes;if(!_)return w_;var y=f.stateNode;if(y&&y.__reactInternalMemoizedUnmaskedChildContext===u)return y.__reactInternalMemoizedMaskedChildContext;var l={},$;for($ in _)l[$]=u[$];return y&&(f=f.stateNode,f.__reactInternalMemoizedUnmaskedChildContext=u,f.__reactInternalMemoizedMaskedChildContext=l),l}function Nu(f){return f=f.childContextTypes,f!==null&&f!==void 0}function b8(){U0(Xu),U0($u)}function BA(f,u,_){if($u.current!==w_)throw Error(Ff(168));j0($u,u),j0(Xu,_)}function sU(f,u,_){var y=f.stateNode;if(u=u.childContextTypes,typeof y.getChildContext!=="function")return _;y=y.getChildContext();for(var l in y)if(!(l in u))throw Error(Ff(108,wH(f)||"Unknown",l));return E0({},_,y)}function h8(f){return f=(f=f.stateNode)&&f.__reactInternalMemoizedMergedChildContext||w_,Vy=$u.current,j0($u,f),j0(Xu,Xu.current),!0}function DA(f,u,_){var y=f.stateNode;if(!y)throw Error(Ff(169));_?(f=sU(f,u,Vy),y.__reactInternalMemoizedMergedChildContext=f,U0(Xu),U0($u),j0($u,f)):U0(Xu),j0(Xu,_)}var p1=null,l4=!1,u9=!1;function oU(f){p1===null?p1=[f]:p1.push(f)}function kV(f){l4=!0,oU(f)}function M_(){if(!u9&&p1!==null){u9=!0;var f=0,u=f0;try{var _=p1;for(f0=1;f<_.length;f++){var y=_[f];do y=y(!0);while(y!==null)}p1=null,l4=!1}catch(l){throw p1!==null&&(p1=p1.slice(f+1)),OU(U7,M_),l}finally{f0=u,u9=!1}}return null}var zl=[],Kl=0,I8=null,c8=0,su=[],ou=0,Oy=null,k1=1,m1="";function Gy(f,u){zl[Kl++]=c8,zl[Kl++]=I8,I8=f,c8=u}function aU(f,u,_){su[ou++]=k1,su[ou++]=m1,su[ou++]=Oy,Oy=f;var y=k1;f=m1;var l=32-G1(y)-1;y&=~(1<>=j,l-=j,k1=1<<32-G1(u)+l|_<D?(x=N,N=null):x=N.sibling;var c=W(z,N,Z[D],V);if(c===null){N===null&&(N=x);break}f&&N&&c.alternate===null&&u(z,N),q=$(c,q,D),r===null?L=c:r.sibling=c,r=c,N=x}if(D===Z.length)return _(z,N),G0&&Gy(z,D),L;if(N===null){for(;DD?(x=N,N=null):x=N.sibling;var v=W(z,N,c.value,V);if(v===null){N===null&&(N=x);break}f&&N&&v.alternate===null&&u(z,N),q=$(v,q,D),r===null?L=v:r.sibling=v,r=v,N=x}if(c.done)return _(z,N),G0&&Gy(z,D),L;if(N===null){for(;!c.done;D++,c=Z.next())c=G(z,c.value,V),c!==null&&(q=$(c,q,D),r===null?L=c:r.sibling=c,r=c);return G0&&Gy(z,D),L}for(N=y(z,N);!c.done;D++,c=Z.next())c=K(N,z,D,c.value,V),c!==null&&(f&&c.alternate!==null&&N.delete(c.key===null?D:c.key),q=$(c,q,D),r===null?L=c:r.sibling=c,r=c);return f&&N.forEach(function(C){return u(z,C)}),G0&&Gy(z,D),L}function O(z,q,Z,V){if(typeof Z==="object"&&Z!==null&&Z.type===Fl&&Z.key===null&&(Z=Z.props.children),typeof Z==="object"&&Z!==null){switch(Z.$$typeof){case y8:f:{for(var L=Z.key,r=q;r!==null;){if(r.key===L){if(L=Z.type,L===Fl){if(r.tag===7){_(z,r.sibling),q=l(r,Z.props.children),q.return=z,z=q;break f}}else if(r.elementType===L||typeof L==="object"&&L!==null&&L.$$typeof===G_&&rA(L)===r.type){_(z,r.sibling),q=l(r,Z.props),q.ref=v3(z,r,Z),q.return=z,z=q;break f}_(z,r);break}else u(z,r);r=r.sibling}Z.type===Fl?(q=Hy(Z.props.children,z.mode,V,Z.key),q.return=z,z=q):(V=w8(Z.type,Z.key,Z.props,null,z.mode,V),V.ref=v3(z,q,Z),V.return=z,z=V)}return j(z);case Jl:f:{for(r=Z.key;q!==null;){if(q.key===r)if(q.tag===4&&q.stateNode.containerInfo===Z.containerInfo&&q.stateNode.implementation===Z.implementation){_(z,q.sibling),q=l(q,Z.children||[]),q.return=z,z=q;break f}else{_(z,q);break}else u(z,q);q=q.sibling}q=Q9(Z,z.mode,V),q.return=z,z=q}return j(z);case G_:return r=Z._init,O(z,q,r(Z._payload),V)}if(c3(Z))return E(z,q,Z,V);if(S3(Z))return H(z,q,Z,V);z8(z,Z)}return typeof Z==="string"&&Z!==""||typeof Z==="number"?(Z=""+Z,q!==null&&q.tag===6?(_(z,q.sibling),q=l(q,Z),q.return=z,z=q):(_(z,q),q=F9(Z,z.mode,V),q.return=z,z=q),j(z)):_(z,q)}return O}var wl=fW(!0),uW=fW(!1),p8=r_(null),k8=null,Zl=null,N7=null;function L7(){N7=Zl=k8=null}function Y7(f){var u=p8.current;U0(p8),f._currentValue=u}function c9(f,u,_){for(;f!==null;){var y=f.alternate;if((f.childLanes&u)!==u?(f.childLanes|=u,y!==null&&(y.childLanes|=u)):y!==null&&(y.childLanes&u)!==u&&(y.childLanes|=u),f===_)break;f=f.return}}function Nl(f,u){k8=f,N7=Zl=null,f=f.dependencies,f!==null&&f.firstContext!==null&&((f.lanes&u)!==0&&(Ou=!0),f.firstContext=null)}function eu(f){var u=f._currentValue;if(N7!==f)if(f={context:f,memoizedValue:u,next:null},Zl===null){if(k8===null)throw Error(Ff(308));Zl=f,k8.dependencies={lanes:0,firstContext:f}}else Zl=Zl.next=f;return u}var Zy=null;function B7(f){Zy===null?Zy=[f]:Zy.push(f)}function _W(f,u,_,y){var l=u.interleaved;return l===null?(_.next=_,B7(u)):(_.next=l.next,l.next=_),u.interleaved=_,t1(f,y)}function t1(f,u){f.lanes|=u;var _=f.alternate;_!==null&&(_.lanes|=u),_=f;for(f=f.return;f!==null;)f.childLanes|=u,_=f.alternate,_!==null&&(_.childLanes|=u),_=f,f=f.return;return _.tag===3?_.stateNode:null}var z_=!1;function D7(f){f.updateQueue={baseState:f.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function yW(f,u){f=f.updateQueue,u.updateQueue===f&&(u.updateQueue={baseState:f.baseState,firstBaseUpdate:f.firstBaseUpdate,lastBaseUpdate:f.lastBaseUpdate,shared:f.shared,effects:f.effects})}function i1(f,u){return{eventTime:f,lane:u,tag:0,payload:null,callback:null,next:null}}function N_(f,u,_){var y=f.updateQueue;if(y===null)return null;if(y=y.shared,(gf&2)!==0){var l=y.pending;return l===null?u.next=u:(u.next=l.next,l.next=u),y.pending=u,t1(f,_)}return l=y.interleaved,l===null?(u.next=u,B7(y)):(u.next=l.next,l.next=u),y.interleaved=u,t1(f,_)}function X8(f,u,_){if(u=u.updateQueue,u!==null&&(u=u.shared,(_&4194240)!==0)){var y=u.lanes;y&=f.pendingLanes,_|=y,u.lanes=_,W7(f,_)}}function MA(f,u){var{updateQueue:_,alternate:y}=f;if(y!==null&&(y=y.updateQueue,_===y)){var l=null,$=null;if(_=_.firstBaseUpdate,_!==null){do{var j={eventTime:_.eventTime,lane:_.lane,tag:_.tag,payload:_.payload,callback:_.callback,next:null};$===null?l=$=j:$=$.next=j,_=_.next}while(_!==null);$===null?l=$=u:$=$.next=u}else l=$=u;_={baseState:y.baseState,firstBaseUpdate:l,lastBaseUpdate:$,shared:y.shared,effects:y.effects},f.updateQueue=_;return}f=_.lastBaseUpdate,f===null?_.firstBaseUpdate=u:f.next=u,_.lastBaseUpdate=u}function m8(f,u,_,y){var l=f.updateQueue;z_=!1;var{firstBaseUpdate:$,lastBaseUpdate:j}=l,J=l.shared.pending;if(J!==null){l.shared.pending=null;var F=J,A=F.next;F.next=null,j===null?$=A:j.next=A,j=F;var U=f.alternate;U!==null&&(U=U.updateQueue,J=U.lastBaseUpdate,J!==j&&(J===null?U.firstBaseUpdate=A:J.next=A,U.lastBaseUpdate=F))}if($!==null){var G=l.baseState;j=0,U=A=F=null,J=$;do{var{lane:W,eventTime:K}=J;if((y&W)===W){U!==null&&(U=U.next={eventTime:K,lane:0,tag:J.tag,payload:J.payload,callback:J.callback,next:null});f:{var E=f,H=J;switch(W=u,K=_,H.tag){case 1:if(E=H.payload,typeof E==="function"){G=E.call(K,G,W);break f}G=E;break f;case 3:E.flags=E.flags&-65537|128;case 0:if(E=H.payload,W=typeof E==="function"?E.call(K,G,W):E,W===null||W===void 0)break f;G=E0({},G,W);break f;case 2:z_=!0}}J.callback!==null&&J.lane!==0&&(f.flags|=64,W=l.effects,W===null?l.effects=[J]:W.push(J))}else K={eventTime:K,lane:W,tag:J.tag,payload:J.payload,callback:J.callback,next:null},U===null?(A=U=K,F=G):U=U.next=K,j|=W;if(J=J.next,J===null)if(J=l.shared.pending,J===null)break;else W=J,J=W.next,W.next=null,l.lastBaseUpdate=W,l.shared.pending=null}while(1);if(U===null&&(F=G),l.baseState=F,l.firstBaseUpdate=A,l.lastBaseUpdate=U,u=l.shared.interleaved,u!==null){l=u;do j|=l.lane,l=l.next;while(l!==u)}else $===null&&(l.shared.lanes=0);Ny|=j,f.lanes=j,f.memoizedState=G}}function PA(f,u,_){if(f=u.effects,u.effects=null,f!==null)for(u=0;u_?_:4,f(!0);var y=y9.transition;y9.transition={};try{f(!1),u()}finally{f0=_,y9.transition=y}}function VW(){return f1().memoizedState}function nV(f,u,_){var y=Y_(f);if(_={lane:y,action:_,hasEagerState:!1,eagerState:null,next:null},OW(f))XW(u,_);else if(_=_W(f,u,_,y),_!==null){var l=zu();z1(_,f,y,l),NW(_,u,y)}}function tV(f,u,_){var y=Y_(f),l={lane:y,action:_,hasEagerState:!1,eagerState:null,next:null};if(OW(f))XW(u,l);else{var $=f.alternate;if(f.lanes===0&&($===null||$.lanes===0)&&($=u.lastRenderedReducer,$!==null))try{var j=u.lastRenderedState,J=$(j,_);if(l.hasEagerState=!0,l.eagerState=J,K1(J,j)){var F=u.interleaved;F===null?(l.next=l,B7(u)):(l.next=F.next,F.next=l),u.interleaved=l;return}}catch(A){}finally{}_=_W(f,u,l,y),_!==null&&(l=zu(),z1(_,f,y,l),NW(_,u,y))}}function OW(f){var u=f.alternate;return f===q0||u!==null&&u===q0}function XW(f,u){e3=g8=!0;var _=f.pending;_===null?u.next=u:(u.next=_.next,_.next=u),f.pending=u}function NW(f,u,_){if((_&4194240)!==0){var y=u.lanes;y&=f.pendingLanes,_|=y,u.lanes=_,W7(f,_)}}var n8={readContext:eu,useCallback:_u,useContext:_u,useEffect:_u,useImperativeHandle:_u,useInsertionEffect:_u,useLayoutEffect:_u,useMemo:_u,useReducer:_u,useRef:_u,useState:_u,useDebugValue:_u,useDeferredValue:_u,useTransition:_u,useMutableSource:_u,useSyncExternalStore:_u,useId:_u,unstable_isNewReconciler:!1},sV={readContext:eu,useCallback:function(f,u){return D1().memoizedState=[f,u===void 0?null:u],f},useContext:eu,useEffect:CA,useImperativeHandle:function(f,u,_){return _=_!==null&&_!==void 0?_.concat([f]):null,L8(4194308,4,KW.bind(null,u,f),_)},useLayoutEffect:function(f,u){return L8(4194308,4,f,u)},useInsertionEffect:function(f,u){return L8(4,2,f,u)},useMemo:function(f,u){var _=D1();return u=u===void 0?null:u,f=f(),_.memoizedState=[f,u],f},useReducer:function(f,u,_){var y=D1();return u=_!==void 0?_(u):u,y.memoizedState=y.baseState=u,f={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:f,lastRenderedState:u},y.queue=f,f=f.dispatch=nV.bind(null,q0,f),[y.memoizedState,f]},useRef:function(f){var u=D1();return f={current:f},u.memoizedState=f},useState:SA,useDebugValue:R7,useDeferredValue:function(f){return D1().memoizedState=f},useTransition:function(){var f=SA(!1),u=f[0];return f=gV.bind(null,f[1]),D1().memoizedState=f,[u,f]},useMutableSource:function(){},useSyncExternalStore:function(f,u,_){var y=q0,l=D1();if(G0){if(_===void 0)throw Error(Ff(407));_=_()}else{if(_=u(),k0===null)throw Error(Ff(349));(Xy&30)!==0||JW(y,u,_)}l.memoizedState=_;var $={value:_,getSnapshot:u};return l.queue=$,CA(QW.bind(null,y,$,f),[f]),y.flags|=2048,E$(9,FW.bind(null,y,$,_,u),void 0,null),_},useId:function(){var f=D1(),u=k0.identifierPrefix;if(G0){var _=m1,y=k1;_=(y&~(1<<32-G1(y)-1)).toString(32)+_,u=":"+u+"R"+_,_=Z$++,0<_&&(u+="H"+_.toString(32)),u+=":"}else _=iV++,u=":"+u+"r"+_.toString(32)+":";return f.memoizedState=u},unstable_isNewReconciler:!1},oV={readContext:eu,useCallback:qW,useContext:eu,useEffect:C7,useImperativeHandle:ZW,useInsertionEffect:GW,useLayoutEffect:zW,useMemo:EW,useReducer:l9,useRef:WW,useState:function(){return l9(q$)},useDebugValue:R7,useDeferredValue:function(f){var u=f1();return HW(u,S0.memoizedState,f)},useTransition:function(){var f=l9(q$)[0],u=f1().memoizedState;return[f,u]},useMutableSource:$W,useSyncExternalStore:jW,useId:VW,unstable_isNewReconciler:!1},aV={readContext:eu,useCallback:qW,useContext:eu,useEffect:C7,useImperativeHandle:ZW,useInsertionEffect:GW,useLayoutEffect:zW,useMemo:EW,useReducer:$9,useRef:WW,useState:function(){return $9(q$)},useDebugValue:R7,useDeferredValue:function(f){var u=f1();return S0===null?u.memoizedState=f:HW(u,S0.memoizedState,f)},useTransition:function(){var f=$9(q$)[0],u=f1().memoizedState;return[f,u]},useMutableSource:$W,useSyncExternalStore:jW,useId:VW,unstable_isNewReconciler:!1};function A1(f,u){if(f&&f.defaultProps){u=E0({},u),f=f.defaultProps;for(var _ in f)u[_]===void 0&&(u[_]=f[_]);return u}return u}function p9(f,u,_,y){u=f.memoizedState,_=_(y,u),_=_===null||_===void 0?u:E0({},u,_),f.memoizedState=_,f.lanes===0&&(f.updateQueue.baseState=_)}var j4={isMounted:function(f){return(f=f._reactInternals)?By(f)===f:!1},enqueueSetState:function(f,u,_){f=f._reactInternals;var y=zu(),l=Y_(f),$=i1(y,l);$.payload=u,_!==void 0&&_!==null&&($.callback=_),u=N_(f,$,l),u!==null&&(z1(u,f,l,y),X8(u,f,l))},enqueueReplaceState:function(f,u,_){f=f._reactInternals;var y=zu(),l=Y_(f),$=i1(y,l);$.tag=1,$.payload=u,_!==void 0&&_!==null&&($.callback=_),u=N_(f,$,l),u!==null&&(z1(u,f,l,y),X8(u,f,l))},enqueueForceUpdate:function(f,u){f=f._reactInternals;var _=zu(),y=Y_(f),l=i1(_,y);l.tag=2,u!==void 0&&u!==null&&(l.callback=u),u=N_(f,l,y),u!==null&&(z1(u,f,y,_),X8(u,f,y))}};function RA(f,u,_,y,l,$,j){return f=f.stateNode,typeof f.shouldComponentUpdate==="function"?f.shouldComponentUpdate(y,$,j):u.prototype&&u.prototype.isPureReactComponent?!A$(_,y)||!A$(l,$):!0}function LW(f,u,_){var y=!1,l=w_,$=u.contextType;return typeof $==="object"&&$!==null?$=eu($):(l=Nu(u)?Vy:$u.current,y=u.contextTypes,$=(y=y!==null&&y!==void 0)?Bl(f,l):w_),u=new u(_,$),f.memoizedState=u.state!==null&&u.state!==void 0?u.state:null,u.updater=j4,f.stateNode=u,u._reactInternals=f,y&&(f=f.stateNode,f.__reactInternalMemoizedUnmaskedChildContext=l,f.__reactInternalMemoizedMaskedChildContext=$),u}function xA(f,u,_,y){f=u.state,typeof u.componentWillReceiveProps==="function"&&u.componentWillReceiveProps(_,y),typeof u.UNSAFE_componentWillReceiveProps==="function"&&u.UNSAFE_componentWillReceiveProps(_,y),u.state!==f&&j4.enqueueReplaceState(u,u.state,null)}function k9(f,u,_,y){var l=f.stateNode;l.props=_,l.state=f.memoizedState,l.refs={},D7(f);var $=u.contextType;typeof $==="object"&&$!==null?l.context=eu($):($=Nu(u)?Vy:$u.current,l.context=Bl(f,$)),l.state=f.memoizedState,$=u.getDerivedStateFromProps,typeof $==="function"&&(p9(f,u,$,_),l.state=f.memoizedState),typeof u.getDerivedStateFromProps==="function"||typeof l.getSnapshotBeforeUpdate==="function"||typeof l.UNSAFE_componentWillMount!=="function"&&typeof l.componentWillMount!=="function"||(u=l.state,typeof l.componentWillMount==="function"&&l.componentWillMount(),typeof l.UNSAFE_componentWillMount==="function"&&l.UNSAFE_componentWillMount(),u!==l.state&&j4.enqueueReplaceState(l,l.state,null),m8(f,_,l,y),l.state=f.memoizedState),typeof l.componentDidMount==="function"&&(f.flags|=4194308)}function rl(f,u){try{var _="",y=u;do _+=DH(y),y=y.return;while(y);var l=_}catch($){l=` +Error generating stack: `+$.message+` +`+$.stack}return{value:f,source:u,stack:l,digest:null}}function j9(f,u,_){return{value:f,source:null,stack:_!=null?_:null,digest:u!=null?u:null}}function m9(f,u){try{console.error(u.value)}catch(_){setTimeout(function(){throw _})}}var dV=typeof WeakMap==="function"?WeakMap:Map;function YW(f,u,_){_=i1(-1,_),_.tag=3,_.payload={element:null};var y=u.value;return _.callback=function(){s8||(s8=!0,f7=y),m9(f,u)},_}function BW(f,u,_){_=i1(-1,_),_.tag=3;var y=f.type.getDerivedStateFromError;if(typeof y==="function"){var l=u.value;_.payload=function(){return y(l)},_.callback=function(){m9(f,u)}}var $=f.stateNode;return $!==null&&typeof $.componentDidCatch==="function"&&(_.callback=function(){m9(f,u),typeof y!=="function"&&(L_===null?L_=new Set([this]):L_.add(this));var j=u.stack;this.componentDidCatch(u.value,{componentStack:j!==null?j:""})}),_}function vA(f,u,_){var y=f.pingCache;if(y===null){y=f.pingCache=new dV;var l=new Set;y.set(u,l)}else l=y.get(u),l===void 0&&(l=new Set,y.set(u,l));l.has(_)||(l.add(_),f=WO.bind(null,f,u,_),u.then(f,f))}function bA(f){do{var u;if(u=f.tag===13)u=f.memoizedState,u=u!==null?u.dehydrated!==null?!0:!1:!0;if(u)return f;f=f.return}while(f!==null);return null}function hA(f,u,_,y,l){if((f.mode&1)===0)return f===u?f.flags|=65536:(f.flags|=128,_.flags|=131072,_.flags&=-52805,_.tag===1&&(_.alternate===null?_.tag=17:(u=i1(-1,1),u.tag=2,N_(_,u,1))),_.lanes|=1),f;return f.flags|=65536,f.lanes=l,f}var eV=o1.ReactCurrentOwner,Ou=!1;function Gu(f,u,_,y){u.child=f===null?uW(u,null,_,y):wl(u,f.child,_,y)}function IA(f,u,_,y,l){_=_.render;var $=u.ref;if(Nl(u,l),y=P7(f,u,_,y,$,l),_=S7(),f!==null&&!Ou)return u.updateQueue=f.updateQueue,u.flags&=-2053,f.lanes&=~l,s1(f,u,l);return G0&&_&&V7(u),u.flags|=1,Gu(f,u,y,l),u.child}function cA(f,u,_,y,l){if(f===null){var $=_.type;if(typeof $==="function"&&!k7($)&&$.defaultProps===void 0&&_.compare===null&&_.defaultProps===void 0)return u.tag=15,u.type=$,DW(f,u,$,y,l);return f=w8(_.type,null,y,u,u.mode,l),f.ref=u.ref,f.return=u,u.child=f}if($=f.child,(f.lanes&l)===0){var j=$.memoizedProps;if(_=_.compare,_=_!==null?_:A$,_(j,y)&&f.ref===u.ref)return s1(f,u,l)}return u.flags|=1,f=B_($,y),f.ref=u.ref,f.return=u,u.child=f}function DW(f,u,_,y,l){if(f!==null){var $=f.memoizedProps;if(A$($,y)&&f.ref===u.ref)if(Ou=!1,u.pendingProps=y=$,(f.lanes&l)!==0)(f.flags&131072)!==0&&(Ou=!0);else return u.lanes=f.lanes,s1(f,u,l)}return i9(f,u,_,y,l)}function wW(f,u,_){var y=u.pendingProps,l=y.children,$=f!==null?f.memoizedState:null;if(y.mode==="hidden")if((u.mode&1)===0)u.memoizedState={baseLanes:0,cachePool:null,transitions:null},j0(El,Su),Su|=_;else{if((_&1073741824)===0)return f=$!==null?$.baseLanes|_:_,u.lanes=u.childLanes=1073741824,u.memoizedState={baseLanes:f,cachePool:null,transitions:null},u.updateQueue=null,j0(El,Su),Su|=f,null;u.memoizedState={baseLanes:0,cachePool:null,transitions:null},y=$!==null?$.baseLanes:_,j0(El,Su),Su|=y}else $!==null?(y=$.baseLanes|_,u.memoizedState=null):y=_,j0(El,Su),Su|=y;return Gu(f,u,l,_),u.child}function TW(f,u){var _=u.ref;if(f===null&&_!==null||f!==null&&f.ref!==_)u.flags|=512,u.flags|=2097152}function i9(f,u,_,y,l){var $=Nu(_)?Vy:$u.current;if($=Bl(u,$),Nl(u,l),_=P7(f,u,_,y,$,l),y=S7(),f!==null&&!Ou)return u.updateQueue=f.updateQueue,u.flags&=-2053,f.lanes&=~l,s1(f,u,l);return G0&&y&&V7(u),u.flags|=1,Gu(f,u,_,l),u.child}function pA(f,u,_,y,l){if(Nu(_)){var $=!0;h8(u)}else $=!1;if(Nl(u,l),u.stateNode===null)Y8(f,u),LW(u,_,y),k9(u,_,y,l),y=!0;else if(f===null){var{stateNode:j,memoizedProps:J}=u;j.props=J;var F=j.context,A=_.contextType;typeof A==="object"&&A!==null?A=eu(A):(A=Nu(_)?Vy:$u.current,A=Bl(u,A));var U=_.getDerivedStateFromProps,G=typeof U==="function"||typeof j.getSnapshotBeforeUpdate==="function";G||typeof j.UNSAFE_componentWillReceiveProps!=="function"&&typeof j.componentWillReceiveProps!=="function"||(J!==y||F!==A)&&xA(u,j,y,A),z_=!1;var W=u.memoizedState;j.state=W,m8(u,y,j,l),F=u.memoizedState,J!==y||W!==F||Xu.current||z_?(typeof U==="function"&&(p9(u,_,U,y),F=u.memoizedState),(J=z_||RA(u,_,J,y,W,F,A))?(G||typeof j.UNSAFE_componentWillMount!=="function"&&typeof j.componentWillMount!=="function"||(typeof j.componentWillMount==="function"&&j.componentWillMount(),typeof j.UNSAFE_componentWillMount==="function"&&j.UNSAFE_componentWillMount()),typeof j.componentDidMount==="function"&&(u.flags|=4194308)):(typeof j.componentDidMount==="function"&&(u.flags|=4194308),u.memoizedProps=y,u.memoizedState=F),j.props=y,j.state=F,j.context=A,y=J):(typeof j.componentDidMount==="function"&&(u.flags|=4194308),y=!1)}else{j=u.stateNode,yW(f,u),J=u.memoizedProps,A=u.type===u.elementType?J:A1(u.type,J),j.props=A,G=u.pendingProps,W=j.context,F=_.contextType,typeof F==="object"&&F!==null?F=eu(F):(F=Nu(_)?Vy:$u.current,F=Bl(u,F));var K=_.getDerivedStateFromProps;(U=typeof K==="function"||typeof j.getSnapshotBeforeUpdate==="function")||typeof j.UNSAFE_componentWillReceiveProps!=="function"&&typeof j.componentWillReceiveProps!=="function"||(J!==G||W!==F)&&xA(u,j,y,F),z_=!1,W=u.memoizedState,j.state=W,m8(u,y,j,l);var E=u.memoizedState;J!==G||W!==E||Xu.current||z_?(typeof K==="function"&&(p9(u,_,K,y),E=u.memoizedState),(A=z_||RA(u,_,A,y,W,E,F)||!1)?(U||typeof j.UNSAFE_componentWillUpdate!=="function"&&typeof j.componentWillUpdate!=="function"||(typeof j.componentWillUpdate==="function"&&j.componentWillUpdate(y,E,F),typeof j.UNSAFE_componentWillUpdate==="function"&&j.UNSAFE_componentWillUpdate(y,E,F)),typeof j.componentDidUpdate==="function"&&(u.flags|=4),typeof j.getSnapshotBeforeUpdate==="function"&&(u.flags|=1024)):(typeof j.componentDidUpdate!=="function"||J===f.memoizedProps&&W===f.memoizedState||(u.flags|=4),typeof j.getSnapshotBeforeUpdate!=="function"||J===f.memoizedProps&&W===f.memoizedState||(u.flags|=1024),u.memoizedProps=y,u.memoizedState=E),j.props=y,j.state=E,j.context=F,y=A):(typeof j.componentDidUpdate!=="function"||J===f.memoizedProps&&W===f.memoizedState||(u.flags|=4),typeof j.getSnapshotBeforeUpdate!=="function"||J===f.memoizedProps&&W===f.memoizedState||(u.flags|=1024),y=!1)}return g9(f,u,_,y,$,l)}function g9(f,u,_,y,l,$){TW(f,u);var j=(u.flags&128)!==0;if(!y&&!j)return l&&DA(u,_,!1),s1(f,u,$);y=u.stateNode,eV.current=u;var J=j&&typeof _.getDerivedStateFromError!=="function"?null:y.render();return u.flags|=1,f!==null&&j?(u.child=wl(u,f.child,null,$),u.child=wl(u,null,J,$)):Gu(f,u,J,$),u.memoizedState=y.state,l&&DA(u,_,!0),u.child}function rW(f){var u=f.stateNode;u.pendingContext?BA(f,u.pendingContext,u.pendingContext!==u.context):u.context&&BA(f,u.context,!1),w7(f,u.containerInfo)}function kA(f,u,_,y,l){return Dl(),X7(l),u.flags|=256,Gu(f,u,_,y),u.child}var n9={dehydrated:null,treeContext:null,retryLane:0};function t9(f){return{baseLanes:f,cachePool:null,transitions:null}}function MW(f,u,_){var y=u.pendingProps,l=Z0.current,$=!1,j=(u.flags&128)!==0,J;if((J=j)||(J=f!==null&&f.memoizedState===null?!1:(l&2)!==0),J)$=!0,u.flags&=-129;else if(f===null||f.memoizedState!==null)l|=1;if(j0(Z0,l&1),f===null){if(I9(u),f=u.memoizedState,f!==null&&(f=f.dehydrated,f!==null))return(u.mode&1)===0?u.lanes=1:f.data==="$!"?u.lanes=8:u.lanes=1073741824,null;return j=y.children,f=y.fallback,$?(y=u.mode,$=u.child,j={mode:"hidden",children:j},(y&1)===0&&$!==null?($.childLanes=0,$.pendingProps=j):$=Q4(j,y,0,null),f=Hy(f,y,_,null),$.return=u,f.return=u,$.sibling=f,u.child=$,u.child.memoizedState=t9(_),u.memoizedState=n9,f):x7(u,j)}if(l=f.memoizedState,l!==null&&(J=l.dehydrated,J!==null))return fO(f,u,j,y,J,l,_);if($){$=y.fallback,j=u.mode,l=f.child,J=l.sibling;var F={mode:"hidden",children:y.children};return(j&1)===0&&u.child!==l?(y=u.child,y.childLanes=0,y.pendingProps=F,u.deletions=null):(y=B_(l,F),y.subtreeFlags=l.subtreeFlags&14680064),J!==null?$=B_(J,$):($=Hy($,j,_,null),$.flags|=2),$.return=u,y.return=u,y.sibling=$,u.child=y,y=$,$=u.child,j=f.child.memoizedState,j=j===null?t9(_):{baseLanes:j.baseLanes|_,cachePool:null,transitions:j.transitions},$.memoizedState=j,$.childLanes=f.childLanes&~_,u.memoizedState=n9,y}return $=f.child,f=$.sibling,y=B_($,{mode:"visible",children:y.children}),(u.mode&1)===0&&(y.lanes=_),y.return=u,y.sibling=null,f!==null&&(_=u.deletions,_===null?(u.deletions=[f],u.flags|=16):_.push(f)),u.child=y,u.memoizedState=null,y}function x7(f,u){return u=Q4({mode:"visible",children:u},f.mode,0,null),u.return=f,f.child=u}function K8(f,u,_,y){return y!==null&&X7(y),wl(u,f.child,null,_),f=x7(u,u.pendingProps.children),f.flags|=2,u.memoizedState=null,f}function fO(f,u,_,y,l,$,j){if(_){if(u.flags&256)return u.flags&=-257,y=j9(Error(Ff(422))),K8(f,u,j,y);if(u.memoizedState!==null)return u.child=f.child,u.flags|=128,null;return $=y.fallback,l=u.mode,y=Q4({mode:"visible",children:y.children},l,0,null),$=Hy($,l,j,null),$.flags|=2,y.return=u,$.return=u,y.sibling=$,u.child=y,(u.mode&1)!==0&&wl(u,f.child,null,j),u.child.memoizedState=t9(j),u.memoizedState=n9,$}if((u.mode&1)===0)return K8(f,u,j,null);if(l.data==="$!"){if(y=l.nextSibling&&l.nextSibling.dataset,y)var J=y.dgst;return y=J,$=Error(Ff(419)),y=j9($,y,void 0),K8(f,u,j,y)}if(J=(j&f.childLanes)!==0,Ou||J){if(y=k0,y!==null){switch(j&-j){case 4:l=2;break;case 16:l=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:l=32;break;case 536870912:l=268435456;break;default:l=0}l=(l&(y.suspendedLanes|j))!==0?0:l,l!==0&&l!==$.retryLane&&($.retryLane=l,t1(f,l),z1(y,f,l,-1))}return p7(),y=j9(Error(Ff(421))),K8(f,u,j,y)}if(l.data==="$?")return u.flags|=128,u.child=f.child,u=GO.bind(null,f),l._reactRetry=u,null;return f=$.treeContext,Cu=X_(l.nextSibling),Ru=u,G0=!0,W1=null,f!==null&&(su[ou++]=k1,su[ou++]=m1,su[ou++]=Oy,k1=f.id,m1=f.overflow,Oy=u),u=x7(u,y.children),u.flags|=4096,u}function mA(f,u,_){f.lanes|=u;var y=f.alternate;y!==null&&(y.lanes|=u),c9(f.return,u,_)}function J9(f,u,_,y,l){var $=f.memoizedState;$===null?f.memoizedState={isBackwards:u,rendering:null,renderingStartTime:0,last:y,tail:_,tailMode:l}:($.isBackwards=u,$.rendering=null,$.renderingStartTime=0,$.last=y,$.tail=_,$.tailMode=l)}function PW(f,u,_){var y=u.pendingProps,l=y.revealOrder,$=y.tail;if(Gu(f,u,y.children,_),y=Z0.current,(y&2)!==0)y=y&1|2,u.flags|=128;else{if(f!==null&&(f.flags&128)!==0)f:for(f=u.child;f!==null;){if(f.tag===13)f.memoizedState!==null&&mA(f,_,u);else if(f.tag===19)mA(f,_,u);else if(f.child!==null){f.child.return=f,f=f.child;continue}if(f===u)break f;for(;f.sibling===null;){if(f.return===null||f.return===u)break f;f=f.return}f.sibling.return=f.return,f=f.sibling}y&=1}if(j0(Z0,y),(u.mode&1)===0)u.memoizedState=null;else switch(l){case"forwards":_=u.child;for(l=null;_!==null;)f=_.alternate,f!==null&&i8(f)===null&&(l=_),_=_.sibling;_=l,_===null?(l=u.child,u.child=null):(l=_.sibling,_.sibling=null),J9(u,!1,l,_,$);break;case"backwards":_=null,l=u.child;for(u.child=null;l!==null;){if(f=l.alternate,f!==null&&i8(f)===null){u.child=l;break}f=l.sibling,l.sibling=_,_=l,l=f}J9(u,!0,_,null,$);break;case"together":J9(u,!1,null,null,void 0);break;default:u.memoizedState=null}return u.child}function Y8(f,u){(u.mode&1)===0&&f!==null&&(f.alternate=null,u.alternate=null,u.flags|=2)}function s1(f,u,_){if(f!==null&&(u.dependencies=f.dependencies),Ny|=u.lanes,(_&u.childLanes)===0)return null;if(f!==null&&u.child!==f.child)throw Error(Ff(153));if(u.child!==null){f=u.child,_=B_(f,f.pendingProps),u.child=_;for(_.return=u;f.sibling!==null;)f=f.sibling,_=_.sibling=B_(f,f.pendingProps),_.return=u;_.sibling=null}return u.child}function uO(f,u,_){switch(u.tag){case 3:rW(u),Dl();break;case 5:lW(u);break;case 1:Nu(u.type)&&h8(u);break;case 4:w7(u,u.stateNode.containerInfo);break;case 10:var y=u.type._context,l=u.memoizedProps.value;j0(p8,y._currentValue),y._currentValue=l;break;case 13:if(y=u.memoizedState,y!==null){if(y.dehydrated!==null)return j0(Z0,Z0.current&1),u.flags|=128,null;if((_&u.child.childLanes)!==0)return MW(f,u,_);return j0(Z0,Z0.current&1),f=s1(f,u,_),f!==null?f.sibling:null}j0(Z0,Z0.current&1);break;case 19:if(y=(_&u.childLanes)!==0,(f.flags&128)!==0){if(y)return PW(f,u,_);u.flags|=128}if(l=u.memoizedState,l!==null&&(l.rendering=null,l.tail=null,l.lastEffect=null),j0(Z0,Z0.current),y)break;else return null;case 22:case 23:return u.lanes=0,wW(f,u,_)}return s1(f,u,_)}var SW,s9,CW,RW;SW=function(f,u){for(var _=u.child;_!==null;){if(_.tag===5||_.tag===6)f.appendChild(_.stateNode);else if(_.tag!==4&&_.child!==null){_.child.return=_,_=_.child;continue}if(_===u)break;for(;_.sibling===null;){if(_.return===null||_.return===u)return;_=_.return}_.sibling.return=_.return,_=_.sibling}};s9=function(){};CW=function(f,u,_,y){var l=f.memoizedProps;if(l!==y){f=u.stateNode,qy(r1.current);var $=null;switch(_){case"input":l=K9(f,l),y=K9(f,y),$=[];break;case"select":l=E0({},l,{value:void 0}),y=E0({},y,{value:void 0}),$=[];break;case"textarea":l=E9(f,l),y=E9(f,y),$=[];break;default:typeof l.onClick!=="function"&&typeof y.onClick==="function"&&(f.onclick=v8)}V9(_,y);var j;_=null;for(A in l)if(!y.hasOwnProperty(A)&&l.hasOwnProperty(A)&&l[A]!=null)if(A==="style"){var J=l[A];for(j in J)J.hasOwnProperty(j)&&(_||(_={}),_[j]="")}else A!=="dangerouslySetInnerHTML"&&A!=="children"&&A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&A!=="autoFocus"&&(y$.hasOwnProperty(A)?$||($=[]):($=$||[]).push(A,null));for(A in y){var F=y[A];if(J=l!=null?l[A]:void 0,y.hasOwnProperty(A)&&F!==J&&(F!=null||J!=null))if(A==="style")if(J){for(j in J)!J.hasOwnProperty(j)||F&&F.hasOwnProperty(j)||(_||(_={}),_[j]="");for(j in F)F.hasOwnProperty(j)&&J[j]!==F[j]&&(_||(_={}),_[j]=F[j])}else _||($||($=[]),$.push(A,_)),_=F;else A==="dangerouslySetInnerHTML"?(F=F?F.__html:void 0,J=J?J.__html:void 0,F!=null&&J!==F&&($=$||[]).push(A,F)):A==="children"?typeof F!=="string"&&typeof F!=="number"||($=$||[]).push(A,""+F):A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&(y$.hasOwnProperty(A)?(F!=null&&A==="onScroll"&&A0("scroll",f),$||J===F||($=[])):($=$||[]).push(A,F))}_&&($=$||[]).push("style",_);var A=$;if(u.updateQueue=A)u.flags|=4}};RW=function(f,u,_,y){_!==y&&(u.flags|=4)};function b3(f,u){if(!G0)switch(f.tailMode){case"hidden":u=f.tail;for(var _=null;u!==null;)u.alternate!==null&&(_=u),u=u.sibling;_===null?f.tail=null:_.sibling=null;break;case"collapsed":_=f.tail;for(var y=null;_!==null;)_.alternate!==null&&(y=_),_=_.sibling;y===null?u||f.tail===null?f.tail=null:f.tail.sibling=null:y.sibling=null}}function yu(f){var u=f.alternate!==null&&f.alternate.child===f.child,_=0,y=0;if(u)for(var l=f.child;l!==null;)_|=l.lanes|l.childLanes,y|=l.subtreeFlags&14680064,y|=l.flags&14680064,l.return=f,l=l.sibling;else for(l=f.child;l!==null;)_|=l.lanes|l.childLanes,y|=l.subtreeFlags,y|=l.flags,l.return=f,l=l.sibling;return f.subtreeFlags|=y,f.childLanes=_,u}function _O(f,u,_){var y=u.pendingProps;switch(O7(u),u.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return yu(u),null;case 1:return Nu(u.type)&&b8(),yu(u),null;case 3:if(y=u.stateNode,Tl(),U0(Xu),U0($u),r7(),y.pendingContext&&(y.context=y.pendingContext,y.pendingContext=null),f===null||f.child===null)G8(u)?u.flags|=4:f===null||f.memoizedState.isDehydrated&&(u.flags&256)===0||(u.flags|=1024,W1!==null&&(y7(W1),W1=null));return s9(f,u),yu(u),null;case 5:T7(u);var l=qy(K$.current);if(_=u.type,f!==null&&u.stateNode!=null)CW(f,u,_,y,l),f.ref!==u.ref&&(u.flags|=512,u.flags|=2097152);else{if(!y){if(u.stateNode===null)throw Error(Ff(166));return yu(u),null}if(f=qy(r1.current),G8(u)){y=u.stateNode,_=u.type;var $=u.memoizedProps;switch(y[w1]=u,y[G$]=$,f=(u.mode&1)!==0,_){case"dialog":A0("cancel",y),A0("close",y);break;case"iframe":case"object":case"embed":A0("load",y);break;case"video":case"audio":for(l=0;l",f=f.removeChild(f.firstChild)):typeof y.is==="string"?f=j.createElement(_,{is:y.is}):(f=j.createElement(_),_==="select"&&(j=f,y.multiple?j.multiple=!0:y.size&&(j.size=y.size))):f=j.createElementNS(f,_),f[w1]=u,f[G$]=y,SW(f,u,!1,!1),u.stateNode=f;f:{switch(j=O9(_,y),_){case"dialog":A0("cancel",f),A0("close",f),l=y;break;case"iframe":case"object":case"embed":A0("load",f),l=y;break;case"video":case"audio":for(l=0;lMl&&(u.flags|=128,y=!0,b3($,!1),u.lanes=4194304)}else{if(!y)if(f=i8(j),f!==null){if(u.flags|=128,y=!0,_=f.updateQueue,_!==null&&(u.updateQueue=_,u.flags|=4),b3($,!0),$.tail===null&&$.tailMode==="hidden"&&!j.alternate&&!G0)return yu(u),null}else 2*w0()-$.renderingStartTime>Ml&&_!==1073741824&&(u.flags|=128,y=!0,b3($,!1),u.lanes=4194304);$.isBackwards?(j.sibling=u.child,u.child=j):(_=$.last,_!==null?_.sibling=j:u.child=j,$.last=j)}if($.tail!==null)return u=$.tail,$.rendering=u,$.tail=u.sibling,$.renderingStartTime=w0(),u.sibling=null,_=Z0.current,j0(Z0,y?_&1|2:_&1),u;return yu(u),null;case 22:case 23:return c7(),y=u.memoizedState!==null,f!==null&&f.memoizedState!==null!==y&&(u.flags|=8192),y&&(u.mode&1)!==0?(Su&1073741824)!==0&&(yu(u),u.subtreeFlags&6&&(u.flags|=8192)):yu(u),null;case 24:return null;case 25:return null}throw Error(Ff(156,u.tag))}function yO(f,u){switch(O7(u),u.tag){case 1:return Nu(u.type)&&b8(),f=u.flags,f&65536?(u.flags=f&-65537|128,u):null;case 3:return Tl(),U0(Xu),U0($u),r7(),f=u.flags,(f&65536)!==0&&(f&128)===0?(u.flags=f&-65537|128,u):null;case 5:return T7(u),null;case 13:if(U0(Z0),f=u.memoizedState,f!==null&&f.dehydrated!==null){if(u.alternate===null)throw Error(Ff(340));Dl()}return f=u.flags,f&65536?(u.flags=f&-65537|128,u):null;case 19:return U0(Z0),null;case 4:return Tl(),null;case 10:return Y7(u.type._context),null;case 22:case 23:return c7(),null;case 24:return null;default:return null}}var Z8=!1,lu=!1,lO=typeof WeakSet==="function"?WeakSet:Set,qf=null;function ql(f,u){var _=f.ref;if(_!==null)if(typeof _==="function")try{_(null)}catch(y){Y0(f,u,y)}else _.current=null}function o9(f,u,_){try{_()}catch(y){Y0(f,u,y)}}var iA=!1;function $O(f,u){if(S9=C8,f=IU(),H7(f)){if("selectionStart"in f)var _={start:f.selectionStart,end:f.selectionEnd};else f:{_=(_=f.ownerDocument)&&_.defaultView||window;var y=_.getSelection&&_.getSelection();if(y&&y.rangeCount!==0){_=y.anchorNode;var{anchorOffset:l,focusNode:$}=y;y=y.focusOffset;try{_.nodeType,$.nodeType}catch(V){_=null;break f}var j=0,J=-1,F=-1,A=0,U=0,G=f,W=null;u:for(;;){for(var K;;){if(G!==_||l!==0&&G.nodeType!==3||(J=j+l),G!==$||y!==0&&G.nodeType!==3||(F=j+y),G.nodeType===3&&(j+=G.nodeValue.length),(K=G.firstChild)===null)break;W=G,G=K}for(;;){if(G===f)break u;if(W===_&&++A===l&&(J=j),W===$&&++U===y&&(F=j),(K=G.nextSibling)!==null)break;G=W,W=G.parentNode}G=K}_=J===-1||F===-1?null:{start:J,end:F}}else _=null}_=_||{start:0,end:0}}else _=null;C9={focusedElem:f,selectionRange:_},C8=!1;for(qf=u;qf!==null;)if(u=qf,f=u.child,(u.subtreeFlags&1028)!==0&&f!==null)f.return=u,qf=f;else for(;qf!==null;){u=qf;try{var E=u.alternate;if((u.flags&1024)!==0)switch(u.tag){case 0:case 11:case 15:break;case 1:if(E!==null){var{memoizedProps:H,memoizedState:O}=E,z=u.stateNode,q=z.getSnapshotBeforeUpdate(u.elementType===u.type?H:A1(u.type,H),O);z.__reactInternalSnapshotBeforeUpdate=q}break;case 3:var Z=u.stateNode.containerInfo;Z.nodeType===1?Z.textContent="":Z.nodeType===9&&Z.documentElement&&Z.removeChild(Z.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(Ff(163))}}catch(V){Y0(u,u.return,V)}if(f=u.sibling,f!==null){f.return=u.return,qf=f;break}qf=u.return}return E=iA,iA=!1,E}function f$(f,u,_){var y=u.updateQueue;if(y=y!==null?y.lastEffect:null,y!==null){var l=y=y.next;do{if((l.tag&f)===f){var $=l.destroy;l.destroy=void 0,$!==void 0&&o9(u,_,$)}l=l.next}while(l!==y)}}function J4(f,u){if(u=u.updateQueue,u=u!==null?u.lastEffect:null,u!==null){var _=u=u.next;do{if((_.tag&f)===f){var y=_.create;_.destroy=y()}_=_.next}while(_!==u)}}function a9(f){var u=f.ref;if(u!==null){var _=f.stateNode;switch(f.tag){case 5:f=_;break;default:f=_}typeof u==="function"?u(f):u.current=f}}function xW(f){var u=f.alternate;u!==null&&(f.alternate=null,xW(u)),f.child=null,f.deletions=null,f.sibling=null,f.tag===5&&(u=f.stateNode,u!==null&&(delete u[w1],delete u[G$],delete u[v9],delete u[cV],delete u[pV])),f.stateNode=null,f.return=null,f.dependencies=null,f.memoizedProps=null,f.memoizedState=null,f.pendingProps=null,f.stateNode=null,f.updateQueue=null}function vW(f){return f.tag===5||f.tag===3||f.tag===4}function gA(f){f:for(;;){for(;f.sibling===null;){if(f.return===null||vW(f.return))return null;f=f.return}f.sibling.return=f.return;for(f=f.sibling;f.tag!==5&&f.tag!==6&&f.tag!==18;){if(f.flags&2)continue f;if(f.child===null||f.tag===4)continue f;else f.child.return=f,f=f.child}if(!(f.flags&2))return f.stateNode}}function d9(f,u,_){var y=f.tag;if(y===5||y===6)f=f.stateNode,u?_.nodeType===8?_.parentNode.insertBefore(f,u):_.insertBefore(f,u):(_.nodeType===8?(u=_.parentNode,u.insertBefore(f,_)):(u=_,u.appendChild(f)),_=_._reactRootContainer,_!==null&&_!==void 0||u.onclick!==null||(u.onclick=v8));else if(y!==4&&(f=f.child,f!==null))for(d9(f,u,_),f=f.sibling;f!==null;)d9(f,u,_),f=f.sibling}function e9(f,u,_){var y=f.tag;if(y===5||y===6)f=f.stateNode,u?_.insertBefore(f,u):_.appendChild(f);else if(y!==4&&(f=f.child,f!==null))for(e9(f,u,_),f=f.sibling;f!==null;)e9(f,u,_),f=f.sibling}var g0=null,U1=!1;function W_(f,u,_){for(_=_.child;_!==null;)bW(f,u,_),_=_.sibling}function bW(f,u,_){if(T1&&typeof T1.onCommitFiberUnmount==="function")try{T1.onCommitFiberUnmount(e8,_)}catch(J){}switch(_.tag){case 5:lu||ql(_,u);case 6:var y=g0,l=U1;g0=null,W_(f,u,_),g0=y,U1=l,g0!==null&&(U1?(f=g0,_=_.stateNode,f.nodeType===8?f.parentNode.removeChild(_):f.removeChild(_)):g0.removeChild(_.stateNode));break;case 18:g0!==null&&(U1?(f=g0,_=_.stateNode,f.nodeType===8?f9(f.parentNode,_):f.nodeType===1&&f9(f,_),F$(f)):f9(g0,_.stateNode));break;case 4:y=g0,l=U1,g0=_.stateNode.containerInfo,U1=!0,W_(f,u,_),g0=y,U1=l;break;case 0:case 11:case 14:case 15:if(!lu&&(y=_.updateQueue,y!==null&&(y=y.lastEffect,y!==null))){l=y=y.next;do{var $=l,j=$.destroy;$=$.tag,j!==void 0&&(($&2)!==0?o9(_,u,j):($&4)!==0&&o9(_,u,j)),l=l.next}while(l!==y)}W_(f,u,_);break;case 1:if(!lu&&(ql(_,u),y=_.stateNode,typeof y.componentWillUnmount==="function"))try{y.props=_.memoizedProps,y.state=_.memoizedState,y.componentWillUnmount()}catch(J){Y0(_,u,J)}W_(f,u,_);break;case 21:W_(f,u,_);break;case 22:_.mode&1?(lu=(y=lu)||_.memoizedState!==null,W_(f,u,_),lu=y):W_(f,u,_);break;default:W_(f,u,_)}}function nA(f){var u=f.updateQueue;if(u!==null){f.updateQueue=null;var _=f.stateNode;_===null&&(_=f.stateNode=new lO),u.forEach(function(y){var l=zO.bind(null,f,y);_.has(y)||(_.add(y),y.then(l,l))})}}function Q1(f,u){var _=u.deletions;if(_!==null)for(var y=0;y<_.length;y++){var l=_[y];try{var $=f,j=u,J=j;f:for(;J!==null;){switch(J.tag){case 5:g0=J.stateNode,U1=!1;break f;case 3:g0=J.stateNode.containerInfo,U1=!0;break f;case 4:g0=J.stateNode.containerInfo,U1=!0;break f}J=J.return}if(g0===null)throw Error(Ff(160));bW($,j,l),g0=null,U1=!1;var F=l.alternate;F!==null&&(F.return=null),l.return=null}catch(A){Y0(l,u,A)}}if(u.subtreeFlags&12854)for(u=u.child;u!==null;)hW(u,f),u=u.sibling}function hW(f,u){var{alternate:_,flags:y}=f;switch(f.tag){case 0:case 11:case 14:case 15:if(Q1(u,f),B1(f),y&4){try{f$(3,f,f.return),J4(3,f)}catch(H){Y0(f,f.return,H)}try{f$(5,f,f.return)}catch(H){Y0(f,f.return,H)}}break;case 1:Q1(u,f),B1(f),y&512&&_!==null&&ql(_,_.return);break;case 5:if(Q1(u,f),B1(f),y&512&&_!==null&&ql(_,_.return),f.flags&32){var l=f.stateNode;try{l$(l,"")}catch(H){Y0(f,f.return,H)}}if(y&4&&(l=f.stateNode,l!=null)){var $=f.memoizedProps,j=_!==null?_.memoizedProps:$,J=f.type,F=f.updateQueue;if(f.updateQueue=null,F!==null)try{J==="input"&&$.type==="radio"&&$.name!=null&&JU(l,$),O9(J,j);var A=O9(J,$);for(j=0;jl&&(l=j),y&=~$}if(y=l,y=w0()-y,y=(120>y?120:480>y?480:1080>y?1080:1920>y?1920:3000>y?3000:4320>y?4320:1960*JO(y/1960))-y,10f?16:f,E_===null)var y=!1;else{if(f=E_,E_=null,o8=0,(gf&6)!==0)throw Error(Ff(331));var l=gf;gf|=4;for(qf=f.current;qf!==null;){var $=qf,j=$.child;if((qf.flags&16)!==0){var J=$.deletions;if(J!==null){for(var F=0;Fw0()-h7?Ey(f,0):b7|=_),Lu(f,u)}function gW(f,u){u===0&&((f.mode&1)===0?u=1:(u=J8,J8<<=1,(J8&130023424)===0&&(J8=4194304)));var _=zu();f=t1(f,u),f!==null&&(V$(f,u,_),Lu(f,_))}function GO(f){var u=f.memoizedState,_=0;u!==null&&(_=u.retryLane),gW(f,_)}function zO(f,u){var _=0;switch(f.tag){case 13:var{stateNode:y,memoizedState:l}=f;l!==null&&(_=l.retryLane);break;case 19:y=f.stateNode;break;default:throw Error(Ff(314))}y!==null&&y.delete(u),gW(f,_)}var nW;nW=function(f,u,_){if(f!==null)if(f.memoizedProps!==u.pendingProps||Xu.current)Ou=!0;else{if((f.lanes&_)===0&&(u.flags&128)===0)return Ou=!1,uO(f,u,_);Ou=(f.flags&131072)!==0?!0:!1}else Ou=!1,G0&&(u.flags&1048576)!==0&&aU(u,c8,u.index);switch(u.lanes=0,u.tag){case 2:var y=u.type;Y8(f,u),f=u.pendingProps;var l=Bl(u,$u.current);Nl(u,_),l=P7(null,u,y,f,l,_);var $=S7();return u.flags|=1,typeof l==="object"&&l!==null&&typeof l.render==="function"&&l.$$typeof===void 0?(u.tag=1,u.memoizedState=null,u.updateQueue=null,Nu(y)?($=!0,h8(u)):$=!1,u.memoizedState=l.state!==null&&l.state!==void 0?l.state:null,D7(u),l.updater=j4,u.stateNode=l,l._reactInternals=u,k9(u,y,f,_),u=g9(null,u,y,!0,$,_)):(u.tag=0,G0&&$&&V7(u),Gu(null,u,l,_),u=u.child),u;case 16:y=u.elementType;f:{switch(Y8(f,u),f=u.pendingProps,l=y._init,y=l(y._payload),u.type=y,l=u.tag=ZO(y),f=A1(y,f),l){case 0:u=i9(null,u,y,f,_);break f;case 1:u=pA(null,u,y,f,_);break f;case 11:u=IA(null,u,y,f,_);break f;case 14:u=cA(null,u,y,A1(y.type,f),_);break f}throw Error(Ff(306,y,""))}return u;case 0:return y=u.type,l=u.pendingProps,l=u.elementType===y?l:A1(y,l),i9(f,u,y,l,_);case 1:return y=u.type,l=u.pendingProps,l=u.elementType===y?l:A1(y,l),pA(f,u,y,l,_);case 3:f:{if(rW(u),f===null)throw Error(Ff(387));y=u.pendingProps,$=u.memoizedState,l=$.element,yW(f,u),m8(u,y,null,_);var j=u.memoizedState;if(y=j.element,$.isDehydrated)if($={element:y,isDehydrated:!1,cache:j.cache,pendingSuspenseBoundaries:j.pendingSuspenseBoundaries,transitions:j.transitions},u.updateQueue.baseState=$,u.memoizedState=$,u.flags&256){l=rl(Error(Ff(423)),u),u=kA(f,u,y,_,l);break f}else if(y!==l){l=rl(Error(Ff(424)),u),u=kA(f,u,y,_,l);break f}else for(Cu=X_(u.stateNode.containerInfo.firstChild),Ru=u,G0=!0,W1=null,_=uW(u,null,y,_),u.child=_;_;)_.flags=_.flags&-3|4096,_=_.sibling;else{if(Dl(),y===l){u=s1(f,u,_);break f}Gu(f,u,y,_)}u=u.child}return u;case 5:return lW(u),f===null&&I9(u),y=u.type,l=u.pendingProps,$=f!==null?f.memoizedProps:null,j=l.children,R9(y,l)?j=null:$!==null&&R9(y,$)&&(u.flags|=32),TW(f,u),Gu(f,u,j,_),u.child;case 6:return f===null&&I9(u),null;case 13:return MW(f,u,_);case 4:return w7(u,u.stateNode.containerInfo),y=u.pendingProps,f===null?u.child=wl(u,null,y,_):Gu(f,u,y,_),u.child;case 11:return y=u.type,l=u.pendingProps,l=u.elementType===y?l:A1(y,l),IA(f,u,y,l,_);case 7:return Gu(f,u,u.pendingProps,_),u.child;case 8:return Gu(f,u,u.pendingProps.children,_),u.child;case 12:return Gu(f,u,u.pendingProps.children,_),u.child;case 10:f:{if(y=u.type._context,l=u.pendingProps,$=u.memoizedProps,j=l.value,j0(p8,y._currentValue),y._currentValue=j,$!==null)if(K1($.value,j)){if($.children===l.children&&!Xu.current){u=s1(f,u,_);break f}}else for($=u.child,$!==null&&($.return=u);$!==null;){var J=$.dependencies;if(J!==null){j=$.child;for(var F=J.firstContext;F!==null;){if(F.context===y){if($.tag===1){F=i1(-1,_&-_),F.tag=2;var A=$.updateQueue;if(A!==null){A=A.shared;var U=A.pending;U===null?F.next=F:(F.next=U.next,U.next=F),A.pending=F}}$.lanes|=_,F=$.alternate,F!==null&&(F.lanes|=_),c9($.return,_,u),J.lanes|=_;break}F=F.next}}else if($.tag===10)j=$.type===u.type?null:$.child;else if($.tag===18){if(j=$.return,j===null)throw Error(Ff(341));j.lanes|=_,J=j.alternate,J!==null&&(J.lanes|=_),c9(j,_,u),j=$.sibling}else j=$.child;if(j!==null)j.return=$;else for(j=$;j!==null;){if(j===u){j=null;break}if($=j.sibling,$!==null){$.return=j.return,j=$;break}j=j.return}$=j}Gu(f,u,l.children,_),u=u.child}return u;case 9:return l=u.type,y=u.pendingProps.children,Nl(u,_),l=eu(l),y=y(l),u.flags|=1,Gu(f,u,y,_),u.child;case 14:return y=u.type,l=A1(y,u.pendingProps),l=A1(y.type,l),cA(f,u,y,l,_);case 15:return DW(f,u,u.type,u.pendingProps,_);case 17:return y=u.type,l=u.pendingProps,l=u.elementType===y?l:A1(y,l),Y8(f,u),u.tag=1,Nu(y)?(f=!0,h8(u)):f=!1,Nl(u,_),LW(u,y,l),k9(u,y,l,_),g9(null,u,y,!0,f,_);case 19:return PW(f,u,_);case 22:return wW(f,u,_)}throw Error(Ff(156,u.tag))};function tW(f,u){return OU(f,u)}function KO(f,u,_,y){this.tag=f,this.key=_,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=u,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=y,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function au(f,u,_,y){return new KO(f,u,_,y)}function k7(f){return f=f.prototype,!(!f||!f.isReactComponent)}function ZO(f){if(typeof f==="function")return k7(f)?1:0;if(f!==void 0&&f!==null){if(f=f.$$typeof,f===F7)return 11;if(f===Q7)return 14}return 2}function B_(f,u){var _=f.alternate;return _===null?(_=au(f.tag,u,f.key,f.mode),_.elementType=f.elementType,_.type=f.type,_.stateNode=f.stateNode,_.alternate=f,f.alternate=_):(_.pendingProps=u,_.type=f.type,_.flags=0,_.subtreeFlags=0,_.deletions=null),_.flags=f.flags&14680064,_.childLanes=f.childLanes,_.lanes=f.lanes,_.child=f.child,_.memoizedProps=f.memoizedProps,_.memoizedState=f.memoizedState,_.updateQueue=f.updateQueue,u=f.dependencies,_.dependencies=u===null?null:{lanes:u.lanes,firstContext:u.firstContext},_.sibling=f.sibling,_.index=f.index,_.ref=f.ref,_}function w8(f,u,_,y,l,$){var j=2;if(y=f,typeof f==="function")k7(f)&&(j=1);else if(typeof f==="string")j=5;else f:switch(f){case Fl:return Hy(_.children,l,$,u);case J7:j=8,l|=8;break;case U9:return f=au(12,_,u,l|2),f.elementType=U9,f.lanes=$,f;case W9:return f=au(13,_,u,l),f.elementType=W9,f.lanes=$,f;case G9:return f=au(19,_,u,l),f.elementType=G9,f.lanes=$,f;case lU:return Q4(_,l,$,u);default:if(typeof f==="object"&&f!==null)switch(f.$$typeof){case _U:j=10;break f;case yU:j=9;break f;case F7:j=11;break f;case Q7:j=14;break f;case G_:j=16,y=null;break f}throw Error(Ff(130,f==null?f:typeof f,""))}return u=au(j,_,u,l),u.elementType=f,u.type=y,u.lanes=$,u}function Hy(f,u,_,y){return f=au(7,f,y,u),f.lanes=_,f}function Q4(f,u,_,y){return f=au(22,f,y,u),f.elementType=lU,f.lanes=_,f.stateNode={isHidden:!1},f}function F9(f,u,_){return f=au(6,f,null,u),f.lanes=_,f}function Q9(f,u,_){return u=au(4,f.children!==null?f.children:[],f.key,u),u.lanes=_,u.stateNode={containerInfo:f.containerInfo,pendingChildren:null,implementation:f.implementation},u}function qO(f,u,_,y,l){this.tag=u,this.containerInfo=f,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=n2(0),this.expirationTimes=n2(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=n2(0),this.identifierPrefix=y,this.onRecoverableError=l,this.mutableSourceEagerHydrationData=null}function m7(f,u,_,y,l,$,j,J,F){return f=new qO(f,u,_,J,F),u===1?(u=1,$===!0&&(u|=8)):u=0,$=au(3,null,null,u),f.current=$,$.stateNode=f,$.memoizedState={element:y,isDehydrated:_,cache:null,transitions:null,pendingSuspenseBoundaries:null},D7($),f}function EO(f,u,_){var y=3{function eW(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=="function")return;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(eW)}catch(f){console.error(f)}}eW(),fG.exports=dW()});var _G=Pu((s7)=>{var uG=t7();s7.createRoot=uG.createRoot,s7.hydrateRoot=uG.hydrateRoot;var NO});var zz=Pu((I4)=>{var SN=c0(),CN=Symbol.for("react.element"),RN=Symbol.for("react.fragment"),xN=Object.prototype.hasOwnProperty,vN=SN.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,bN={key:!0,ref:!0,__self:!0,__source:!0};function Gz(f,u,_){var y,l={},$=null,j=null;_!==void 0&&($=""+_),u.key!==void 0&&($=""+u.key),u.ref!==void 0&&(j=u.ref);for(y in u)xN.call(u,y)&&!bN.hasOwnProperty(y)&&(l[y]=u[y]);if(f&&f.defaultProps)for(y in u=f.defaultProps,u)l[y]===void 0&&(l[y]=u[y]);return{$$typeof:CN,type:f,key:$,ref:j,props:l,_owner:vN.current}}I4.Fragment=RN;I4.jsx=Gz;I4.jsxs=Gz});var Zz=Pu((kP,Kz)=>{Kz.exports=zz()});var nK=Pu((gK)=>{var F3=c0();function uD(f,u){return f===u&&(f!==0||1/f===1/u)||f!==f&&u!==u}var _D=typeof Object.is==="function"?Object.is:uD,yD=F3.useState,lD=F3.useEffect,$D=F3.useLayoutEffect,jD=F3.useDebugValue;function JD(f,u){var _=u(),y=yD({inst:{value:_,getSnapshot:u}}),l=y[0].inst,$=y[1];return $D(function(){l.value=_,l.getSnapshot=u,DF(l)&&$({inst:l})},[f,_,u]),lD(function(){return DF(l)&&$({inst:l}),f(function(){DF(l)&&$({inst:l})})},[f]),jD(_),_}function DF(f){var u=f.getSnapshot;f=f.value;try{var _=u();return!_D(f,_)}catch(y){return!0}}function FD(f,u){return u()}var QD=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?FD:JD;gK.useSyncExternalStore=F3.useSyncExternalStore!==void 0?F3.useSyncExternalStore:QD});var sK=Pu((xb,tK)=>{tK.exports=nK()});var aK=Pu((oK)=>{var S5=c0(),AD=sK();function UD(f,u){return f===u&&(f!==0||1/f===1/u)||f!==f&&u!==u}var WD=typeof Object.is==="function"?Object.is:UD,GD=AD.useSyncExternalStore,zD=S5.useRef,KD=S5.useEffect,ZD=S5.useMemo,qD=S5.useDebugValue;oK.useSyncExternalStoreWithSelector=function(f,u,_,y,l){var $=zD(null);if($.current===null){var j={hasValue:!1,value:null};$.current=j}else j=$.current;$=ZD(function(){function F(K){if(!A){if(A=!0,U=K,K=y(K),l!==void 0&&j.hasValue){var E=j.value;if(l(E,K))return G=E}return G=K}if(E=G,WD(U,K))return E;var H=y(K);if(l!==void 0&&l(E,H))return U=K,E;return U=K,G=H}var A=!1,U,G,W=_===void 0?null:_;return[function(){return F(u())},W===null?void 0:function(){return F(W())}]},[u,_,y,l]);var J=GD(f,$[0],$[1]);return KD(function(){j.hasValue=!0,j.value=J},[J]),qD(J),J}});var eK=Pu((bb,dK)=>{dK.exports=aK()});var r6=Sf(c0(),1);var s6="北京时间";var EH={timeZone:"Asia/Shanghai",hour12:!1},HH={timeZone:"Asia/Shanghai",hour12:!1},VH=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 M2(f){if(f===null||f===void 0||f==="")return null;let u=f instanceof Date?f:new Date(f);return Number.isNaN(u.getTime())?null:u}function hQ(f){let u=M2(f);if(!u)return null;return VH.formatToParts(u).reduce((_,y)=>{if(y.type!=="literal")_[y.type]=y.value;return _},{})}function zf(f){let u=M2(f);return u?u.toLocaleString("zh-CN",EH):"--"}function L0(f){let u=M2(f);return u?u.toLocaleTimeString("zh-CN",HH):"--"}function P2(f){let u=hQ(f);if(!u)return"";let _=u.hour==="24"?"00":u.hour;return`${u.year}-${u.month}-${u.day}T${_}:${u.minute}`}function IQ(f=new Date){let u=hQ(f);if(!u)return"";return`${u.year}-${u.month}-${u.day}`}function cQ(f){if(!f)return null;let u=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(f);if(!u)return null;let[,_,y,l,$,j,J="00"]=u,F=Date.UTC(Number(_),Number(y)-1,Number(l),Number($)-8,Number(j),Number(J)),A=new Date(F),U=P2(A);return Number.isNaN(A.getTime())||U!==`${_}-${y}-${l}T${$}:${j}`?null:A.toISOString()}var NE=Sf(_G(),1);var q4=Sf(c0(),1);class Cl extends Error{unideskRequestError=!0;meta;constructor(f,u){super(f);this.name="UniDeskRequestError",this.meta=u}}function LO(f){return new Promise((u)=>setTimeout(u,f))}function B$(f,u="操作失败"){return f instanceof Error?f.message:String(f||u)}function z4(f,u=500){if(f===null||f===void 0)return"";let _=typeof f==="string"?f:JSON.stringify(f),y=String(_||"").replace(/\s+/gu," ").trim();return y.length>u?`${y.slice(0,u)}...`:y}function YO(f){try{let u=typeof location<"u"&&location.origin?location.origin:"http://localhost";return new URL(f,u).toString()}catch{return f}}function yG(f){return String(f.method||"GET").toUpperCase()}function BO(f){if(f===null||f===void 0)return!1;if(typeof f!=="object")return!1;if(typeof Blob<"u"&&f instanceof Blob)return!1;if(typeof FormData<"u"&&f instanceof FormData)return!1;if(typeof URLSearchParams<"u"&&f instanceof URLSearchParams)return!1;if(typeof ArrayBuffer<"u"&&f instanceof ArrayBuffer)return!1;return!0}function lG(f){let u=new Headers(f.headers||{}),_=BO(f.body)?JSON.stringify(f.body):f.body;if(_&&!u.has("content-type")&&typeof _==="string")u.set("content-type","application/json");return{...f,credentials:f.credentials||"same-origin",body:_,headers:u}}function $G(f){if(f?.error&&typeof f.error==="object"&&typeof f.error.message==="string")return f.error.message;if(typeof f?.error==="string")return f.error;if(typeof f?.message==="string")return f.message;if(typeof f?.detail==="string")return f.detail;return""}function DO(f,u){if(!f||typeof f!=="object"||Array.isArray(f))return!1;return u.some((_)=>_!==!1&&f[_]===!1)}function L$(f,u,_,y,l={}){return{kind:f,method:_,url:YO(u),occurredAt:y.toISOString(),...l}}function Y$(f,u){if(!f)return"请求失败";return`HTTP ${f}${u?` ${u}`:""}`}function jG(f){try{return{body:f?JSON.parse(f):null,parseError:""}}catch(u){return{body:{text:f},parseError:B$(u,"parse failed")}}}async function wf(f,u={},_=0){let{failureFields:y=["ok"],strictJson:l=!1,retryInvalidJson:$=0,retryDelayMs:j=120,invalidJsonPrefix:J="服务返回了无效 JSON",invalidJsonPreview:F=!1,responsePreviewLength:A=500,...U}=u,G=yG(U),W=new Date,K;try{K=await fetch(f,lG(U))}catch(O){let z=B$(O,"网络请求失败");throw new Cl(z,L$("network",f,G,W,{upstreamMessage:z}))}let E=await K.text(),H=jG(E);if(H.parseError){if(l&&G==="GET"&&_<$)return await LO(j),wf(f,u,_+1);if(l){let O=F?`;响应预览:${z4(E,180)}`:"";throw new Cl(`${J}(${E.length} bytes):${H.parseError}${O}`,L$("parse",f,G,W,{status:K.status,statusText:K.statusText,parseError:H.parseError,responsePreview:z4(E,A)}))}}if(!K.ok||DO(H.body,y)){let O=$G(H.body),z=O||Y$(K.status,K.statusText);throw new Cl(z,L$("http",f,G,W,{status:K.status,statusText:K.statusText,upstreamMessage:O,responsePreview:z4(H.parseError?E:H.body,A)}))}return H.body}async function JG(f,u={}){let _=yG(u),y=new Date,l;try{l=await fetch(f,lG(u))}catch(A){let U=B$(A,"网络请求失败");throw new Cl(U,L$("network",f,_,y,{upstreamMessage:U}))}if(l.ok)return l.blob();let $=await l.text(),j=jG($),J=$G(j.body),F=J||Y$(l.status,l.statusText);throw new Cl(F,L$("http",f,_,y,{status:l.status,statusText:l.statusText,upstreamMessage:J,responsePreview:z4(j.parseError?$:j.body),parseError:j.parseError||void 0}))}function FG(f){return Boolean(f&&typeof f==="object"&&f.unideskRequestError===!0&&f.meta)}function wO(f){if(!f)return"";let u=new Date(f);if(Number.isNaN(u.getTime()))return f;return`${zf(u)} ${s6}`}function o7(f,u="操作失败"){if(FG(f)){let l=f.meta.kind==="parse"?"响应解析失败":f.meta.kind==="network"?"网络请求失败":f.meta.status&&(f.meta.status<200||f.meta.status>=300)?Y$(f.meta.status,f.meta.statusText):"应用请求失败",$=f.meta.status?Y$(f.meta.status):"",j=(F)=>!F||F===l||F===$,J=!j(f.message)?f.message:j(f.meta.upstreamMessage)?"":f.meta.upstreamMessage||"";return{title:l,message:J,status:f.meta.status,statusText:f.meta.statusText,method:f.meta.method,url:f.meta.url,occurredAt:wO(f.meta.occurredAt),responsePreview:f.meta.responsePreview,parseError:f.meta.parseError,structured:!0}}let y=B$(f,u).split(/\r?\n/u);return{title:y[0]||u,message:y.slice(1).join(` +`),structured:y.length>1}}function TO(f,u="操作失败"){let _=o7(f,u),y=[_.title];if(_.message)y.push(`原因: ${_.message}`);if(_.method||_.url)y.push(`请求: ${[_.method,_.url].filter(Boolean).join(" ")}`);if(_.status)y.push(`状态: ${Y$(_.status,_.statusText)}`);if(_.occurredAt)y.push(`时间: ${_.occurredAt}`);if(_.parseError)y.push(`解析错误: ${_.parseError}`);if(_.responsePreview&&_.responsePreview!==_.message)y.push(`响应预览: ${_.responsePreview}`);return y.filter(Boolean).join(` +`)}function Pf(f,u="操作失败"){return FG(f)?TO(f,u):B$(f,u)}var QG=Sf(c0(),1);var P_=QG.default.createElement;function D$(f,u){return u?[P_("dt",{key:`${f}-label`},f),P_("dd",{key:f},u)]:null}function H0({error:f,wide:u=!1,fallback:_="操作失败",className:y=""}){if(!f)return null;let l=o7(f,_),$=[D$("请求",[l.method,l.url].filter(Boolean).join(" ")),D$("状态",l.status?`HTTP ${l.status}${l.statusText?` ${l.statusText}`:""}`:""),D$("时间",l.occurredAt),D$("解析错误",l.parseError),D$("响应预览",l.responsePreview)].filter(Boolean);return P_("div",{className:`form-error unidesk-error${u?" wide":""}${y?` ${y}`:""}`,role:"alert","data-testid":"unidesk-error"},P_("div",{className:"unidesk-error-title"},P_("strong",null,l.title),l.status?P_("span",{className:"unidesk-error-code"},`HTTP ${l.status}`):null),l.message?P_("pre",{className:"unidesk-error-message"},l.message):null,$.length>0?P_("dl",{className:"unidesk-error-details"},$):null)}var m=q4.default.createElement,{useEffect:rO}=q4.default,K4=q4.default.useState,Dy={label:"主用户私聊账号",userId:645275593};function a7(f){let u=Number(f);return Number.isFinite(u)?u.toLocaleString("zh-CN"):"--"}async function a1(f,u={}){return wf(f,{failureFields:["ok","success"],...u})}function Z4({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return m("span",{className:`status-badge ${_}`},u||f||"unknown")}function Rl({label:f,value:u,hint:_,tone:y}){return m("article",{className:`metric-card ${y||""}`},m("div",{className:"metric-label"},f),m("div",{className:"metric-value"},u),m("div",{className:"metric-hint"},_))}function xl({title:f,eyebrow:u,actions:_,children:y,className:l}){return m("section",{className:`panel ${l||""}`},m("div",{className:"panel-head"},m("div",null,u?m("p",{className:"panel-eyebrow"},u):null,m("h2",null,f)),_?m("div",{className:"panel-actions"},_):null),m("div",{className:"panel-body"},y))}function w$({title:f,data:u,onOpen:_,testId:y}){return m("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:(l)=>{l?.stopPropagation?.(),_(f,u)}},"查看原始JSON")}function T$({title:f,text:u}){return m("div",{className:"empty-state"},m("strong",null,f),m("span",null,u))}function MO(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function PO(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function SO(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function S_(f,u){return`${f}/microservices/claudeqq/proxy${u}`}function CO(f){return Array.isArray(f?.events)?f.events.slice(0,80):[]}function RO(f){return Array.isArray(f?.subscriptions)?f.subscriptions.slice(0,50):[]}function xO(f){return Array.isArray(f?.messages)?f.messages.slice(0,30):[]}function AG(f){let u=f?.text??f?.message??f?.raw?.raw_message;if(typeof u!=="string")return"--";return u.length>180?`${u.slice(0,177)}...`:u}function UG(f){let u=f?.groupId??f?.group_id??(f?.message_type==="group"?f?.target_id:void 0),_=f?.userId??f?.user_id??(f?.message_type==="private"?f?.target_id:void 0);if(u)return`群 ${u}`;if(_)return`私聊 ${_}`;return"--"}function WG({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((w)=>w.id==="claudeqq")||null,[l,$]=K4({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}),[j,J]=K4({targetType:"private",targetId:String(Dy.userId),message:""}),[F,A]=K4({name:"unidesk-callback",targetUrl:"",eventTypes:"message",secret:""}),[U,G]=K4("");async function W(){if(!y)return;$((w)=>({...w,loading:!0,error:""}));try{let[w,Y,R,k,p]=await Promise.all([a1(`${_}/microservices/claudeqq/health`),a1(S_(_,"/api/server/status")),a1(S_(_,"/api/events/recent?limit=60")),a1(S_(_,"/api/events/subscriptions")),a1(S_(_,"/api/messages/sent?limit=20"))]);if($((n)=>({...n,loading:!1,error:"",health:w,status:Y,events:R,subscriptions:k,sent:p,refreshedAt:new Date})),!l.qrcodeFetched)K(!1)}catch(w){$((Y)=>({...Y,loading:!1,error:Pf(w,"ClaudeQQ 加载失败")}))}}async function K(w=!0){if(!y)return;$((Y)=>({...Y,qrLoading:!0,error:w?"":Y.error}));try{let Y=await a1(S_(_,"/api/napcat/login")),R=Y?.napcat?.qrcode||Y?.qrcode||null;$((k)=>({...k,qrLoading:!1,error:"",napcatLogin:Y,napcatQrcode:R,qrcodeFetched:!0,qrcodeRefreshedAt:new Date}))}catch(Y){$((R)=>({...R,qrLoading:!1,error:w||!R.napcatQrcode?Pf(Y,"NapCat 二维码加载失败"):R.error}))}}async function E(w){w.preventDefault(),G("");let Y=Number(j.targetId);if(!Number.isFinite(Y)||Y<=0||j.message.trim().length===0){$((R)=>({...R,error:"请填写 QQ 目标和消息内容"}));return}try{await a1(S_(_,"/api/push/text"),{method:"POST",body:JSON.stringify({userId:j.targetType==="private"?Y:void 0,groupId:j.targetType==="group"?Y:void 0,message:j.message})}),J((R)=>({...R,targetType:"private",targetId:String(Dy.userId),message:""})),G("消息推送请求已提交"),await W()}catch(R){$((k)=>({...k,error:Pf(R,"发送失败")}))}}async function H(w){if(w.preventDefault(),G(""),F.targetUrl.trim().length===0){$((Y)=>({...Y,error:"请填写订阅回调 URL"}));return}try{await a1(S_(_,"/api/events/subscriptions"),{method:"POST",body:JSON.stringify({name:F.name,targetUrl:F.targetUrl,eventTypes:F.eventTypes.split(",").map((Y)=>Y.trim()).filter(Boolean),secret:F.secret||void 0,enabled:!0})}),G("事件订阅已创建"),await W()}catch(Y){$((R)=>({...R,error:Pf(Y,"订阅失败")}))}}async function O(w){if(!w)return;G("");try{await a1(S_(_,`/api/events/subscriptions/${encodeURIComponent(w)}`),{method:"DELETE"}),G("事件订阅已删除"),await W()}catch(Y){$((R)=>({...R,error:Pf(Y,"删除订阅失败")}))}}if(rO(()=>{if(!y)return;W();return},[y?.id,y?.runtime?.providerStatus]),!y)return m(T$,{title:"ClaudeQQ 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=claudeqq"});let z=MO(y),q=SO(y),Z=PO(y),V=l.health||{},L=l.status||{},r=l.napcatLogin||{},N=V.napcat||L.napcat||{},D={...r.napcat||{},...N,qrcode:l.napcatQrcode||{},webui:N.webui||r.napcat?.webui},x=r.login||{},c=l.napcatQrcode||{},v=CO(l.events),C=RO(l.subscriptions),S=xO(l.sent),B=Boolean(D.httpConnected||x.ready),P=String(D.loginState||x.state||(B?"logged_in":"unknown")),M=Boolean(c.available&&c.dataUrl);return m("div",{className:"claudeqq-page","data-testid":"claudeqq-page"},m(xl,{title:"ClaudeQQ 工作台",eyebrow:"D601 QQ Event Gateway",actions:m("div",{className:"panel-actions"},m("button",{type:"button",className:"ghost-btn",onClick:W,disabled:l.loading,"data-testid":"claudeqq-refresh-button"},l.loading?"刷新中":"刷新"),m(w$,{title:"ClaudeQQ 用户服务",data:y,onOpen:u,testId:"raw-claudeqq-service"}))},m("div",{className:"findjob-hero"},m("div",null,m("div",{className:"node-version-line"},m(Z4,{status:z.providerStatus==="online"?"online":"warn"},z.providerStatus||"unknown"),m("span",null,y.providerId),m("span",null,Z.public?"公网暴露":"仅 UniDesk frontend 代理访问")),m("p",{className:"muted paragraph"},y.description)),m("div",{className:"microservice-ref-card"},m("span",null,"Repo"),m("strong",null,q.url||"--"),m("code",null,q.commitId||"--")),m("div",{className:"microservice-ref-card"},m("span",null,"D601 Docker"),m("strong",null,`${Z.nodeBindHost||"--"}:${Z.nodePort||"--"}`),m("code",null,`${q.composeFile||"--"} / ${q.composeService||"--"}`))),m(H0,{error:l.error,wide:!0}),U?m("div",{className:"form-success wide"},U):null),m("div",{className:"metric-grid"},m(Rl,{label:"Health",value:V.ok||V.status==="ok"?"OK":"--",hint:"D601 /health",tone:V.ok||V.status==="ok"?"ok":"warn"}),m(Rl,{label:"NapCat HTTP",value:D.httpConnected||D.http?.connected?"OK":"离线",hint:`${D.httpHost||V.napcat?.httpHost||"--"}:${D.httpPort||V.napcat?.httpPort||"--"}`}),m(Rl,{label:"NapCat WS",value:D.wsConnected||D.ws?.connected?"OK":"离线",hint:`${D.wsHost||V.napcat?.wsHost||"--"}:${D.wsPort||V.napcat?.wsPort||"--"}`}),m(Rl,{label:"事件缓存",value:a7(l.events?.count??v.length),hint:"recent QQ events"}),m(Rl,{label:"订阅",value:a7(l.subscriptions?.count??C.length),hint:"webhook subscribers"}),m(Rl,{label:"已发送",value:a7(l.sent?.count??S.length),hint:"sent message log"})),m("div",{className:"findjob-grid"},m(xl,{title:"NapCat 容器登录",eyebrow:"QR Login",className:"claudeqq-login-panel",actions:m("div",{className:"panel-actions inline-actions"},m("button",{type:"button",className:"ghost-btn",onClick:()=>K(!0),disabled:l.qrLoading,"data-testid":"claudeqq-napcat-refresh"},l.qrLoading?"刷新中":"手动刷新二维码"),m(w$,{title:"NapCat Login",data:l.napcatLogin,onOpen:u,testId:"raw-claudeqq-napcat-login"}))},m("div",{className:"claudeqq-login-card","data-testid":"claudeqq-napcat-login"},m("div",{className:"claudeqq-qr-frame"},M?m("img",{src:c.dataUrl,alt:"NapCat QQ 登录二维码","data-testid":"claudeqq-napcat-qrcode"}):m(T$,{title:"等待二维码",text:"NapCat 容器启动后会把登录二维码写入 cache/qrcode.png"})),m("div",{className:"claudeqq-login-copy"},m("div",{className:"node-version-line"},m(Z4,{status:B?"online":M?"warn":"unknown"},B?"已登录":M?"待扫码":"等待二维码"),m("span",null,P),m("span",null,"D601 containerized")),m("p",{className:"muted paragraph"},B?"NapCat 已登录,ClaudeQQ 可通过容器内 HTTP/WS 链路收发 QQ 消息。":"用手机 QQ 扫描二维码授权登录。二维码只在首次加载或手动刷新时更新,D601 的 NapCat 端口仍只绑定 127.0.0.1。"),m("div",{className:"microservice-ref-card"},m("span",null,"NapCat WebUI"),m("strong",null,D.webui?.url||"http://napcat:6099/webui"),m("code",null,"local-only / proxied QR login")),m("div",{className:"microservice-ref-card"},m("span",null,"QR Source"),m("strong",null,c.modifiedAt?zf(c.modifiedAt):l.qrcodeRefreshedAt?zf(l.qrcodeRefreshedAt):"--"),m("code",null,c.file||"/napcat/cache/qrcode.png"))))),m(xl,{title:"消息推送",eyebrow:"Push API"},m("div",{className:"microservice-ref-card"},m("span",null,Dy.label),m("strong",null,String(Dy.userId)),m("code",null,"private userId / 默认推送测试目标")),m("form",{className:"stack-form",onSubmit:E,"data-testid":"claudeqq-push-form"},m("label",null,"目标类型",m("select",{value:j.targetType,onChange:(w)=>J((Y)=>({...Y,targetType:w.target.value}))},m("option",{value:"private"},"私聊 userId"),m("option",{value:"group"},"群 groupId"))),m("label",null,"QQ ID",m("input",{value:j.targetId,onChange:(w)=>J((Y)=>({...Y,targetId:w.target.value})),placeholder:String(Dy.userId)})),m("label",null,"消息内容",m("textarea",{value:j.message,onChange:(w)=>J((Y)=>({...Y,message:w.target.value})),rows:4,placeholder:"通过 ClaudeQQ 推送一条 QQ 消息"})),m("button",{type:"submit",className:"primary-btn"},"发送 QQ 消息")),m("p",{className:"muted paragraph"},`主 server 和其他用户服务可通过 UniDesk 同源代理调用 /api/push/text;当前人工推送测试默认使用 ${Dy.label} ${Dy.userId},不需要暴露 D601 后端端口。`)),m(xl,{title:"QQ 事件订阅",eyebrow:"Webhook Subscription"},m("form",{className:"stack-form",onSubmit:H,"data-testid":"claudeqq-subscription-form"},m("label",null,"订阅名称",m("input",{value:F.name,onChange:(w)=>A((Y)=>({...Y,name:w.target.value}))})),m("label",null,"回调 URL",m("input",{value:F.targetUrl,onChange:(w)=>A((Y)=>({...Y,targetUrl:w.target.value})),placeholder:"http://host.docker.internal:18080/..."})),m("label",null,"事件类型",m("input",{value:F.eventTypes,onChange:(w)=>A((Y)=>({...Y,eventTypes:w.target.value})),placeholder:"message,notice"})),m("label",null,"签名密钥",m("input",{value:F.secret,onChange:(w)=>A((Y)=>({...Y,secret:w.target.value})),placeholder:"可选,生成 x-claudeqq-signature"})),m("button",{type:"submit",className:"primary-btn"},"创建订阅")),C.length===0?m(T$,{title:"暂无订阅",text:"可以为 main server 或其他用户服务注册 HTTP webhook"}):m("div",{className:"table-wrap","data-testid":"claudeqq-subscription-table"},m("table",null,m("thead",null,m("tr",null,m("th",null,"名称"),m("th",null,"状态"),m("th",null,"事件"),m("th",null,"回调"),m("th",null,"最近投递"),m("th",null,"操作"))),m("tbody",null,C.map((w)=>m("tr",{key:w.id},m("td",null,m("strong",null,w.name||w.id),m("code",null,w.id||"--")),m("td",null,m(Z4,{status:w.enabled?"online":"warn"},w.enabled?"enabled":"disabled")),m("td",null,Array.isArray(w.eventTypes)?w.eventTypes.join(", "):"message"),m("td",null,w.targetUrl||"--"),m("td",null,w.lastDelivery?`${w.lastDelivery.ok?"OK":"FAIL"} ${zf(w.lastDelivery.at)}`:"--"),m("td",null,m("button",{type:"button",className:"ghost-btn",onClick:()=>O(w.id)},"删除"))))))),m("div",{className:"panel-actions inline-actions"},m(w$,{title:"ClaudeQQ Subscriptions",data:l.subscriptions,onOpen:u,testId:"raw-claudeqq-subscriptions"}))),m(xl,{title:"最近 QQ 事件",eyebrow:l.refreshedAt?`Updated ${L0(l.refreshedAt)}`:"Event Stream"},v.length===0?m(T$,{title:"暂无事件",text:"等待 NapCat WebSocket 上报 QQ 消息事件,或通过订阅 API 消费后续事件"}):m("div",{className:"table-wrap","data-testid":"claudeqq-event-list"},m("table",null,m("thead",null,m("tr",null,m("th",null,"时间"),m("th",null,"类型"),m("th",null,"会话"),m("th",null,"消息"),m("th",null,"ID"))),m("tbody",null,v.map((w)=>m("tr",{key:w.id},m("td",null,zf(w.receivedAt||w.timestamp)),m("td",null,m(Z4,{status:w.postType||w.eventType},w.postType||w.eventType||"--")),m("td",null,UG(w)),m("td",null,AG(w)),m("td",null,m("code",null,w.messageId||w.id||"--"))))))),m("div",{className:"panel-actions inline-actions"},m(w$,{title:"ClaudeQQ Events",data:l.events,onOpen:u,testId:"raw-claudeqq-events"}))),m(xl,{title:"已发送消息",eyebrow:`${S.length} Sent`},S.length===0?m(T$,{title:"暂无发送记录",text:"发送日志来自 ClaudeQQ bot_workspace/messages/sent_messages.jsonl"}):m("div",{className:"table-wrap"},m("table",null,m("thead",null,m("tr",null,m("th",null,"时间"),m("th",null,"目标"),m("th",null,"消息"),m("th",null,"结果"))),m("tbody",null,S.map((w,Y)=>m("tr",{key:w.id||Y},m("td",null,zf(w.timestamp||w.sentAt||w.createdAt)),m("td",null,UG(w)),m("td",null,AG(w)),m("td",null,w.status||w.messageId||w.message_id||"--")))))),m("div",{className:"panel-actions inline-actions"},m(w$,{title:"ClaudeQQ Sent Messages",data:l.sent,onOpen:u,testId:"raw-claudeqq-sent"})))))}var T4=Sf(c0(),1);var jj=Sf(c0(),1);var Lf=jj.default.createElement,{useEffect:vO,useRef:GG}=jj.default;function bO(f,u){return TG(f.toTrace(u))}function hO(f){let u=Number(f);if(!Number.isFinite(u)||u<0)return"--";let _=Math.floor(u/1000),y=Math.floor(_/3600),l=Math.floor(_%3600/60),$=_%60;if(y>0)return`${y}h ${String(l).padStart(2,"0")}m`;if(l>0)return`${l}m ${String($).padStart(2,"0")}s`;return`${$}s`}function wy(f){let u=Number(f);return Number.isFinite(u)&&u>=0?u:null}function OG(f,u=180){let _=String(f||"").replace(/\s+/gu," ").trim();return _.length>u?`${_.slice(0,u-1)}…`:_}function IO(f){if(!f)return 0;return f.split(/\r?\n/u).length}function _j(f){return{ran:"Ran",explored:"Explored",edited:"Edited",toolGroup:"Tool calls",plan:"Plan",message:"Message",system:"System",error:"Error"}[f]||"Message"}function yj(f){let u=Number(f||0);return Number.isFinite(u)&&u>0?`… +${Math.floor(u)} lines`:""}function cO(f){return(Array.isArray(f)?f:[]).reduce((u,_)=>Math.max(u,Number(_?.seq??0)),0)}function zG(f){return["explored","edited","ran"].includes(String(f?.kind||""))}function XG(f){let u={read:0,edit:0,run:0};for(let _ of f){let y=String(_?.kind||"");if(y==="explored")u.read+=1;else if(y==="edited")u.edit+=1;else if(y==="ran")u.run+=1}return u}function NG(f){let u=XG(f);return`${u.read} read, ${u.edit} edit, ${u.run} run`}function LG(f){return f.replace(/^['"`([{<]+/u,"").replace(/['"`)\]}>.,;:]+$/u,"").replace(/:\d+(?::\d+)?$/u,"").trim()}function KG(f){let _=String(f||"").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)||[],y=[];for(let l of _){let $=LG(l);if($.length<2||$.includes("..."))continue;if(/^(http|https|status|method)$/iu.test($))continue;if(!y.includes($))y.push($)}return y}function d7(f,u=4){if(f.length===0)return"--";let _=f.slice(0,u).join(", ");return f.length>u?`${_} +${f.length-u}`:_}function ZG(f){let u="";for(let _ of f){if(_.length===0)continue;if(u.length>0&&!u.endsWith(` `)&&!_.startsWith(` `))u+=` -`;u+=_}return u}function Oz(f){let u=String(f||"").replace(/\r\n/gu,` +`;u+=_}return u}function YG(f){let u=String(f||"").replace(/\r\n/gu,` `).replace(/\r/gu,` `).trimEnd();return u.length>0?u.split(` -`):[]}function _j(f){let u=String(f.status||"").trim();if(u.length>0)return u;let _=String(f.bodyPreview||"");return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(_)?.[1]||"item/fileChange"}function pO(f){let u=String(f.bodyPreview||"");return/file changes status=([A-Za-z0-9_-]+)/u.exec(u)?.[1]}function mO(f){return/^item\/(?:started|completed): file changes status=/u.test(String(f||"").trim())}function Xz(f){if(String(f.kind||"")!=="edited")return!1;let u=String(f.status||""),_=String(f.title||""),y=String(f.bodyPreview||""),$=String(f.commandPreview||"");if(_==="Edited files")return!0;if(/^item\/fileChange\//u.test(u))return!0;if((u==="item/started"||u==="item/completed")&&/file changes status=/u.test(y))return!0;if(/^Success\. Updated the following files:/mu.test(y))return!0;if(/^diff --git /mu.test(y))return!0;return $.length===0&&/^([AMDRCU?]{1,2})\s+\S+/mu.test(y)}function I3(f){return Vz(String(f||"").replace(/^[ab]\//u,"").trim())}function lj(f){let u=/^([AMDRCU?]{1,2})\s+(.+)$/u.exec(f);if(!u)return null;let _=I3(u[2]||"");return _.length>0?{status:u[1]||"M",path:_}:null}function jj(f){let u=/^\*\*\*\s+(Add|Update|Delete)\s+File:\s+(.+)$/u.exec(f);if(u){let y=u[1]==="Add"?"A":u[1]==="Delete"?"D":"M",$=I3(u[2]||"");return $.length>0?{status:y,path:$}:null}let _=/^\*\*\*\s+Move to:\s+(.+)$/u.exec(f);if(_){let y=I3(_[1]||"");return y.length>0?{status:"R",path:y}:null}return null}function kO(f){let u=[],_=($,l)=>{let j=I3(l);if(j.length===0||j==="/dev/null")return;let J=u.find((F)=>F.path===j);if(J){if(J.status==="M"&&$!=="M")J.status=$;return}u.push({status:$,path:j})},y="";for(let $ of Oz(f)){let l=lj($)||jj($);if(l!==null){_(l.status,l.path),y=l.path;continue}let j=/^diff --git a\/(.+?) b\/(.+)$/u.exec($);if(j){let z=j[2]||j[1]||"";_("M",z),y=I3(z);continue}let J=/^\+\+\+ b\/(.+)$/u.exec($);if(J&&J[1]!=="/dev/null"){_("M",J[1]||""),y=I3(J[1]||"");continue}if(/^new file mode /u.exec($)&&y)_("A",y);if(/^deleted file mode /u.exec($)&&y)_("D",y);let U=/^rename to (.+)$/u.exec($);if(U)_("R",U[1]||"")}return u}function iO(f){if(lj(f)!==null||jj(f)!==null)return"file";if(/^(diff --git |index |--- |\+\+\+ |\*\*\* Begin Patch|\*\*\* End Patch)/u.test(f))return"meta";if(/^@@ /u.test(f))return"hunk";if(/^\+/u.test(f))return"add";if(/^-/u.test(f))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(f))return"note";return"context"}function gO(f){return Oz(f).map((u)=>{let _=lj(u)||jj(u);if(_!==null)return{text:u,kind:"file",path:_.path,status:_.status};return{text:u,kind:iO(u)}})}function nO(f){return f.reduce((u,_)=>{if(_.kind==="add")u.added+=1;else if(_.kind==="del")u.removed+=1;return u},{added:0,removed:0})}function Wz(f,u){return`${u} ${f} line${f===1?"":"s"}`}function tO(f,u){let _=[];if(f>0)_.push(Wz(f,"Added"));if(u>0)_.push(Wz(u,"removed"));return _.join(", ")}function sO(f){for(let _=f.length-1;_>=0;_-=1){let y=String(f[_]?.status||"").trim();if(y.length>0)return y}let u=String(f[f.length-1]?.method||"").trim();if(u==="item/fileChange/outputDelta")return"updated";if(u==="item/started")return"started";if(u==="item/completed")return"completed";return u.replace(/^item\//u,"")||"changed"}function oO(f){return`${f} file${f===1?"":"s"}`}function Nz(f){let u=f.length>0?f:[],_=Uz(u.map((W)=>String(W.bodyPreview||""))),$=Uz(u.map((W)=>String(W.bodyPreview||"")).filter((W)=>W.trim().length>0&&!mO(W)))||_,l=kO($||_),j=u.map((W)=>({method:_j(W),status:pO(W),at:W.at})),J=gO($||_),F=nO(J),A=tO(F.added,F.removed),U=l.length>0?oO(l.length):"",z=A.length>0?`${A}${U?` in ${U}`:""}`:l.length>0?U:qz($||_||"File changes",72);return{status:sO(j),summary:z,files:l,stages:j,lines:J,addedLines:F.added,removedLines:F.removed,rawText:_}}function aO(f){let u=f[0],_=f[f.length-1]||u,y=Nz(f);return{...u,seq:Number.isFinite(Number(_?.seq))?Number(_?.seq):Number(u?.seq??0),at:_?.at||u?.at,title:y.files.length>0?`Edited ${y.summary}`:"Edited files",status:y.status,commandPreview:"",commandOmittedLines:void 0,bodyPreview:y.rawText,bodyOmittedLines:f.reduce(($,l)=>$+Number(l.bodyOmittedLines||0),0)||void 0,rawSeqs:f.flatMap(($)=>Array.isArray($?.rawSeqs)?$.rawSeqs:[$?.seq]).filter(($)=>$!==void 0),editObservation:y}}function dO(f){let u=Array.isArray(f)?f:[],_=[],y=[],$=()=>{if(y.length===0)return;_.push(aO(y)),y=[]};for(let l of u){if(Xz(l)){if(_j(l)==="item/started"&&y.length>0)$();if(y.push(l),_j(l)==="item/completed")$();continue}$(),_.push(l)}return $(),_}function Lz(f){let u=[],_=[],y=[],$=(A,U)=>{for(let z of U)if(!A.includes(z))A.push(z)};for(let A of f){let U=String(A?.kind||""),z=[A?.commandPreview,A?.bodyPreview,A?.title].map((W)=>String(W||"")).join(` -`);if(U==="explored")$(u,Az(z));else if(U==="edited")$(_,Az(z));else if(U==="ran"){let W=String(A?.commandPreview||A?.title||"").trim();if(W.length>0&&!y.includes(W))y.push(qz(W,90))}}let l=f.map((A)=>Date.parse(String(A?.at||""))).filter((A)=>Number.isFinite(A)),j=l.length>=2?Math.max(0,Math.max(...l)-Math.min(...l)):0,J=f.reduce((A,U)=>A+(Dy(U?.durationMs)??Dy(U?.elapsedMs)??0),0),F=j>0?j:J;return{readFiles:u,editedFiles:_,runCommands:y,durationLabel:hO(F)}}function eO(f,u=3){let _=Array.isArray(f)?f:[],y=[],$=[],l=Math.max(0,u),j=new Set;for(let F=_.length-1;F>=0&&l>0;F-=1){let A=_[F];if(!Qz(A))continue;j.add(A),l-=1}let J=()=>{if($.length>=2){let F=Hz($);y.push({seq:Number($[0]?.seq??0),at:$[0]?.at||$.at(-1)?.at,kind:"toolGroup",title:Ez($),status:`${$.length} calls`,items:$,counts:F,digest:Lz($),rawSeqs:$.flatMap((A)=>Array.isArray(A?.rawSeqs)?A.rawSeqs:[A?.seq]).filter((A)=>A!==void 0)})}else y.push(...$);$=[]};for(let F of _){if(Qz(F)&&!j.has(F)){$.push(F);continue}J(),y.push(F)}return J(),y}function Yz(f){return(Array.isArray(f)?f:[]).map((u,_)=>({...u,seq:Number.isFinite(Number(u?.seq))?Number(u.seq):_+1,kind:String(u?.kind||"message"),at:u?.at===void 0?void 0:String(u.at),durationMs:Dy(u?.durationMs)??void 0,title:u?.title===void 0?void 0:String(u.title),status:u?.status===void 0?void 0:String(u.status)}))}function a7(f){return Dy(f?.durationMs)??Dy(f?.elapsedMs)??Dy(f?.timing?.durationMs)??Dy(f?.metadata?.durationMs)??void 0}function d7(f,u){return f?.createdAt||f?.updatedAt||f?.completedAt||u||void 0}function e7(f,u){return f?.id||f?.messageId||u}function yj(f,u){let _=new Set(u.map((y)=>y.toLowerCase()));for(let y of Array.isArray(f?.inputFields)?f.inputFields:[]){let $=String(y?.key||"").toLowerCase();if(_.has($))return String(y?.value||"")}return""}function fX(f){let u=String(f?.tool||f?.title||"").toLowerCase();if(/read|grep|glob|list|ls|find|search|view|cat|sed|rg/u.test(u))return"explored";if(/edit|write|patch|apply|update|create|delete/u.test(u))return"edited";let _=yj(f,["command","cmd"]);if(/\b(rg|grep|find|ls|cat|sed|tail|head|git status|git diff|ps)\b/u.test(_))return"explored";if(/\b(apply_patch|git apply|cat >|tee .*<<|sed -i|python3? .*write_text)\b/u.test(_))return"edited";return"ran"}function uX(f){let u=[],_=1;for(let y of Array.isArray(f)?f:[]){let $=y?.createdAt||y?.updatedAt||y?.completedAt,l=String(y?.role||"assistant").toLowerCase(),j=Array.isArray(y?.parts)?y.parts:[];for(let J of j){let F=String(J?.type||"").toLowerCase();if(F==="step-start"||F==="step-finish")continue;if(F==="text"||F==="reasoning"){let U=String(J?.textPreview||y?.textPreview||"").trim();if(U.length===0)continue;u.push({seq:_++,at:d7(J,$),kind:"message",title:F==="reasoning"?"Reasoning":l==="user"?"User message":l==="system"?"System message":"Assistant message",status:F==="reasoning"?"reasoning":l,bodyPreview:U,durationMs:a7(J),rawSeqs:[e7(J,_)]});continue}if(F==="tool"){let U=yj(J,["command","cmd"])||yj(J,["filePath","filepath","path"])||String(J?.title||J?.tool||"tool"),z=String(J?.outputPreview&&J.outputPreview!=="--"?J.outputPreview:J?.textPreview||"");u.push({seq:_++,at:d7(J,$),kind:fX(J),title:String(J?.title||J?.tool||"tool"),status:String(J?.status||""),commandPreview:U,bodyPreview:z,durationMs:a7(J),rawSeqs:[e7(J,_)]});continue}let A=String(J?.textPreview||J?.title||F||"").trim();if(A)u.push({seq:_++,at:d7(J,$),kind:"system",title:F||"part",bodyPreview:A,status:String(J?.status||""),durationMs:a7(J),rawSeqs:[e7(J,_)]})}if(j.length===0&&y?.textPreview)u.push({seq:_++,at:$,kind:"message",title:`${l||"assistant"} message`,status:l,bodyPreview:String(y.textPreview),rawSeqs:[y?.messageId||_]})}return u}var Bz={source:"opencode",toTrace:uX};function _X(f){return String(f||"unknown").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-")||"unknown"}function zz(f){let u=String(f||"M").toUpperCase();if(u.startsWith("A")||u==="??")return"added";if(u.startsWith("D"))return"deleted";if(u.startsWith("R"))return"renamed";return"modified"}function yX(f){if(f==="item/fileChange/outputDelta")return"delta";return f.replace(/^item\//u,"")}function $X(f,u){if(f.kind==="file"){let $=String(f.status||"M");return Lf("div",{key:`${u}-${f.text}`,className:`codex-edit-diff-line file ${zz($)}`},Lf("span",{className:`codex-edit-file-status ${zz($)}`},$),Lf("code",null,f.path||f.text.replace(/^([AMDRCU?]{1,2})\s+/u,"")))}let _=f.kind==="add"||f.kind==="del"?f.text.slice(0,1):f.kind==="hunk"?"@@":f.kind==="note"?"ok":"",y=f.kind==="add"||f.kind==="del"?f.text.slice(1):f.text;return Lf("div",{key:`${u}-${f.text}`,className:`codex-edit-diff-line ${f.kind}`},Lf("span",{className:"codex-edit-diff-sign"},_),Lf("code",null,y||" "))}function lX(f,u){let _=f.lines.length>0?f.lines:f.files.map(($)=>({text:`${$.status} ${$.path}`,kind:"file",path:$.path,status:$.status})),y=Number(f.addedLines||0)+Number(f.removedLines||0)>0;return Lf("div",{className:"codex-edit-observation","data-testid":"codex-edit-observation"},Lf("div",{className:"codex-edit-observation-head"},Lf("span",{className:"codex-edit-window-controls","aria-hidden":"true"},Lf("i",null),Lf("i",null),Lf("i",null)),Lf("strong",null,y?"git diff":"git diff --stat"),Lf("code",null,f.summary||"File changes")),f.stages.length>0?Lf("div",{className:"codex-edit-stage-strip"},f.stages.map(($,l)=>Lf("span",{key:`${$.method}-${l}`,className:`codex-edit-stage ${_X($.status||$.method)}`},Lf("b",null,yX($.method)),$.status?Lf("em",null,$.status):null))):null,_.length>0?Lf("div",{className:"codex-edit-diff",role:"list"},_.map($X)):null,u?Lf("div",{className:"codex-edit-omitted"},`${u} (查看原始JSON获取完整记录)`):null)}function Gz(f,u,_){let y=uj(_);return Lf("div",{className:`codex-transcript-stream ${f}`,"data-testid":`codex-trace-${f}`},Lf("span",{className:"codex-transcript-stream-label"},f),Lf("pre",{className:"codex-transcript-body"},u,y?` -${y} (查看原始JSON获取完整记录)`:""))}function wz(f,u=!1){let _=String(f.kind||"message"),y=["ran","explored","edited"].includes(_),$=uj(f.commandOmittedLines),l=uj(f.bodyOmittedLines),j=String(f.commandPreview||(y?f.title||"":"")),J=String(f.stdoutPreview||""),F=String(f.stderrPreview||""),A=J.length>0||F.length>0,U=Boolean(f.foldedReferencePrompt)&&String(f.fullPrompt||"").length>0,z=_==="edited"&&(f.editObservation!==void 0||Xz(f))?f.editObservation||Nz([f]):null;return Lf("article",{key:`${f.seq}-${_}`,className:`codex-transcript-item ${_} ${u?"nested":""}`},Lf("div",{className:"codex-transcript-main"},Lf("div",{className:"codex-transcript-title"},Lf("span",{className:"codex-output-channel"},fj(_)),y&&z===null?null:Lf("strong",null,z!==null?"File changes":String(f.title||fj(_))),f.status?Lf("code",null,String(z?.status||f.status)):null,Lf("time",null,Zz(f.at))),j&&z===null?Lf("pre",{className:"codex-transcript-command"},j,$?` -${$}`:""):null,z!==null?lX(z,l):A?Lf("div",{className:"codex-transcript-streams"},J.length>0?Gz("stdout",J,f.stdoutOmittedLines):null,F.length>0?Gz("stderr",F,f.stderrOmittedLines):null):f.bodyPreview?Lf("pre",{className:"codex-transcript-body"},String(f.bodyPreview),l?` -${l} (查看原始JSON获取完整记录)`:""):null,U?Lf("details",{className:"codex-initial-prompt-full","data-testid":"codex-initial-prompt-full"},Lf("summary",null,Lf("span",null,"引用注入已折叠,点击查看最终传入 Codex 的完整 prompt"),Lf("code",null,`${f.fullPromptLines||IO(String(f.fullPrompt||""))} lines / ${f.fullPromptChars||String(f.fullPrompt||"").length} chars`)),Lf("pre",{className:"codex-transcript-body codex-transcript-full-prompt","data-testid":"codex-initial-prompt-full-text"},String(f.fullPrompt||""))):null))}function jX(f){let u=Array.isArray(f.items)?f.items:[],_=f.digest&&typeof f.digest==="object"?f.digest:Lz(u);return Lf("article",{key:`${f.seq}-toolGroup`,className:"codex-transcript-item toolGroup"},Lf("div",{className:"codex-transcript-main"},Lf("details",{className:"codex-tool-group","data-testid":"codex-tool-group"},Lf("summary",null,Lf("div",{className:"codex-tool-group-head"},Lf("span",{className:"codex-output-channel"},fj("toolGroup")),Lf("strong",null,String(f.title||Ez(u))),Lf("code",null,String(f.status||`${u.length} calls`)),Lf("time",null,Zz(f.at)))),Lf("div",{className:"codex-tool-group-digest"},Lf("span",null,`read: ${o7(Array.isArray(_.readFiles)?_.readFiles:[])}`),Lf("span",null,`edit: ${o7(Array.isArray(_.editedFiles)?_.editedFiles:[])}`),Lf("span",null,`run: ${o7(Array.isArray(_.runCommands)?_.runCommands:[],2)}`),Lf("span",null,`duration: ${_.durationLabel||"--"}`)),Lf("div",{className:"codex-tool-group-items"},u.map((y)=>wz(y,!0))))))}var JX=16;function Kz(f){return f.scrollHeight-f.scrollTop-f.clientHeight<=JX}function X4({items:f,input:u,port:_,autoScroll:y=!1,loading:$=!1,hasDetail:l=!0,emptyText:j="等待 Trace 输出...",loadingText:J="正在加载完整 Trace...",testId:F="trace-output",className:A="codex-transcript",keepRecentToolCalls:U=3,collapseTools:z=!0}){let W=Fz(null),K=Fz(!0),q=dO(_?bO(_,u):Yz(f)),E=z?eO(q,U):q,O=cO(q);vO(()=>{let Z=W.current;if(!y||!Z)return;if(!K.current&&!Kz(Z))return;Z.scrollTop=Z.scrollHeight,K.current=!0},[y,q.length,O]);let H={className:A,ref:W,onScroll:(Z)=>{let V=Z.currentTarget;K.current=Kz(V)},"data-testid":F};if($&&!l)return Lf("div",H,Lf("div",{className:"codex-output-empty"},J));return Lf("div",H,E.length===0?Lf("div",{className:"codex-output-empty"},j):E.map((Z)=>String(Z.kind||"")==="toolGroup"?jX(Z):wz(Z)))}var B=S4.default.createElement,{useEffect:C6,useMemo:Dz,useRef:Zu}=S4.default,df=S4.default.useState,FX=120,zj=24,QX=48,AX=300,UX=1200;function Tz(){return typeof document>"u"||document.visibilityState!=="hidden"}function Ty(f,u="操作失败"){return Mf(f,u)}function Py(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return u.toLocaleString("zh-CN",{hour12:!1})}function WX(f){return f.toLocaleTimeString("zh-CN",{hour12:!1})}function B4(f){let u=Number(f);if(!Number.isFinite(u)||u<0)return"--";let _=Math.floor(u/1000),y=Math.floor(_/3600),$=Math.floor(_%3600/60),l=_%60;if(y>0)return`${y}h ${String($).padStart(2,"0")}m`;if($>0)return`${$}m ${String(l).padStart(2,"0")}s`;return`${l}s`}function Jj(f){let u=Number(f);if(!Number.isFinite(u)||u<0)return"--";if(u<1000)return`${Math.round(u)}ms`;return`${(u/1000).toFixed(u<1e4?2:1)}s`}function hz(f,u=180){let _=String(f||"").replace(/\s+/gu," ").trim();return _.length>u?`${_.slice(0,u-1)}…`:_}async function M0(f,u={}){return wf(f,{strictJson:!0,retryInvalidJson:1,invalidJsonPrefix:"Codex Queue 返回了无效 JSON",invalidJsonPreview:!0,responsePreviewLength:UX,...u})}function y_({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return B("span",{className:`status-badge ${_}`},u||f||"unknown")}function My({label:f,value:u,hint:_,tone:y}){return B("article",{className:`metric-card ${y||""}`},B("div",{className:"metric-label"},f),B("div",{className:"metric-value"},u),B("div",{className:"metric-hint"},_))}function Sy({title:f,eyebrow:u,summary:_,actions:y,children:$,className:l}){return B("section",{className:`panel ${l||""}`},B("div",{className:"panel-head"},B("div",null,u?B("p",{className:"panel-eyebrow"},u):null,B("h2",null,f),_?B("div",{className:"panel-summary"},_):null),y?B("div",{className:"panel-actions"},y):null),B("div",{className:"panel-body"},$))}function Mz({title:f,data:u,onOpen:_,testId:y}){return B("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function ry({title:f,text:u}){return B("div",{className:"empty-state"},B("strong",null,f),B("span",null,u))}function zX(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function GX(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function KX(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function S0(f,u){return`${f}/codex-queue-direct${u}`}function Z1(f){return Array.isArray(f?.tasks)?f.tasks:[]}function r6(f){return f?.pagination&&typeof f.pagination==="object"&&!Array.isArray(f.pagination)?f.pagination:{}}function Sz(f){let u=Date.parse(String(f?.updatedAt||f?.createdAt||""));return Number.isFinite(u)?u:0}function Iz(f,u=""){let _=new Map;for(let y of f)for(let $ of y){let l=String($?.id||"");if(l.length>0&&!_.has(l))_.set(l,$)}return Array.from(_.values()).sort((y,$)=>{let l=xz(y)-xz($);if(l!==0)return l;let j=String(y?.id||"")===u?0:1,J=String($?.id||"")===u?0:1;if(j!==J)return j-J;return Sz($)-Sz(y)})}function N4(f,u=""){let _=new Map;for(let y of f)for(let $ of y){let l=String($?.id||"");if(l.length===0)continue;_.set(l,{..._.get(l)||{},...$})}return Iz([Array.from(_.values())],u)}function w4(f){return Array.isArray(f?.activeTaskIds)?f.activeTaskIds.map((u)=>String(u||"")).filter(Boolean):[String(f?.activeTaskId||"")].filter(Boolean)}var v_="__all__",ZX="(max-width: 760px)",qX="(min-width: 761px)",cz="unidesk:codex-queue:read-at:v1";function vu(f){return!f||f===v_}function HX(){return typeof window<"u"&&window.matchMedia(ZX).matches}function Vj(f){return vu(f)?"":`&queueId=${encodeURIComponent(f)}`}function L4(f,u){return Number(f?.counts?.[u]||0)}function rz(f,u=""){let _=new Map;for(let $ of Array.isArray(f?.queues)?f.queues:[]){let l=String($?.id||"").trim();if(l.length>0)_.set(l,$)}for(let $ of[String(f?.defaultQueueId||"default"),u].map((l)=>l.trim()).filter(Boolean))if(!_.has($))_.set($,{id:$,total:0,counts:{},activeTaskId:null,runnableTaskId:null,processing:!1});return Array.from(_.values()).sort(($,l)=>{let j=String($?.id||"")===String(f?.defaultQueueId||"default")?0:1,J=String(l?.id||"")===String(f?.defaultQueueId||"default")?0:1;if(j!==J)return j-J;return String($?.id||"").localeCompare(String(l?.id||""))})}function Gj(f){let u=String(f?.id||"default"),_=L4(f,"running")+L4(f,"judging"),y=L4(f,"queued")+L4(f,"retry_wait"),$=Number(f?.total||0),l=[`${u}`,`${$} tasks`];if(_>0)l.push(`${_} running`);if(y>0)l.push(`${y} queued`);return l.join(" · ")}function T4(f,u){if(vu(u))return null;return f.find((_)=>String(_?.id||"")===u)||null}function Pz(f,u,_,y){if(vu(_)){let l=w4(f);return String(f?.activeTaskId||l[0]||y.find((j)=>Rz(j))?.id||"")}let $=T4(u,_);return String($?.activeTaskId||y.find((l)=>Rz(l))?.id||"")}function EX(f,u,_){if(!vu(u)){let y=T4(f,u);return String(y?.runnableTaskId||_.find(($)=>String($?.status||"")==="queued"||String($?.status||"")==="retry_wait")?.id||"")}return String(_.find((y)=>String(y?.status||"")==="queued"||String(y?.status||"")==="retry_wait")?.id||"")}async function VX(f,u,_=v_){let y=Vj(_);try{return await M0(S0(f,`/api/tasks?limit=${zj}&lite=1&devReady=0${y}`))}catch{let l=await Promise.all(["running","judging","retry_wait","queued"].map(async(A)=>{try{return await M0(S0(f,`/api/tasks?status=${encodeURIComponent(A)}&limit=80&lite=1&devReady=0${y}`))}catch{return null}})),j=await M0(S0(f,`/api/tasks?limit=${zj}&lite=1&devReady=0${y}`)).catch(()=>null),J=l.find((A)=>A?.queue)?.queue||j?.queue||u?.queue||u?.body?.queue||{},F=Iz([...l.map((A)=>Z1(A)),Z1(j)],String(J?.activeTaskId||""));if(F.length>0)return{ok:!0,queue:J,tasks:F};return M0(S0(f,`/api/tasks?limit=5&lite=1&devReady=0${y}`))}}async function OX(f,u,_=0,y=v_){return M0(S0(f,`/api/tasks/overview?limit=${zj}&transcriptLimit=3&compact=1&afterSeq=${encodeURIComponent(String(Math.max(0,_)))}&preferId=${encodeURIComponent(u)}${Vj(y)}`))}async function XX(f,u,_,y=QX){return M0(S0(f,`/api/tasks?limit=${encodeURIComponent(String(y))}&lite=1&devReady=0&includeActive=0&beforeId=${encodeURIComponent(_)}${Vj(u)}`))}async function NX(f,u){return M0(S0(f,`/api/tasks/${encodeURIComponent(u)}/trace-summary`))}async function LX(f,u,_,y=null){let $=y===null||y===void 0||String(y).length===0?"":`&attempt=${encodeURIComponent(String(y))}`;return M0(S0(f,`/api/tasks/${encodeURIComponent(u)}/prompt?part=${encodeURIComponent(_)}${$}`))}async function YX(f,u,_=0,y=500,$=null){let l=$===null||$===void 0||String($).length===0?"":`&attempt=${encodeURIComponent(String($))}`;return M0(S0(f,`/api/tasks/${encodeURIComponent(u)}/trace-steps?afterSeq=${encodeURIComponent(String(_))}&limit=${encodeURIComponent(String(y))}${l}`))}async function BX(f,u,_){return M0(S0(f,`/api/tasks/${encodeURIComponent(u)}/trace-step?seq=${encodeURIComponent(String(_))}`))}async function wX(f,u){return M0(S0(f,`/api/tasks/${encodeURIComponent(u)}/read`),{method:"POST",body:{}})}async function DX(f){return M0(S0(f,"/api/tasks/read-all"),{method:"POST",body:{}})}function TX(f){return Array.isArray(f?.output)?f.output:[]}function pz(f){return Array.isArray(f?.attempts)?f.attempts:[]}function Fj(f){return f?.counts&&typeof f.counts==="object"&&!Array.isArray(f.counts)?f.counts:{}}function MX(f){return f.split(/^\s*---+\s*$/gmu).map((u)=>u.trim()).filter(Boolean)}function Cz(f){let u=Number(f);return Number.isFinite(u)?Math.max(1,Math.min(50,Math.floor(u))):1}function D4(f){let u=[];for(let _ of f.split(/[\s,,;;]+/u)){let y=_.trim();if(/^codex_\d+_[A-Za-z0-9_-]+$/u.test(y)&&!u.includes(y))u.push(y)}return u}function SX(f,u){let _=D4(u);if(_.length===0)return f;return[`引用 Codex Queue 任务 ${_.join(" ")}。后端会在入队时只注入这些任务的 initial prompt 和 final response 全文;中间执行过程不注入,如需补充核查可运行:${_.map((y)=>`bun scripts/cli.ts codex task ${y}`).join(";")}`,"","本次任务:",f].join(` -`)}function rX(f){let y=f.trimStart();if(!y.startsWith("# Codex Queue 已解析引用上下文"))return{hasInjection:!1,reference:"",userPrompt:f};let $=f.length-y.length,l=f.lastIndexOf(` +`):[]}function lj(f){let u=String(f.status||"").trim();if(u.length>0)return u;let _=String(f.bodyPreview||"");return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(_)?.[1]||"item/fileChange"}function pO(f){let u=String(f.bodyPreview||"");return/file changes status=([A-Za-z0-9_-]+)/u.exec(u)?.[1]}function kO(f){return/^item\/(?:started|completed): file changes status=/u.test(String(f||"").trim())}function BG(f){if(String(f.kind||"")!=="edited")return!1;let u=String(f.status||""),_=String(f.title||""),y=String(f.bodyPreview||""),l=String(f.commandPreview||"");if(_==="Edited files")return!0;if(/^item\/fileChange\//u.test(u))return!0;if((u==="item/started"||u==="item/completed")&&/file changes status=/u.test(y))return!0;if(/^Success\. Updated the following files:/mu.test(y))return!0;if(/^diff --git /mu.test(y))return!0;return l.length===0&&/^([AMDRCU?]{1,2})\s+\S+/mu.test(y)}function vl(f){return LG(String(f||"").replace(/^[ab]\//u,"").trim())}function Jj(f){let u=/^([AMDRCU?]{1,2})\s+(.+)$/u.exec(f);if(!u)return null;let _=vl(u[2]||"");return _.length>0?{status:u[1]||"M",path:_}:null}function Fj(f){let u=/^\*\*\*\s+(Add|Update|Delete)\s+File:\s+(.+)$/u.exec(f);if(u){let y=u[1]==="Add"?"A":u[1]==="Delete"?"D":"M",l=vl(u[2]||"");return l.length>0?{status:y,path:l}:null}let _=/^\*\*\*\s+Move to:\s+(.+)$/u.exec(f);if(_){let y=vl(_[1]||"");return y.length>0?{status:"R",path:y}:null}return null}function mO(f){let u=[],_=(l,$)=>{let j=vl($);if(j.length===0||j==="/dev/null")return;let J=u.find((F)=>F.path===j);if(J){if(J.status==="M"&&l!=="M")J.status=l;return}u.push({status:l,path:j})},y="";for(let l of YG(f)){let $=Jj(l)||Fj(l);if($!==null){_($.status,$.path),y=$.path;continue}let j=/^diff --git a\/(.+?) b\/(.+)$/u.exec(l);if(j){let G=j[2]||j[1]||"";_("M",G),y=vl(G);continue}let J=/^\+\+\+ b\/(.+)$/u.exec(l);if(J&&J[1]!=="/dev/null"){_("M",J[1]||""),y=vl(J[1]||"");continue}if(/^new file mode /u.exec(l)&&y)_("A",y);if(/^deleted file mode /u.exec(l)&&y)_("D",y);let U=/^rename to (.+)$/u.exec(l);if(U)_("R",U[1]||"")}return u}function iO(f){if(Jj(f)!==null||Fj(f)!==null)return"file";if(/^(diff --git |index |--- |\+\+\+ |\*\*\* Begin Patch|\*\*\* End Patch)/u.test(f))return"meta";if(/^@@ /u.test(f))return"hunk";if(/^\+/u.test(f))return"add";if(/^-/u.test(f))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(f))return"note";return"context"}function gO(f){return YG(f).map((u)=>{let _=Jj(u)||Fj(u);if(_!==null)return{text:u,kind:"file",path:_.path,status:_.status};return{text:u,kind:iO(u)}})}function nO(f){return f.reduce((u,_)=>{if(_.kind==="add")u.added+=1;else if(_.kind==="del")u.removed+=1;return u},{added:0,removed:0})}function qG(f,u){return`${u} ${f} line${f===1?"":"s"}`}function tO(f,u){let _=[];if(f>0)_.push(qG(f,"Added"));if(u>0)_.push(qG(u,"removed"));return _.join(", ")}function sO(f){for(let _=f.length-1;_>=0;_-=1){let y=String(f[_]?.status||"").trim();if(y.length>0)return y}let u=String(f[f.length-1]?.method||"").trim();if(u==="item/fileChange/outputDelta")return"updated";if(u==="item/started")return"started";if(u==="item/completed")return"completed";return u.replace(/^item\//u,"")||"changed"}function oO(f){return`${f} file${f===1?"":"s"}`}function DG(f){let u=f.length>0?f:[],_=ZG(u.map((W)=>String(W.bodyPreview||""))),l=ZG(u.map((W)=>String(W.bodyPreview||"")).filter((W)=>W.trim().length>0&&!kO(W)))||_,$=mO(l||_),j=u.map((W)=>({method:lj(W),status:pO(W),at:W.at})),J=gO(l||_),F=nO(J),A=tO(F.added,F.removed),U=$.length>0?oO($.length):"",G=A.length>0?`${A}${U?` in ${U}`:""}`:$.length>0?U:OG(l||_||"File changes",72);return{status:sO(j),summary:G,files:$,stages:j,lines:J,addedLines:F.added,removedLines:F.removed,rawText:_}}function aO(f){let u=f[0],_=f[f.length-1]||u,y=DG(f);return{...u,seq:Number.isFinite(Number(_?.seq))?Number(_?.seq):Number(u?.seq??0),at:_?.at||u?.at,title:y.files.length>0?`Edited ${y.summary}`:"Edited files",status:y.status,commandPreview:"",commandOmittedLines:void 0,bodyPreview:y.rawText,bodyOmittedLines:f.reduce((l,$)=>l+Number($.bodyOmittedLines||0),0)||void 0,rawSeqs:f.flatMap((l)=>Array.isArray(l?.rawSeqs)?l.rawSeqs:[l?.seq]).filter((l)=>l!==void 0),editObservation:y}}function dO(f){let u=Array.isArray(f)?f:[],_=[],y=[],l=()=>{if(y.length===0)return;_.push(aO(y)),y=[]};for(let $ of u){if(BG($)){if(lj($)==="item/started"&&y.length>0)l();if(y.push($),lj($)==="item/completed")l();continue}l(),_.push($)}return l(),_}function wG(f){let u=[],_=[],y=[],l=(A,U)=>{for(let G of U)if(!A.includes(G))A.push(G)};for(let A of f){let U=String(A?.kind||""),G=[A?.commandPreview,A?.bodyPreview,A?.title].map((W)=>String(W||"")).join(` +`);if(U==="explored")l(u,KG(G));else if(U==="edited")l(_,KG(G));else if(U==="ran"){let W=String(A?.commandPreview||A?.title||"").trim();if(W.length>0&&!y.includes(W))y.push(OG(W,90))}}let $=f.map((A)=>Date.parse(String(A?.at||""))).filter((A)=>Number.isFinite(A)),j=$.length>=2?Math.max(0,Math.max(...$)-Math.min(...$)):0,J=f.reduce((A,U)=>A+(wy(U?.durationMs)??wy(U?.elapsedMs)??0),0),F=j>0?j:J;return{readFiles:u,editedFiles:_,runCommands:y,durationLabel:hO(F)}}function eO(f,u=3){let _=Array.isArray(f)?f:[],y=[],l=[],$=Math.max(0,u),j=new Set;for(let F=_.length-1;F>=0&&$>0;F-=1){let A=_[F];if(!zG(A))continue;j.add(A),$-=1}let J=()=>{if(l.length>=2){let F=XG(l);y.push({seq:Number(l[0]?.seq??0),at:l[0]?.at||l.at(-1)?.at,kind:"toolGroup",title:NG(l),status:`${l.length} calls`,items:l,counts:F,digest:wG(l),rawSeqs:l.flatMap((A)=>Array.isArray(A?.rawSeqs)?A.rawSeqs:[A?.seq]).filter((A)=>A!==void 0)})}else y.push(...l);l=[]};for(let F of _){if(zG(F)&&!j.has(F)){l.push(F);continue}J(),y.push(F)}return J(),y}function TG(f){return(Array.isArray(f)?f:[]).map((u,_)=>({...u,seq:Number.isFinite(Number(u?.seq))?Number(u.seq):_+1,kind:String(u?.kind||"message"),at:u?.at===void 0?void 0:String(u.at),durationMs:wy(u?.durationMs)??void 0,title:u?.title===void 0?void 0:String(u.title),status:u?.status===void 0?void 0:String(u.status)}))}function e7(f){return wy(f?.durationMs)??wy(f?.elapsedMs)??wy(f?.timing?.durationMs)??wy(f?.metadata?.durationMs)??void 0}function fj(f,u){return f?.createdAt||f?.updatedAt||f?.completedAt||u||void 0}function uj(f,u){return f?.id||f?.messageId||u}function $j(f,u){let _=new Set(u.map((y)=>y.toLowerCase()));for(let y of Array.isArray(f?.inputFields)?f.inputFields:[]){let l=String(y?.key||"").toLowerCase();if(_.has(l))return String(y?.value||"")}return""}function fX(f){let u=String(f?.tool||f?.title||"").toLowerCase();if(/read|grep|glob|list|ls|find|search|view|cat|sed|rg/u.test(u))return"explored";if(/edit|write|patch|apply|update|create|delete/u.test(u))return"edited";let _=$j(f,["command","cmd"]);if(/\b(rg|grep|find|ls|cat|sed|tail|head|git status|git diff|ps)\b/u.test(_))return"explored";if(/\b(apply_patch|git apply|cat >|tee .*<<|sed -i|python3? .*write_text)\b/u.test(_))return"edited";return"ran"}function uX(f){let u=[],_=1;for(let y of Array.isArray(f)?f:[]){let l=y?.createdAt||y?.updatedAt||y?.completedAt,$=String(y?.role||"assistant").toLowerCase(),j=Array.isArray(y?.parts)?y.parts:[];for(let J of j){let F=String(J?.type||"").toLowerCase();if(F==="step-start"||F==="step-finish")continue;if(F==="text"||F==="reasoning"){let U=String(J?.textPreview||y?.textPreview||"").trim();if(U.length===0)continue;u.push({seq:_++,at:fj(J,l),kind:"message",title:F==="reasoning"?"Reasoning":$==="user"?"User message":$==="system"?"System message":"Assistant message",status:F==="reasoning"?"reasoning":$,bodyPreview:U,durationMs:e7(J),rawSeqs:[uj(J,_)]});continue}if(F==="tool"){let U=$j(J,["command","cmd"])||$j(J,["filePath","filepath","path"])||String(J?.title||J?.tool||"tool"),G=String(J?.outputPreview&&J.outputPreview!=="--"?J.outputPreview:J?.textPreview||"");u.push({seq:_++,at:fj(J,l),kind:fX(J),title:String(J?.title||J?.tool||"tool"),status:String(J?.status||""),commandPreview:U,bodyPreview:G,durationMs:e7(J),rawSeqs:[uj(J,_)]});continue}let A=String(J?.textPreview||J?.title||F||"").trim();if(A)u.push({seq:_++,at:fj(J,l),kind:"system",title:F||"part",bodyPreview:A,status:String(J?.status||""),durationMs:e7(J),rawSeqs:[uj(J,_)]})}if(j.length===0&&y?.textPreview)u.push({seq:_++,at:l,kind:"message",title:`${$||"assistant"} message`,status:$,bodyPreview:String(y.textPreview),rawSeqs:[y?.messageId||_]})}return u}var rG={source:"opencode",toTrace:uX};function _X(f){return String(f||"unknown").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-")||"unknown"}function EG(f){let u=String(f||"M").toUpperCase();if(u.startsWith("A")||u==="??")return"added";if(u.startsWith("D"))return"deleted";if(u.startsWith("R"))return"renamed";return"modified"}function yX(f){if(f==="item/fileChange/outputDelta")return"delta";return f.replace(/^item\//u,"")}function lX(f,u){if(f.kind==="file"){let l=String(f.status||"M");return Lf("div",{key:`${u}-${f.text}`,className:`codex-edit-diff-line file ${EG(l)}`},Lf("span",{className:`codex-edit-file-status ${EG(l)}`},l),Lf("code",null,f.path||f.text.replace(/^([AMDRCU?]{1,2})\s+/u,"")))}let _=f.kind==="add"||f.kind==="del"?f.text.slice(0,1):f.kind==="hunk"?"@@":f.kind==="note"?"ok":"",y=f.kind==="add"||f.kind==="del"?f.text.slice(1):f.text;return Lf("div",{key:`${u}-${f.text}`,className:`codex-edit-diff-line ${f.kind}`},Lf("span",{className:"codex-edit-diff-sign"},_),Lf("code",null,y||" "))}function $X(f,u){let _=f.lines.length>0?f.lines:f.files.map((l)=>({text:`${l.status} ${l.path}`,kind:"file",path:l.path,status:l.status})),y=Number(f.addedLines||0)+Number(f.removedLines||0)>0;return Lf("div",{className:"codex-edit-observation","data-testid":"codex-edit-observation"},Lf("div",{className:"codex-edit-observation-head"},Lf("span",{className:"codex-edit-window-controls","aria-hidden":"true"},Lf("i",null),Lf("i",null),Lf("i",null)),Lf("strong",null,y?"git diff":"git diff --stat"),Lf("code",null,f.summary||"File changes")),f.stages.length>0?Lf("div",{className:"codex-edit-stage-strip"},f.stages.map((l,$)=>Lf("span",{key:`${l.method}-${$}`,className:`codex-edit-stage ${_X(l.status||l.method)}`},Lf("b",null,yX(l.method)),l.status?Lf("em",null,l.status):null))):null,_.length>0?Lf("div",{className:"codex-edit-diff",role:"list"},_.map(lX)):null,u?Lf("div",{className:"codex-edit-omitted"},`${u} (查看原始JSON获取完整记录)`):null)}function HG(f,u,_){let y=yj(_);return Lf("div",{className:`codex-transcript-stream ${f}`,"data-testid":`codex-trace-${f}`},Lf("span",{className:"codex-transcript-stream-label"},f),Lf("pre",{className:"codex-transcript-body"},u,y?` +${y} (查看原始JSON获取完整记录)`:""))}function MG(f,u=!1){let _=String(f.kind||"message"),y=["ran","explored","edited"].includes(_),l=yj(f.commandOmittedLines),$=yj(f.bodyOmittedLines),j=String(f.commandPreview||(y?f.title||"":"")),J=String(f.stdoutPreview||""),F=String(f.stderrPreview||""),A=J.length>0||F.length>0,U=Boolean(f.foldedReferencePrompt)&&String(f.fullPrompt||"").length>0,G=_==="edited"&&(f.editObservation!==void 0||BG(f))?f.editObservation||DG([f]):null;return Lf("article",{key:`${f.seq}-${_}`,className:`codex-transcript-item ${_} ${u?"nested":""}`},Lf("div",{className:"codex-transcript-main"},Lf("div",{className:"codex-transcript-title"},Lf("span",{className:"codex-output-channel"},_j(_)),y&&G===null?null:Lf("strong",null,G!==null?"File changes":String(f.title||_j(_))),f.status?Lf("code",null,String(G?.status||f.status)):null,Lf("time",null,zf(f.at))),j&&G===null?Lf("pre",{className:"codex-transcript-command"},j,l?` +${l}`:""):null,G!==null?$X(G,$):A?Lf("div",{className:"codex-transcript-streams"},J.length>0?HG("stdout",J,f.stdoutOmittedLines):null,F.length>0?HG("stderr",F,f.stderrOmittedLines):null):f.bodyPreview?Lf("pre",{className:"codex-transcript-body"},String(f.bodyPreview),$?` +${$} (查看原始JSON获取完整记录)`:""):null,U?Lf("details",{className:"codex-initial-prompt-full","data-testid":"codex-initial-prompt-full"},Lf("summary",null,Lf("span",null,"引用注入已折叠,点击查看最终传入 Codex 的完整 prompt"),Lf("code",null,`${f.fullPromptLines||IO(String(f.fullPrompt||""))} lines / ${f.fullPromptChars||String(f.fullPrompt||"").length} chars`)),Lf("pre",{className:"codex-transcript-body codex-transcript-full-prompt","data-testid":"codex-initial-prompt-full-text"},String(f.fullPrompt||""))):null))}function jX(f){let u=Array.isArray(f.items)?f.items:[],_=f.digest&&typeof f.digest==="object"?f.digest:wG(u);return Lf("article",{key:`${f.seq}-toolGroup`,className:"codex-transcript-item toolGroup"},Lf("div",{className:"codex-transcript-main"},Lf("details",{className:"codex-tool-group","data-testid":"codex-tool-group"},Lf("summary",null,Lf("div",{className:"codex-tool-group-head"},Lf("span",{className:"codex-output-channel"},_j("toolGroup")),Lf("strong",null,String(f.title||NG(u))),Lf("code",null,String(f.status||`${u.length} calls`)),Lf("time",null,zf(f.at)))),Lf("div",{className:"codex-tool-group-digest"},Lf("span",null,`read: ${d7(Array.isArray(_.readFiles)?_.readFiles:[])}`),Lf("span",null,`edit: ${d7(Array.isArray(_.editedFiles)?_.editedFiles:[])}`),Lf("span",null,`run: ${d7(Array.isArray(_.runCommands)?_.runCommands:[],2)}`),Lf("span",null,`duration: ${_.durationLabel||"--"}`)),Lf("div",{className:"codex-tool-group-items"},u.map((y)=>MG(y,!0))))))}var JX=16;function VG(f){return f.scrollHeight-f.scrollTop-f.clientHeight<=JX}function E4({items:f,input:u,port:_,autoScroll:y=!1,loading:l=!1,hasDetail:$=!0,emptyText:j="等待 Trace 输出...",loadingText:J="正在加载完整 Trace...",testId:F="trace-output",className:A="codex-transcript",keepRecentToolCalls:U=3,collapseTools:G=!0}){let W=GG(null),K=GG(!0),E=dO(_?bO(_,u):TG(f)),H=G?eO(E,U):E,O=cO(E);vO(()=>{let Z=W.current;if(!y||!Z)return;if(!K.current&&!VG(Z))return;Z.scrollTop=Z.scrollHeight,K.current=!0},[y,E.length,O]);let q={className:A,ref:W,onScroll:(Z)=>{let V=Z.currentTarget;K.current=VG(V)},"data-testid":F};if(l&&!$)return Lf("div",q,Lf("div",{className:"codex-output-empty"},J));return Lf("div",q,H.length===0?Lf("div",{className:"codex-output-empty"},j):H.map((Z)=>String(Z.kind||"")==="toolGroup"?jX(Z):MG(Z)))}var T=T4.default.createElement,{useEffect:P$,useMemo:PG,useRef:Zu}=T4.default,u0=T4.default.useState,FX=120,zj=24,QX=48,AX=1200;function SG(){return typeof document>"u"||document.visibilityState!=="hidden"}function C_(f,u="操作失败"){return Pf(f,u)}function X4(f){let u=Number(f);if(!Number.isFinite(u)||u<0)return"--";let _=Math.floor(u/1000),y=Math.floor(_/3600),l=Math.floor(_%3600/60),$=_%60;if(y>0)return`${y}h ${String(l).padStart(2,"0")}m`;if(l>0)return`${l}m ${String($).padStart(2,"0")}s`;return`${$}s`}function mG(f){if(f===null||f===void 0||f==="")return null;let u=f instanceof Date?f.getTime():new Date(f).getTime();return Number.isFinite(u)?u:null}function UX(f,u=Date.now()){let _=mG(f);if(_===null)return"--";let y=Math.max(0,Math.floor((u-_)/1000));if(y<1)return"刚刚";let l=Math.floor(y/86400),$=Math.floor(y%86400/3600),j=Math.floor(y%3600/60),J=y%60;if(l>0)return`${l}天${$>0?`${$}小时`:""}前`;if($>0)return`${$}小时${j>0?`${j}分钟`:""}前`;if(j>0)return`${j}分钟${J}秒前`;return`${J}秒前`}function WX(...f){let u="",_=-1/0;for(let y of f){let l=String(y||"");if(l.length===0)continue;let $=mG(y);if($!==null&&$>=_)u=l,_=$;else if(u.length===0)u=l}return u}function Qj(f){let u=Number(f);if(!Number.isFinite(u)||u<0)return"--";if(u<1000)return`${Math.round(u)}ms`;return`${(u/1000).toFixed(u<1e4?2:1)}s`}function iG(f,u=180){let _=String(f||"").replace(/\s+/gu," ").trim();return _.length>u?`${_.slice(0,u-1)}…`:_}async function M0(f,u={}){return wf(f,{strictJson:!0,retryInvalidJson:1,invalidJsonPrefix:"Codex Queue 返回了无效 JSON",invalidJsonPreview:!0,responsePreviewLength:AX,...u})}function x_({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return T("span",{className:`status-badge ${_}`},u||f||"unknown")}function Ty({label:f,value:u,hint:_,tone:y}){return T("article",{className:`metric-card ${y||""}`},T("div",{className:"metric-label"},f),T("div",{className:"metric-value"},u),T("div",{className:"metric-hint"},_))}function bl({title:f,eyebrow:u,summary:_,actions:y,children:l,className:$}){return T("section",{className:`panel ${$||""}`},T("div",{className:"panel-head"},T("div",null,u?T("p",{className:"panel-eyebrow"},u):null,T("h2",null,f),_?T("div",{className:"panel-summary"},_):null),y?T("div",{className:"panel-actions"},y):null),T("div",{className:"panel-body"},l))}function CG({title:f,data:u,onOpen:_,testId:y}){return T("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function Il({title:f,text:u}){return T("div",{className:"empty-state"},T("strong",null,f),T("span",null,u))}function GX(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function zX(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function KX(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function P0(f,u){return`${f}/codex-queue-direct${u}`}function Z1(f){return Array.isArray(f?.tasks)?f.tasks:[]}function r$(f){return f?.pagination&&typeof f.pagination==="object"&&!Array.isArray(f.pagination)?f.pagination:{}}function RG(f){let u=Date.parse(String(f?.updatedAt||f?.createdAt||""));return Number.isFinite(u)?u:0}function gG(f,u=""){let _=new Map;for(let y of f)for(let l of y){let $=String(l?.id||"");if($.length>0&&!_.has($))_.set($,l)}return Array.from(_.values()).sort((y,l)=>{let $=cG(y)-cG(l);if($!==0)return $;let j=String(y?.id||"")===u?0:1,J=String(l?.id||"")===u?0:1;if(j!==J)return j-J;return RG(l)-RG(y)})}function H4(f,u=""){let _=new Map;for(let y of f)for(let l of y){let $=String(l?.id||"");if($.length===0)continue;_.set($,{..._.get($)||{},...l})}return gG([Array.from(_.values())],u)}function N4(f){return Array.isArray(f?.activeTaskIds)?f.activeTaskIds.map((u)=>String(u||"")).filter(Boolean):[String(f?.activeTaskId||"")].filter(Boolean)}var R_="__all__",ZX="(max-width: 760px)",qX="(min-width: 761px)";function Yu(f){return!f||f===R_}function EX(){return typeof window<"u"&&window.matchMedia(ZX).matches}function Oj(f){return Yu(f)?"":`&queueId=${encodeURIComponent(f)}`}function V4(f,u){return Number(f?.counts?.[u]||0)}function xG(f,u=""){let _=new Map;for(let l of Array.isArray(f?.queues)?f.queues:[]){let $=String(l?.id||"").trim();if($.length>0)_.set($,l)}for(let l of[String(f?.defaultQueueId||"default"),u].map(($)=>$.trim()).filter(Boolean))if(!_.has(l))_.set(l,{id:l,total:0,counts:{},activeTaskId:null,runnableTaskId:null,processing:!1});return Array.from(_.values()).sort((l,$)=>{let j=String(l?.id||"")===String(f?.defaultQueueId||"default")?0:1,J=String($?.id||"")===String(f?.defaultQueueId||"default")?0:1;if(j!==J)return j-J;return String(l?.id||"").localeCompare(String($?.id||""))})}function Kj(f){let u=String(f?.id||"default"),_=V4(f,"running")+V4(f,"judging"),y=V4(f,"queued")+V4(f,"retry_wait"),l=Number(f?.total||0),$=[`${u}`,`${l} tasks`];if(_>0)$.push(`${_} running`);if(y>0)$.push(`${y} queued`);return $.join(" · ")}function Y4(f,u){if(Yu(u))return null;return f.find((_)=>String(_?.id||"")===u)||null}function vG(f,u,_,y){if(Yu(_)){let $=N4(f);return String(f?.activeTaskId||$[0]||y.find((j)=>IG(j))?.id||"")}let l=Y4(u,_);return String(l?.activeTaskId||y.find(($)=>IG($))?.id||"")}function HX(f,u,_){if(!Yu(u)){let y=Y4(f,u);return String(y?.runnableTaskId||_.find((l)=>String(l?.status||"")==="queued"||String(l?.status||"")==="retry_wait")?.id||"")}return String(_.find((y)=>String(y?.status||"")==="queued"||String(y?.status||"")==="retry_wait")?.id||"")}async function VX(f,u,_=R_){let y=Oj(_);try{return await M0(P0(f,`/api/tasks?limit=${zj}&lite=1&devReady=0${y}`))}catch{let $=await Promise.all(["running","judging","retry_wait","queued"].map(async(A)=>{try{return await M0(P0(f,`/api/tasks?status=${encodeURIComponent(A)}&limit=80&lite=1&devReady=0${y}`))}catch{return null}})),j=await M0(P0(f,`/api/tasks?limit=${zj}&lite=1&devReady=0${y}`)).catch(()=>null),J=$.find((A)=>A?.queue)?.queue||j?.queue||u?.queue||u?.body?.queue||{},F=gG([...$.map((A)=>Z1(A)),Z1(j)],String(J?.activeTaskId||""));if(F.length>0)return{ok:!0,queue:J,tasks:F};return M0(P0(f,`/api/tasks?limit=5&lite=1&devReady=0${y}`))}}async function OX(f,u,_=0,y=R_){return M0(P0(f,`/api/tasks/overview?limit=${zj}&transcriptLimit=3&compact=1&afterSeq=${encodeURIComponent(String(Math.max(0,_)))}&preferId=${encodeURIComponent(u)}${Oj(y)}`))}async function XX(f,u,_,y=QX){return M0(P0(f,`/api/tasks?limit=${encodeURIComponent(String(y))}&lite=1&devReady=0&includeActive=0&beforeId=${encodeURIComponent(_)}${Oj(u)}`))}async function NX(f,u){return M0(P0(f,`/api/tasks/${encodeURIComponent(u)}/trace-summary`))}async function LX(f,u,_,y=null){let l=y===null||y===void 0||String(y).length===0?"":`&attempt=${encodeURIComponent(String(y))}`;return M0(P0(f,`/api/tasks/${encodeURIComponent(u)}/prompt?part=${encodeURIComponent(_)}${l}`))}async function YX(f,u,_=0,y=500,l=null){let $=l===null||l===void 0||String(l).length===0?"":`&attempt=${encodeURIComponent(String(l))}`;return M0(P0(f,`/api/tasks/${encodeURIComponent(u)}/trace-steps?afterSeq=${encodeURIComponent(String(_))}&limit=${encodeURIComponent(String(y))}${$}`))}async function BX(f,u,_){return M0(P0(f,`/api/tasks/${encodeURIComponent(u)}/trace-step?seq=${encodeURIComponent(String(_))}`))}async function DX(f,u){return M0(P0(f,`/api/tasks/${encodeURIComponent(u)}/read`),{method:"POST",body:{}})}async function wX(f){return M0(P0(f,"/api/tasks/read-all"),{method:"POST",body:{}})}function TX(f){return Array.isArray(f?.output)?f.output:[]}function nG(f){return Array.isArray(f?.attempts)?f.attempts:[]}function Aj(f){return f?.counts&&typeof f.counts==="object"&&!Array.isArray(f.counts)?f.counts:{}}function rX(f){return f.split(/^\s*---+\s*$/gmu).map((u)=>u.trim()).filter(Boolean)}function bG(f){let u=Number(f);return Number.isFinite(u)?Math.max(1,Math.min(50,Math.floor(u))):1}function L4(f){let u=[];for(let _ of f.split(/[\s,,;;]+/u)){let y=_.trim();if(/^codex_\d+_[A-Za-z0-9_-]+$/u.test(y)&&!u.includes(y))u.push(y)}return u}function MX(f,u){let _=L4(u);if(_.length===0)return f;return[`引用 Codex Queue 任务 ${_.join(" ")}。后端会在入队时只注入这些任务的 initial prompt 和 final response 全文;中间执行过程不注入,如需补充核查可运行:${_.map((y)=>`bun scripts/cli.ts codex task ${y}`).join(";")}`,"","本次任务:",f].join(` +`)}function PX(f){let y=f.trimStart();if(!y.startsWith("# Codex Queue 已解析引用上下文"))return{hasInjection:!1,reference:"",userPrompt:f};let l=f.length-y.length,$=f.lastIndexOf(` # 本次任务 -`);if(l<$)return{hasInjection:!1,reference:"",userPrompt:f};return{hasInjection:!0,reference:f.slice($,l).trimEnd(),userPrompt:f.slice(l+8).trimStart()}}function PX(f){let u=f.trimStart();if(!/^引用\s+Codex Queue\s+任务\s+codex_\d+_[A-Za-z0-9_-]+/u.test(u))return f;let _=` +`);if($0?f.split(/\r\n|\r|\n/u).length:0}function mz(f){let u=String(f?.displayPrompt||"");if(u.length>0)return u;let _=String(f?.prompt||"");return PX(rX(_).userPrompt)}function Cy(f){return f?._traceSummary&&typeof f._traceSummary==="object"&&!Array.isArray(f._traceSummary)?f._traceSummary:null}function R6(f){return f?._promptDetails&&typeof f._promptDetails==="object"&&!Array.isArray(f._promptDetails)?f._promptDetails:{}}function r4(f){let u=Cy(f)?.prompt;return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function Kj(f){let u=Cy(f)?.execution;return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function kz(f){let u=r4(f),_=String(u.basePrompt||"");return _.length>0?_:mz(f)}function Zj(f){let u=Cy(f);return String(u?.finalResponse||f?.finalResponse||"").trimEnd()}function qj(f){let _=Cy(f)?.lastJudge||f?.lastJudge;return _&&typeof _==="object"&&!Array.isArray(_)?_:null}function b_(f){return f&&typeof f==="object"&&!Array.isArray(f)?f:null}function CX(f){let u=Cy(f)?.attempts;if(Array.isArray(u)&&u.length>0)return u;let _=pz(f);if(_.length>0)return _.map((j,J)=>({...j,index:Number(j?.index||J+1),execution:J===_.length-1?Kj(f):b_(j?.execution)||{},finalResponse:String(j?.finalResponse||j?.finalResponsePreview||(J===_.length-1?Zj(f):"")),judge:b_(j?.judge)||(J===_.length-1?qj(f):null)}));let y=Kj(f),$=Zj(f),l=qj(f);if(Object.keys(y).length===0&&$.length===0&&l===null)return[];return[{index:Number(f?.currentAttempt||1),mode:f?.currentMode||"initial",startedAt:f?.startedAt,finishedAt:f?.finishedAt,terminalStatus:f?.status,execution:y,finalResponse:$,finalResponseChars:$.length,judge:l}]}function RX(f,u){return b_(u?.execution)||Kj(f)}function xX(f,u){let _=String(u?.finalResponse||u?.finalResponsePreview||"");if(Object.prototype.hasOwnProperty.call(u||{},"finalResponse")||Object.prototype.hasOwnProperty.call(u||{},"finalResponsePreview"))return _.trimEnd();return _.length>0?_.trimEnd():Zj(f)}function iz(f,u){if(Object.prototype.hasOwnProperty.call(u||{},"judge"))return b_(u?.judge);return qj(f)}function gz(f){return`feedback:${String(f||"latest")}`}function vX(f,u,_){let y=String(u?.feedbackPrompt||"").trimEnd(),$=String(u?.feedbackPromptPreview||y||"").trimEnd(),l=Number(u?.feedbackPromptChars||y.length||$.length||0),j=Number(u?.feedbackPromptLines||q1(y||$));if(y.length>0||$.length>0||l>0)return{text:y,preview:$,chars:l,lines:j,source:u?.feedbackPromptSource||"judge-feedback",forAttempt:u?.feedbackPromptForAttempt||Number(_||0)+1,truncated:Boolean(u?.feedbackPromptTruncated)};let J=iz(f,u),F=String(J?.continuePrompt||"").trimEnd();if(J?.decision==="retry"&&F.length>0)return{text:"",preview:F,chars:F.length,lines:q1(F),source:"judge-continue-prompt",forAttempt:Number(_||0)+1,truncated:!1};return null}function nz(f){let u=r4(f);return Boolean(u.hasReferenceInjection||Number(u.referencePromptChars||0)>0||f?.referenceInjection||f?.referenceInjectionSummary)}function bX(f,u=null){if(u!==null&&u!==void 0){let y=(b_(f?._traceStepsByAttempt)||{})[String(u)];return Array.isArray(y)?y:[]}return Array.isArray(f?._traceSteps)?f._traceSteps:[]}function tz(f,u=null){if(u!==null&&u!==void 0){let _=b_(f?._traceStepsLoadedByAttempt)||{};return Boolean(_[String(u)])}return Boolean(f?._traceStepsLoaded)}function Hj(f){return f?._traceStepDetails&&typeof f._traceStepDetails==="object"&&!Array.isArray(f._traceStepDetails)?f._traceStepDetails:{}}function hX(f){let u=f?.timing&&typeof f.timing==="object"?f.timing:{},_=String(f?.status||"");if(["queued"].includes(_))return`等待 ${B4(u.queueWaitMs??u.totalElapsedMs)}`;if(["running","judging","retry_wait"].includes(_))return`耗时 ${B4(u.durationMs??u.totalElapsedMs)}`;return`耗时 ${B4(u.durationMs??u.totalElapsedMs)}`}function M4(f){return String(f?.queueId||"default")}function IX(f){return{system:"SYS",user:"YOU",assistant:"GPT",reasoning:"THINK",command:"CMD",diff:"DIFF",tool:"TOOL",error:"ERR"}[f]||f.toUpperCase()}function Rz(f){return["running","judging","retry_wait"].includes(String(f?.status||""))}function P1(f){return["succeeded","failed","canceled"].includes(String(f?.status||""))}function c3(f){if(!P1(f))return!1;if(f?.terminalUnread===!0)return!0;if(f?.terminalUnread===!1)return!1;return!f?.readAt}function cX(){if(typeof window>"u")return{};try{let f=JSON.parse(window.localStorage.getItem(cz)||"{}");return f&&typeof f==="object"&&!Array.isArray(f)?sz(f):{}}catch{return{}}}function sz(f){let u=Object.entries(f||{}).filter(([,_])=>typeof _==="string"&&_.length>0).sort((_,y)=>{let $=Date.parse(String(_[1]||"")),l=Date.parse(String(y[1]||""));return(Number.isFinite(l)?l:0)-(Number.isFinite($)?$:0)}).slice(0,AX);return Object.fromEntries(u)}function pX(f){let u=sz(f);if(typeof window>"u")return u;try{window.localStorage.setItem(cz,JSON.stringify(u))}catch{}return u}function Qj(f,u){let _=String(f?.id||""),y=String(u?.[_]||"");if(!P1(f)||y.length===0)return f;return{...f,readAt:f?.readAt||y,terminalUnread:!1}}function x6(f){let u=Number(f||0);return Number.isFinite(u)?u:0}function mX(f){return x6(f.queued)+x6(f.retry_wait)}function kX(f){return x6(f.running)+x6(f.judging)}function xz(f){if(c3(f))return 0;return{running:1,judging:2,retry_wait:3,queued:4,succeeded:8,failed:8,canceled:8}[String(f?.status||"")]??9}function P6(f){if(!f)return!1;if(f?._traceSummaryLoaded===!0)return!1;return f?.summaryOnly===!0||f?._metaLoaded!==!0}function iX(f){return Boolean(f?._metaLoaded)||f?.summaryOnly===!1}function gX(f,u,_){let y=String(f?.[_]||""),$=String(u?.[_]||"");return y.length>$.length?y:$}function Ej(f,u,_){let y=Array.isArray(f?.[_])?f[_]:[],$=Array.isArray(u?.[_])?u[_]:[];if($.length===0&&y.length>0)return y;return y.length>$.length?y:$}function nX(f,u){let _=u?.summaryOnly===!0&&iX(f),y={...f,...u};if(!_)return y;for(let $ of["prompt","basePrompt","displayPrompt","finalResponse"])y[$]=gX(f,u,$);for(let $ of["promptHistory","attempts","output","events"])y[$]=Ej(f,u,$);if(f?.referenceInjection?.items&&!u?.referenceInjection?.items)y.referenceInjection=f.referenceInjection;if(f?.referenceInjectionSummary&&!u?.referenceInjectionSummary)y.referenceInjectionSummary=f.referenceInjectionSummary;y.summaryOnly=f?.summaryOnly===!1?!1:u.summaryOnly,y._metaLoaded=f?._metaLoaded,y._detailLoaded=f?._detailLoaded,y._transcriptComplete=f?._transcriptComplete,y._transcriptPreview=Object.prototype.hasOwnProperty.call(u,"_transcriptPreview")?u._transcriptPreview:f?._transcriptPreview;for(let $ of["_traceSummary","_traceSummaryLoaded","_traceSteps","_traceStepsLoaded","_traceStepsByAttempt","_traceStepsLoadedByAttempt","_traceStepDetails","_promptDetails"])if(!Object.prototype.hasOwnProperty.call(u,$)&&Object.prototype.hasOwnProperty.call(f||{},$))y[$]=f[$];return y}function tX(f){let u=f?.selected,_=u?.task&&typeof u.task==="object"?u.task:null;if(_!==null){let $=Boolean(u?.preview);return{..._,transcript:Array.isArray(u?.transcript)?u.transcript:[],_detailLoaded:Array.isArray(u?.transcript)&&u.transcript.length>0,_transcriptComplete:Boolean(!$&&!u?.hasMore&&P1(_)),_transcriptPreview:$,_summaryLoaded:!0}}let y=Z1(f)[0];return y?{...y,_summaryLoaded:!0}:null}function Aj(f,u){let _=new Map;for(let y of[...Array.isArray(f)?f:[],...Array.isArray(u)?u:[]]){let $=`${Number(y?.seq??0)}:${String(y?.kind||"message")}`,l=_.get($);if(!l){_.set($,y);continue}let j={...l,...y};for(let[J,F]of[["bodyPreview","bodyOmittedLines"],["commandPreview","commandOmittedLines"]]){let A=String(l?.[J]||""),U=String(y?.[J]||"");if(A.length>U.length)j[J]=l[J],j[F]=l[F]}_.set($,j)}return Array.from(_.values()).sort((y,$)=>Number(y?.seq??0)-Number($?.seq??0))}function Y4(f){return(Array.isArray(f)?f:[]).reduce((u,_)=>Math.max(u,Number(_?.seq??0)),0)}function vz(f,u=8){let _=Array.from(new Set((Array.isArray(f)?f:[]).map(($)=>Number($?.seq??0)).filter(($)=>Number.isFinite($)&&$>0))).sort(($,l)=>$-l);if(_.length===0)return 0;let y=_[Math.max(0,_.length-u)]??0;return Math.max(0,y-0.001)}function Uj(f,u){let _=Number(f[u]??0);return Number.isFinite(_)?String(_):"0"}function sX(f,u){let _=Array.isArray(f?.codexModels)?f.codexModels:[],y=["gpt-5.5","gpt-5.4-mini","gpt-5.4"];return Array.from(new Set([..._,...y,u].map(($)=>String($||"").trim()).filter(Boolean)))}function oX({task:f,selected:u,onSelect:_,onCopy:y,onReference:$,onMarkRead:l,copied:j,markingRead:J}){let F=f?.lastJudge||{},A=String(f?.id||""),U=c3(f);return B("article",{role:"button",tabIndex:0,className:`codex-task-card ${u?"selected":""} ${U?"unread-terminal":""}`,onClick:_,onKeyDown:(z)=>{if(z.key==="Enter"||z.key===" ")z.preventDefault(),_()},"data-unread-terminal":U?"true":"false","data-testid":`codex-task-${f?.id||"unknown"}`},U?B("span",{className:"codex-unread-badge",title:"待读","aria-label":"待读","data-testid":`codex-unread-task-${A||"unknown"}`}):null,B("div",{className:"codex-task-card-head"},B("div",{className:"codex-task-status-line"},B(y_,{status:f?.status},f?.status||"unknown")),B("span",{className:"mono-text"},`${f?.currentAttempt||0}/${f?.maxAttempts||0}`)),B("div",{className:"codex-task-id-row"},B("code",{title:A},A||"unknown"),B("div",{className:"codex-task-id-actions"},B("button",{type:"button",className:"codex-copy-id-btn",onClick:(z)=>{z.stopPropagation(),$(A)},"data-testid":`codex-reference-task-${A||"unknown"}`},"引用"),B("button",{type:"button",className:"codex-copy-id-btn",onClick:(z)=>{z.stopPropagation(),y(A)},"data-testid":`codex-copy-task-id-${A||"unknown"}`},j?"已复制":"复制ID"),U?B("button",{type:"button",className:"codex-copy-id-btn codex-mark-read-btn",disabled:Boolean(J),onClick:(z)=>{z.stopPropagation(),l(A)},"data-testid":`codex-mark-task-read-${A||"unknown"}`},J?"标记中":"标为已读"):null)),B("strong",null,hz(mz(f),120)||"空任务"),B("div",{className:"codex-task-meta"},B("span",null,`queue=${M4(f)}`),B("span",null,f?.model||"--"),B("span",null,hX(f))),B("div",{className:"codex-task-meta"},B("span",null,Py(f?.updatedAt))),F?.decision?B("div",{className:"codex-judge-line"},`judge=${F.decision} ${Math.round(Number(F.confidence||0)*100)}%`):null)}function Wj({title:f,tasks:u,selectedId:_,onSelect:y,onCopy:$,onReference:l,onMarkRead:j,copiedTaskId:J,markingReadTaskId:F,emptyText:A}){let U=Array.isArray(u)?u:[];return B("section",{className:"codex-task-section"},B("div",{className:"codex-task-section-head"},B("span",null,f),B("code",null,String(U.length))),U.length===0?B("p",{className:"codex-task-section-empty"},A):B("div",{className:"codex-task-section-list"},U.map((z)=>B(oX,{key:z.id,task:z,selected:_===z.id,onSelect:()=>y(z.id),onCopy:$,onReference:l,onMarkRead:j,copied:J===z.id,markingRead:F===z.id}))))}function aX({task:f,queueRows:u,busy:_,onMove:y}){let $=String(f?.id||""),l=M4(f),[j,J]=df(l);C6(()=>{J(l)},[$,l]);let F=!$||_||["running","judging","retry_wait"].includes(String(f?.status||""));return B("div",{className:"codex-task-move-control","data-testid":"codex-task-queue-move-control"},B("label",null,"任务 queue",B("select",{value:j,disabled:!$||_,onChange:(A)=>J(String(A.target.value||l)),"data-testid":"codex-task-queue-move-select"},u.map((A)=>B("option",{key:String(A?.id||""),value:String(A?.id||"")},Gj(A))))),B("button",{type:"button",className:"ghost-btn",disabled:F||j===l,onClick:()=>y(j),title:F?"运行中 / judging / retry_wait 的任务不能移动;请先打断或等当前 turn 结束":"移动已创建任务到另一个 queue","data-testid":"codex-task-queue-move-button"},"移动"))}function bz(f,u=4){let _=(Array.isArray(f)?f:[]).map(($)=>String($||"").trim()).filter(Boolean);if(_.length===0)return"--";let y=_.slice(0,u).join(" / ");return _.length>u?`${y} +${_.length-u}`:y}function dX({task:f,loading:u,onLoadPromptPart:_,testId:y="codex-initial-prompt-full",textTestId:$="codex-initial-prompt-full-text",baseTextTestId:l="codex-initial-prompt-base"}){let j=r4(f),J=R6(f),F=kz(f).trimEnd(),A=String(J.full?.text||""),U=nz(f),z=Number(j.promptChars||f?.promptChars||A.length),W=Number(j.basePromptLines||q1(F)),K=Number(j.promptLines||q1(A));return B("section",{className:"codex-progressive-card codex-progressive-prompt","data-testid":"codex-progressive-prompt"},B("div",{className:"codex-progressive-card-head"},B("span",{className:"codex-output-channel"},"Prompt"),B("strong",null,"Submitted prompt / 原始用户 prompt"),B("code",null,`${W||q1(F)} lines / ${F.length} chars`)),B("pre",{className:"codex-prompt-full","data-testid":l},F||"空 prompt"),U?B("details",{className:"codex-reference-injection codex-progressive-full-prompt","data-testid":y,onToggle:(q)=>{if(q.currentTarget?.open&&!A)_?.("full")}},B("summary",null,B("span",null,"引用注入已折叠,点击按需拉取最终进入 opencode 的完整 prompt"),B("code",null,A?`${K||q1(A)} lines / ${A.length} chars`:`${Number.isFinite(z)&&z>0?z:"--"} chars`)),B("pre",{className:"codex-prompt-full codex-prompt-final-full","data-testid":$},A||(u?"正在按需拉取完整 prompt...":"展开后将只请求 full prompt,不拉取完整 transcript。"))):null)}function oz({task:f,attempt:u,attemptIndex:_,loading:y,onLoadSteps:$,onLoadStep:l,testId:j="codex-execution-summary"}){let J=RX(f,u),F=bX(f,_),A=Hj(f),U=tz(f,_),z=Number(J.toolCallCount||0),W=Array.isArray(J.editedFiles)?J.editedFiles:[],K=Array.isArray(J.commands)?J.commands:[],q=_?` #${_}`:"";return B("details",{className:"codex-progressive-card codex-execution-summary","data-testid":j,"data-attempt-index":_?String(_):void 0,onToggle:(E)=>{if(E.currentTarget?.open&&!U)$?.(_)}},B("summary",null,B("div",{className:"codex-progressive-card-head"},B("span",{className:"codex-output-channel"},"Summary"),B("strong",null,`执行过程摘要${q}`),B("code",null,`${B4(J.durationMs??J.totalElapsedMs)} / ${z} tools`)),B("div",{className:"codex-execution-digest"},B("span",null,`read ${Number(J.readCount||0)}`),B("span",null,`edit ${Number(J.editCount||0)}`),B("span",null,`run ${Number(J.runCount||0)}`),B("span",null,`${Number(J.stepCount||F.length||0)} steps`))),B("div",{className:"codex-execution-digest expanded"},B("span",null,`修改文件:${bz(W,6)}`),B("span",null,`执行命令:${bz(K,4)}`)),F.length===0?B("div",{className:"codex-output-empty"},y?"正在按需拉取步骤 summary...":"展开后将只请求执行步骤 summary,不拉取单步骤全量。"):B("div",{className:"codex-trace-step-list"},F.map((E)=>{let O=String(E?.seq??""),G=A[O],H=Array.isArray(E?.summaryLines)?E.summaryLines.slice(0,4):[];return B("details",{key:O||`${E?.title}-${E?.at}`,className:`codex-trace-step ${String(E?.kind||"message")}`,"data-testid":`codex-trace-step-${O||"unknown"}`,onToggle:(Z)=>{if(Z.currentTarget?.open&&!G)l?.(E?.seq)}},B("summary",null,B("span",{className:"codex-output-channel"},eX(E?.kind)),B("strong",null,String(E?.title||"Trace step")),E?.status?B("code",null,String(E.status)):null,B("time",null,Py(E?.at))),B("div",{className:"codex-trace-step-summary"},H.length>0?H.map((Z,V)=>B("pre",{key:`${O}-${V}`},String(Z||""))):B("span",null,"无 summary")),G?.line?B(X4,{items:[G.line],autoScroll:!1,loading:!1,hasDetail:!0,emptyText:"无步骤详情",testId:`codex-trace-step-detail-${O||"unknown"}`,className:"codex-transcript codex-step-detail-transcript",collapseTools:!1}):B("div",{className:"codex-output-empty"},y?"正在按需拉取这个步骤的全量数据...":"展开后将只请求这个单步骤的全量数据。"))})))}function eX(f){let u=String(f||"");if(u==="ran")return"Ran";if(u==="explored")return"Explored";if(u==="edited")return"Edited";if(u==="error")return"Error";if(u==="system")return"System";return"Message"}function az({task:f,attempt:u,attemptIndex:_,testId:y="codex-final-response"}){let $=xX(f,u),l=Number(u?.finalResponseChars||$.length),j=_?` #${_}`:"";return B("section",{className:"codex-progressive-card codex-final-response","data-testid":y,"data-attempt-index":_?String(_):void 0},B("div",{className:"codex-progressive-card-head"},B("span",{className:"codex-output-channel"},"Final"),B("strong",null,`最终 response${j}`),B("code",null,`${Number.isFinite(l)?l:$.length} chars`)),B("pre",{className:"codex-transcript-body"},$||"暂无最终 response"))}function dz({task:f,attempt:u,attemptIndex:_,testId:y="codex-progressive-judge"}){let $=iz(f,u),l=_?` #${_}`:"";return B("section",{className:"codex-progressive-card codex-progressive-judge","data-testid":y,"data-attempt-index":_?String(_):void 0},B("div",{className:"codex-progressive-card-head"},B("span",{className:"codex-output-channel"},"Judge"),B("strong",null,`完成判定${l}`),$?.decision?B("code",null,`${$.decision} ${Math.round(Number($.confidence||0)*100)}%`):null),$?B("div",{className:"codex-judge-card","data-testid":`${y}-card`},B(y_,{status:$.decision},$.decision),B("strong",null,`${Math.round(Number($.confidence||0)*100)}% confidence`),B("p",{"data-testid":`${y}-reason`},$.reason||"--"),$.continuePrompt?B("pre",{"data-testid":`${y}-continue-prompt`},String($.continuePrompt||"")):null):B("div",{className:"codex-output-empty"},"尚未判定"))}function fN({task:f,attempt:u,attemptIndex:_,loading:y,onLoadPromptPart:$,testId:l="codex-judge-feedback-prompt"}){let j=vX(f,u,_);if(j===null)return null;let J=gz(_),A=R6(f)[J],U=String(A?.text||"").trimEnd(),z=String(j.preview||j.text||"").trimEnd(),W=U||String(j.text||"").trimEnd(),K=Number(A?.chars||j.chars||W.length||z.length),q=Number(A?.lines||j.lines||q1(W||z)),E=A?.forAttempt||j.forAttempt||Number(_||0)+1;return B("details",{className:"codex-progressive-card codex-judge-feedback-prompt","data-testid":l,"data-attempt-index":_?String(_):void 0,onToggle:(O)=>{if(O.currentTarget?.open&&!U)$?.("feedback",_)}},B("summary",null,B("div",{className:"codex-progressive-card-head"},B("span",{className:"codex-output-channel"},"Prompt"),B("strong",null,`judge feedback prompt #${_} -> #${E}`),B("code",null,`${q||"--"} lines / ${Number.isFinite(K)?K:z.length} chars`)),B("p",{className:"codex-feedback-preview","data-testid":`${l}-preview`},z||"展开后按需拉取 judge feedback prompt。")),B("pre",{className:"codex-prompt-full codex-feedback-full","data-testid":`${l}-text`},W||(y?"正在按需拉取 judge feedback prompt...":"展开后将只请求这一次 judge feedback prompt。")))}function uN({task:f,attempt:u,position:_,loading:y,onLoadPromptPart:$,onLoadSteps:l,onLoadStep:j}){let J=Number(u?.index||_+1),F=_===0;return B("section",{className:"codex-attempt-cycle","data-testid":`codex-attempt-cycle-${J}`},B("div",{className:"codex-attempt-cycle-head"},B("span",{className:"codex-output-channel"},`Attempt ${J}`),B("strong",null,String(u?.mode||(J<=1?"initial":"retry"))),u?.terminalStatus?B(y_,{status:u.terminalStatus},u.terminalStatus):null,B("code",null,`${Py(u?.startedAt)} -> ${Py(u?.finishedAt)}`)),B(oz,{task:f,attempt:u,attemptIndex:J,loading:y,onLoadSteps:l,onLoadStep:j,testId:F?"codex-execution-summary":`codex-execution-summary-attempt-${J}`}),B(az,{task:f,attempt:u,attemptIndex:J,testId:F?"codex-final-response":`codex-final-response-attempt-${J}`}),B(dz,{task:f,attempt:u,attemptIndex:J,testId:F?"codex-progressive-judge":`codex-progressive-judge-attempt-${J}`}),B(fN,{task:f,attempt:u,attemptIndex:J,loading:y,onLoadPromptPart:$,testId:F?"codex-judge-feedback-prompt":`codex-judge-feedback-prompt-attempt-${J}`}))}function _N({task:f,loading:u,onLoadPromptPart:_,onLoadSteps:y,onLoadStep:$}){if(!f)return B(ry,{title:"未选择任务",text:"从左侧队列选择任务,或提交新 Codex 任务。"});let l=CX(f);return B("div",{className:"codex-transcript codex-progressive-trace","data-testid":"codex-output"},u&&!Cy(f)?B("div",{className:"codex-output-empty"},"正在加载 Trace Summary..."):null,B(dX,{task:f,loading:u,onLoadPromptPart:_}),l.length>0?l.map((j,J)=>B(uN,{key:`${j?.index||J+1}-${j?.startedAt||J}`,task:f,attempt:j,position:J,loading:u,onLoadPromptPart:_,onLoadSteps:y,onLoadStep:$})):[B(oz,{key:"execution",task:f,loading:u,onLoadSteps:y,onLoadStep:$}),B(az,{key:"final",task:f}),B(dz,{key:"judge",task:f})])}function yN({task:f,loading:u,onLoadPromptPart:_}){if(!f)return B(ry,{title:"未选择任务",text:"选择队列或历史 session 后,这里显示完整 prompt、模型和工作目录。"});let y=r4(f),$=R6(f),l=kz(f).trimEnd(),j=String($.full?.text||""),J=nz(f),F=Number(y.basePromptLines||q1(l)),A=Number(y.promptLines||q1(j)),U=Number(y.referencePromptLines||0),z=Number(y.promptChars||f?.promptChars||j.length);return B("div",{className:"codex-prompt-detail","data-testid":"codex-task-prompt-detail"},B("div",{className:"codex-prompt-meta"},B(y_,{status:f?.status},f?.status||"unknown"),B("span",null,`model=${f?.model||"--"}`),B("span",null,`cwd=${f?.cwd||"--"}`),B("span",null,`created=${Py(f?.createdAt)}`),B("span",null,J?`task ${F} lines / total ${Number.isFinite(A)&&A>0?A:"--"} lines`:`${F} lines / ${l.length} chars`)),B("div",{className:"codex-lazy-detail-callout","data-testid":"codex-task-summary-callout"},B("div",null,B("strong",null,"渐进式 Trace"),B("span",null,"首屏使用后端 Summary;展开 prompt / 步骤时只按需拉取对应片段,不一次性拉取完整 transcript。"))),J?B("details",{className:"codex-reference-injection codex-final-prompt-injection","data-testid":"codex-final-prompt-full",onToggle:(W)=>{if(W.currentTarget?.open&&!j)_?.("full")}},B("summary",null,B("span",null,"最终传入 Codex 的真实完整 prompt"),B("code",null,j?`${A||q1(j)} lines / ${j.length} chars`:`${Number.isFinite(z)&&z>0?z:"--"} chars`)),B("pre",{className:"codex-prompt-full codex-prompt-final-full","data-testid":"codex-task-final-prompt-full"},j||(u?"正在按需拉取完整 prompt...":"展开后将只请求完整 prompt。"))):null,J?B("details",{className:"codex-reference-injection","data-testid":"codex-reference-injection",onToggle:(W)=>{if(W.currentTarget?.open&&!$.reference?.text)_?.("reference")}},B("summary",null,B("span",null,"引用注入已折叠"),B("code",null,$.reference?.text?`${q1(String($.reference.text||""))} lines / ${String($.reference.text||"").length} chars`:`${U||"--"} lines`)),B("pre",{className:"codex-prompt-full codex-prompt-reference-full","data-testid":"codex-task-reference-full"},String($.reference?.text||"")||(u?"正在按需拉取引用注入...":"展开后将只请求引用注入片段。"))):null,B("pre",{className:"codex-prompt-full","data-testid":"codex-task-prompt-full"},l||"空 prompt"))}function $N({task:f}){let u=TX(f);if(!f||u.length===0)return B(ry,{title:"暂无原始消息",text:"原始 Codex app-server 消息会保留在任务 JSON 中。"});return B("details",{className:"codex-raw-output"},B("summary",null,`原始 messages (${u.length})`),B("div",null,u.map((_)=>B("article",{key:`${_.seq}-${_.channel}`,className:`codex-output-line ${_.channel||"system"}`},B("div",{className:"codex-output-meta"},B("span",{className:"codex-output-channel"},IX(String(_.channel||"system"))),B("span",null,Py(_.at)),_.method?B("code",null,_.method):null),B("pre",null,String(_.text||""))))))}function lN({task:f}){let u=pz(f).slice().reverse();if(u.length===0)return B(ry,{title:"尚无 attempt",text:"任务开始运行后,这里会记录 Codex 终态、传输中断和 stderr tail。"});return B("div",{className:"table-wrap codex-attempt-table"},B("table",null,B("thead",null,B("tr",null,B("th",null,"#"),B("th",null,"模式"),B("th",null,"终态"),B("th",null,"传输"),B("th",null,"退出"),B("th",null,"完成时间"))),B("tbody",null,u.map((_)=>B("tr",{key:`${_.index}-${_.startedAt}`},B("td",null,_.index),B("td",null,_.mode),B("td",null,B(y_,{status:_.terminalStatus||"unknown"},_.terminalStatus||"unknown")),B("td",null,_.transportClosedBeforeTerminal?B(y_,{status:"failed"},"closed-before-terminal"):B(y_,{status:"succeeded"},"normal")),B("td",null,`code=${_.appServerExitCode??"--"} signal=${_.appServerSignal??"--"}`),B("td",null,Py(_.finishedAt)))))))}function ez({microservices:f,onRaw:u,apiBaseUrl:_="/api",initialTasksData:y=null,standalone:$=!1}){let l=f.find((k)=>k.id==="codex-queue")||null,j=tX(y),J=String(j?.id||""),F=new Map;if(j!==null&&J.length>0)F.set(J,{task:j,maxSeq:Y4(Array.isArray(j.transcript)?j.transcript:[]),complete:Boolean(j._transcriptComplete),completeUpdatedAt:j._transcriptComplete?String(j.updatedAt||""):""});let A=typeof performance>"u"?0:performance.now(),U=Zu(J),z=Zu(0),W=Zu(0),K=Zu(!1),q=Zu(!1),E=Zu(null),O=Zu(new Map),G=Zu(new Map),H=Zu(new Map),Z=Zu(new Map),V=Zu(new Set),L=Zu(!1),M=Zu(Boolean(y)),N=Zu(F),D=Zu(y),[x,c]=df(null),[v,C]=df(y),[P,w]=df(J),[r,S]=df(j),[T,Y]=df(!1),[R,m]=df(""),[p,n]=df(""),[_f,t]=df("default"),[ff,Gf]=df(v_),[zf,jf]=df("gpt-5.5"),[Wf,Vf]=df("/root/unidesk"),[Zf,h]=df(99),[g,I]=df(1),[$f,lf]=df(!1),[Af,Yf]=df(!1),[xf,sf]=df(""),[j0,u0]=df(!0),[D0,Fu]=df(()=>typeof window>"u"?!0:window.matchMedia(qX).matches),[O0,x0]=df(!1),[ku,X0]=df(""),[Qu,uf]=df(""),[vf,a0]=df(""),[Bf,v0]=df(""),[i0,d0]=df(!1),[b0,m1]=df(cX),[ef,iu]=df(y?{phase:"complete",taskId:J,queueMs:0,detailMs:0,totalMs:A,chunks:j?1:0,transcriptRows:Array.isArray(j?.transcript)?j.transcript.length:0,partial:Boolean(y?.selected?.hasMore||P6(j)),completedAt:new Date}:null),[f3,u3]=df(y?new Date:null),[s,Of]=df(!1),qf=Z1(v).map((k)=>Qj(k,b0)),Cf=qf.filter(c3),_0=qf.filter((k)=>!P1(k)),G0=qf.filter((k)=>P1(k)&&!c3(k)),If=v?.queue||x?.body?.queue||x?.queue||{},h0=r6(v),Au=rz(If,_f),xl=T4(Au,ff),L1=Number((vu(ff)?If?.total:xl?.total)??h0.total??qf.length),vl=h0.hasMore===!0&&String(h0.nextBeforeId||"").length>0,_3=w4(If),y3=vu(ff)?_3:[String(T4(Au,ff)?.activeTaskId||"")].filter(Boolean),ly=Pz(If,Au,ff,qf),W_=vu(ff)?Fj(If):Fj(xl||{}),bl=Fj(If),Z2=mX(bl),hl=Math.max(kX(bl),_3.length),k1=x6(If?.unreadTerminal??Cf.length),jy=vu(ff)?"All queues":ff,Il=l?zX(l):{},q2=l?KX(l):{},V$=l?GX(l):{},O$=Dz(()=>MX(R),[R]),j1=Dz(()=>{let k=Cz(g);return O$.flatMap((a)=>Array.from({length:k},()=>SX(a,p)))},[O$,g,p]),Jy=j1.length,X$=Jy>1&&!$f,H2=Af||O0||Jy===0||X$,cl=sX(If,zf),N$=r?.id&&r?.activeTurnId&&String(r?.status)==="running",E2=r?.id&&!["succeeded","failed","canceled"].includes(String(r?.status||"")),V2=r?.id&&["succeeded","failed","canceled"].includes(String(r?.status||""));function i1(k){let a=typeof k==="function"?k(D.current):k;return D.current=a,C(a),a}function pl(k,a,Qf=null,Kf=null){let Df=new Set(k.map((Xf)=>String(Xf||"")).filter(Boolean));if(Df.size===0&&Kf===null&&Qf===null)return;i1((Xf)=>{if(!Xf)return Xf;let Sf=Z1(Xf).map((Rf)=>{let cf=String(Rf?.id||"");if(!Df.has(cf))return Rf;let nf=Kf&&String(Kf?.id||"")===cf?Kf:{};return{...Rf,...nf,readAt:a,terminalUnread:!1}});return{...Xf,queue:Qf||Xf.queue,tasks:Df.size>0?N4([Sf],ly):Sf}});for(let Xf of Df){let Sf=N.current.get(Xf);if(Sf?.task){let Rf=Kf&&String(Kf?.id||"")===Xf?Kf:{},cf={...Sf.task,...Rf,readAt:a,terminalUnread:!1};if(N.current.set(Xf,{...Sf,task:cf}),U.current===Xf)S(cf)}}}function L$(k,a){let Qf=k.map((Kf)=>String(Kf||"")).filter(Boolean);if(Qf.length===0)return;m1((Kf)=>{let Df={...Kf||{}};for(let Xf of Qf)Df[Xf]=a;return pX(Df)})}C6(()=>{lf(!1)},[R,g,p]);function Y1(k,a,Qf){let Kf=N.current.get(k)||{},Df=Kf.task||{},Xf=Array.isArray(Df.transcript)?Df.transcript:[],Sf=nX(Df,a),Rf=Object.prototype.hasOwnProperty.call(a,"transcript")?Aj(Xf,Array.isArray(a.transcript)?a.transcript:[]):Xf,cf={...Df,...Sf,transcript:Rf,output:Array.isArray(Sf.output)?Ej(Df,Sf,"output"):Array.isArray(Df.output)?Df.output:[],events:Array.isArray(Sf.events)?Ej(Df,Sf,"events"):Array.isArray(Df.events)?Df.events:[]},nf=String(cf?.updatedAt||""),of=Boolean(a._transcriptComplete)&&P1(cf),J0=Boolean(Kf.complete)&&P1(cf)&&String(Kf.completeUpdatedAt||"")===nf,e0=of||J0,J1={...Kf,task:cf,maxSeq:Y4(Rf),complete:e0,completeUpdatedAt:e0?nf:""};if(N.current.set(k,J1),Qf===W.current&&U.current===k)S(cf);return J1}async function Y$(k,a=!1,Qf,Kf){if(!l||!k)return;let Xf=N.current.get(k)?.task,Sf=String(Xf?._traceSummaryUpdatedAt||""),Rf=String(Xf?.updatedAt||"");if(!a&&Xf?._traceSummaryLoaded===!0&&Sf===Rf)return;let cf=k,nf=O.current.get(cf);if(nf)return nf;let of=W.current,J0=performance.now();if(U.current===k)Y(!0);let e0=(async()=>{try{let J1=await NX(_,k);if(of!==W.current||U.current!==k)return;let N0=J1?.summary||{};Y1(k,{id:k,status:N0.status,updatedAt:N0.updatedAt,startedAt:N0.startedAt,finishedAt:N0.finishedAt,currentAttempt:N0.currentAttempt,maxAttempts:N0.maxAttempts,finalResponse:N0.finalResponse,lastJudge:N0.lastJudge,lastError:N0.lastError,attempts:Array.isArray(N0.attempts)?N0.attempts:[],timing:N0.timing,_traceSummary:N0,_traceSummaryLoaded:!0,_traceSummaryUpdatedAt:String(N0.updatedAt||""),_detailLoaded:!0},of),iu({phase:"complete",taskId:k,queueMs:Kf??0,detailMs:performance.now()-J0,totalMs:Qf===void 0?performance.now()-J0:performance.now()-Qf,chunks:1,transcriptRows:Number(N0?.execution?.stepCount||0),partial:!1,completedAt:new Date})}finally{if(O.current.delete(cf),of===W.current&&U.current===k)Y(!1)}})();O.current.set(cf,e0),await e0}async function ml(k,a=null){let Qf=U.current;if(!l||!Qf||!k)return;let Kf=N.current.get(Qf)?.task,Df=R6(Kf),Xf=k==="feedback"||k==="judge-feedback"?gz(a):k;if(Df[Xf]?.text)return;let Sf=`${Qf}:${Xf}`,Rf=G.current.get(Sf);if(Rf)return Rf;let cf=W.current;if(U.current===Qf)Y(!0);let nf=(async()=>{try{let of=await LX(_,Qf,k,a);if(cf!==W.current||U.current!==Qf)return;let J0=N.current.get(Qf)?.task,e0=R6(J0);Y1(Qf,{...k==="full"?{prompt:String(of?.text||""),promptChars:Number(of?.chars||0)}:{},_promptDetails:{...e0,[Xf]:of}},cf)}finally{if(G.current.delete(Sf),cf===W.current&&U.current===Qf)Y(!1)}})();G.current.set(Sf,nf),await nf}async function O2(k=null){let a=U.current;if(!l||!a)return;let Qf=N.current.get(a)?.task,Kf=k===null||k===void 0||String(k).length===0?"":String(k);if(tz(Qf,Kf||null))return;let Df=`${a}:${Kf||"all"}`,Xf=H.current.get(Df);if(Xf)return Xf;let Sf=W.current;if(U.current===a)Y(!0);let Rf=(async()=>{try{let cf=await YX(_,a,0,500,Kf||null);if(Sf!==W.current||U.current!==a)return;let nf=Array.isArray(cf?.steps)?cf.steps:[];if(Kf){let of=N.current.get(a)?.task,J0=b_(of?._traceStepsByAttempt)||{},e0=b_(of?._traceStepsLoadedByAttempt)||{};Y1(a,{_traceStepsByAttempt:{...J0,[Kf]:nf},_traceStepsLoadedByAttempt:{...e0,[Kf]:!0}},Sf)}else Y1(a,{_traceSteps:nf,_traceStepsLoaded:!0,_traceStepsHasMore:Boolean(cf?.hasMore),_traceStepsNextAfterSeq:cf?.nextAfterSeq},Sf)}finally{if(H.current.delete(Df),Sf===W.current&&U.current===a)Y(!1)}})();H.current.set(Df,Rf),await Rf}async function X2(k){let a=U.current,Qf=String(k??"");if(!l||!a||Qf.length===0)return;let Kf=N.current.get(a)?.task;if(Hj(Kf)[Qf]?.line)return;let Xf=`${a}:${Qf}`,Sf=Z.current.get(Xf);if(Sf)return Sf;let Rf=W.current;if(U.current===a)Y(!0);let cf=(async()=>{try{let nf=await BX(_,a,k);if(Rf!==W.current||U.current!==a)return;let of=N.current.get(a)?.task,J0=Hj(of);Y1(a,{_traceStepDetails:{...J0,[Qf]:nf}},Rf)}finally{if(Z.current.delete(Xf),Rf===W.current&&U.current===a)Y(!1)}})();Z.current.set(Xf,cf),await cf}async function ZQ(k,a,Qf){if(!l||!k)return;let Kf=performance.now(),Df=W.current,Xf=N.current.get(k);if(Xf?.task){if(S(Xf.task),Y(P6(Xf.task)||!Xf.complete),!P6(Xf.task)&&Xf.complete&&P1(Xf.task)&&String(Xf.completeUpdatedAt||"")===String(Xf.task?.updatedAt||"")){iu({phase:"complete",taskId:k,queueMs:Qf??0,detailMs:0,totalMs:a===void 0?0:performance.now()-a,chunks:0,transcriptRows:Array.isArray(Xf.task.transcript)?Xf.task.transcript.length:0,completedAt:new Date});return}}else Y(!0);let Sf=E.current;if(Sf?.taskId===k&&Sf.token===Df)return Sf.promise;let Rf=(async()=>{try{let cf=await M0(S0(_,`/api/tasks/${encodeURIComponent(k)}?meta=1`));if(Df!==W.current||U.current!==k)return;let nf=N.current.get(k),of=Array.isArray(nf?.task?.transcript)?nf.task.transcript:[],J0=cf?.task||{},e0=Boolean(nf?.complete)&&String(nf?.completeUpdatedAt||"")===String(J0?.updatedAt||"");Y1(k,{...J0,summaryOnly:!1,_metaLoaded:!0,transcript:of,_detailLoaded:of.length>0,_transcriptComplete:e0},Df);let J1=P6(nf?.task)||Boolean(nf?.task?._transcriptPreview),N0=J1?0:of.length>0?vz(of):0,z_=!J1&&nf?.complete&&P1(J0)&&String(nf?.completeUpdatedAt||"")===String(J0?.updatedAt||"")?Y4(of):N0,l3=!0,nl=0,tl=of.length;while(l3){let nu=await M0(S0(_,`/api/tasks/${encodeURIComponent(k)}/transcript?afterSeq=${encodeURIComponent(String(z_))}&limit=${FX}&fullText=1`));if(Df!==W.current||U.current!==k)return;let B1=N.current.get(k),Fy=Array.isArray(B1?.task?.transcript)?B1.task.transcript:[],Qy=Aj(Fy,Array.isArray(nu?.transcript)?nu.transcript:[]);nl+=1,tl=Qy.length;let g0=Boolean(!nu?.hasMore);if(Y1(k,{status:nu?.status||J0.status,updatedAt:nu?.updatedAt||J0.updatedAt,transcript:Qy,_detailLoaded:g0||Qy.length>0,_transcriptComplete:g0,_transcriptPreview:J1&&!g0},Df),l3=Boolean(nu?.hasMore),z_=Number(nu?.nextAfterSeq??Y4(Qy)),!l3)break;await new Promise((XQ)=>window.setTimeout(XQ,0))}iu({phase:"complete",taskId:k,queueMs:Qf??0,detailMs:performance.now()-Kf,totalMs:a===void 0?performance.now()-Kf:performance.now()-a,chunks:nl,transcriptRows:tl,completedAt:new Date})}finally{if(E.current?.taskId===k&&E.current?.token===Df)E.current=null;if(Df===W.current&&U.current===k)Y(!1)}})();E.current={taskId:k,token:Df,promise:Rf},await Rf}async function gu(k=U.current,a=!0,Qf=ff){if(!l)return;if(!a&&L.current)return;let Kf=performance.now();if(a)L.current=!0;if(a)iu({phase:"loading",taskId:String(k||U.current||""),startedAt:new Date});let Df=z.current+1;z.current=Df;let Xf=String(k||U.current||""),Sf=Xf?N.current.get(Xf):null,Rf=Array.isArray(Sf?.task?.transcript)?Sf.task.transcript:[],cf=vz(Rf),nf=x||{},of=null;try{of=await OX(_,Xf,cf,Qf)}catch{of=await VX(_,nf,Qf)}if(Df!==z.current){if(a)L.current=!1;return}let J0=performance.now()-Kf;c(nf);let e0=of?.queue||{},J1=String(e0?.activeTaskId||w4(e0)[0]||""),N0=of;i1((Uu)=>{let T$=Z1(of),Ay=Z1(Uu),j3=Ay.length>0?N4([Ay,T$],J1):N4([T$],J1),sH=r6(of),ol=r6(Uu),oH=Ay.length>T$.length&&(ol.hasMore===!1||String(ol.nextBeforeId||"").length>0),aH={...sH,...oH?{hasMore:ol.hasMore,nextBeforeId:ol.nextBeforeId}:{},returned:j3.length};return N0={...of,tasks:j3,pagination:aH},N0});let z_=Z1(N0),l3=rz(e0,_f),nl=Pz(e0,l3,Qf,z_),tl=EX(l3,Qf,z_),nu=Xf||U.current,B1=N0?.selected||null,Fy=B1?.task||null,Qy=Array.isArray(B1?.transcript)?B1.transcript:null,g0=nu&&(z_.some((Uu)=>Uu.id===nu)||String(Fy?.id||"")===nu)?nu:nl||tl||z_[0]?.id||"";if(U.current!==g0)W.current+=1;U.current=g0,w(g0);let sl=z_.find((Uu)=>Uu.id===g0);if(sl){let Uu=N.current.get(g0);if(Uu?.task)N.current.set(g0,{...Uu,task:{...sl,...Uu.task,status:sl.status,updatedAt:sl.updatedAt}})}if(Fy?.id===g0&&Qy!==null){let Uu=N.current.get(g0),T$=Array.isArray(Uu?.task?.transcript)?Uu.task.transcript:[],Ay=Aj(T$,Qy),j3=Boolean(B1?.preview);if(Y1(g0,{...Fy,_summaryLoaded:!0,transcript:Ay,_detailLoaded:!B1?.hasMore||Ay.length>0,_transcriptComplete:!j3&&!B1?.hasMore&&P1(Fy),_transcriptPreview:j3},W.current),Y(!1),a)iu({phase:"complete",taskId:g0,queueMs:J0,detailMs:Math.max(0,performance.now()-Kf-J0),totalMs:performance.now()-Kf,chunks:1,transcriptRows:Ay.length,partial:Boolean(j3||B1?.hasMore||P6(Fy)),completedAt:new Date});if(u3(new Date),a)L.current=!1;return}if(a)iu({phase:"session",taskId:g0,queueMs:J0,totalMs:J0,startedAt:new Date(Date.now()-J0)});if(g0)Y$(g0,!0,a?Kf:void 0,a?J0:void 0).catch((Uu)=>X0(Ty(Uu,"加载 Codex Trace Summary 失败")));else if(W.current+=1,S(null),Y(!1),a)iu({phase:"complete",taskId:"",queueMs:J0,detailMs:0,totalMs:performance.now()-Kf,chunks:0,transcriptRows:0,completedAt:new Date});if(u3(new Date),a)L.current=!1}async function kl(){if(!l||s||q.current)return;let k=String(r6(v).nextBeforeId||"");if(!k)return;q.current=!0,Of(!0),X0("");try{let a=await XX(_,ff,k),Qf=Z1(a),Kf=a?.queue||If||{},Df=String(Kf?.activeTaskId||w4(Kf)[0]||ly||"");i1((Xf)=>{let Sf=N4([Z1(Xf),Qf],Df),Rf=r6(a);return{...Xf||{},queue:Kf,tasks:Sf,pagination:{...Rf,returned:Sf.length}}})}catch(a){X0(Ty(a,"加载更早 Codex tasks 失败"))}finally{q.current=!1,Of(!1)}}function il(k){let a=k.currentTarget;if(!a||s||!vl)return;if(a.scrollHeight-a.scrollTop-a.clientHeight<120)kl()}async function Tu(k,a){x0(!0),X0("");try{await k()}catch(Qf){X0(Ty(Qf,a))}finally{x0(!1)}}async function $3(k){if(!k)return;try{let a=!1;try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(k),a=!0}catch{a=!1}if(!a){let Qf=document.createElement("textarea");Qf.value=k,Qf.style.position="fixed",Qf.style.opacity="0",document.body.appendChild(Qf),Qf.select(),a=document.execCommand("copy"),document.body.removeChild(Qf)}if(!a)throw Error("browser clipboard rejected the copy request");a0(k),uf(`已复制任务 ID:${k}`),window.setTimeout(()=>a0((Qf)=>Qf===k?"":Qf),1600)}catch(a){X0(`复制任务 ID 失败:${Ty(a)}`)}}function B$(k){if(!k)return;n(k),uf(`已引用任务 ID:${k};提交时后端会读取并注入该任务上下文`)}async function w$(k){if(!l||!k)return;v0(k),await Tu(async()=>{let a=null,Qf=!1;try{a=await wX(_,k)}catch{Qf=!0}let Kf=a?.task||{id:k,readAt:new Date().toISOString(),terminalUnread:!1},Df=String(Kf?.readAt||new Date().toISOString());L$([k],Df),pl([k],Df,a?.queue||null,Kf),uf(Qf?`已在本浏览器将任务 ${k} 标为已读;后端升级后会同步持久化`:`已将任务 ${k} 标为已读`)},"标记 Codex task 已读失败"),v0((a)=>a===k?"":a)}async function D$(){if(!l||i0)return;d0(!0),await Tu(async()=>{let k=null,a=!1;try{k=await DX(_)}catch{a=!0}let Qf=String(k?.readAt||new Date().toISOString()),Kf=Z1(D.current).map((Rf)=>Qj(Rf,b0)).filter(c3).map((Rf)=>String(Rf?.id||"")).filter(Boolean),Df=Array.from(N.current.entries()).filter(([,Rf])=>c3(Qj(Rf?.task,b0))).map(([Rf])=>Rf),Xf=Array.from(new Set([...Kf,...Df]));L$(Xf,Qf),pl(Xf,Qf,k?.queue||null);let Sf=a?Xf.length:Number(k?.count||Xf.length);uf(a?`已在本浏览器将 ${Sf} 个已结束未读任务标为已读;后端升级后会同步持久化`:`已将 ${Sf} 个已结束未读任务标为已读`)},"全部标为已读失败"),d0(!1)}function N2(k){let a=k||v_;if(Gf(a),!vu(a))t(a);if(i1(null),!(vu(a)?U.current:""))U.current="",W.current+=1,w(""),S(null),Y(!0)}async function L2(){let k=typeof window>"u"?"":window.prompt("输入新的 Codex queue ID(字母/数字/._-,最长 64)","new-lane"),a=String(k||"").trim();if(!a)return;await Tu(async()=>{let Qf=await M0(S0(_,"/api/queues"),{method:"POST",body:{queueId:a}}),Kf=String(Qf?.queue?.id||a);t(Kf),Gf(Kf),i1(null),U.current="",W.current+=1,w(""),S(null),uf(`已创建并切换到 queue:${Kf}`),await gu("",!0,Kf)},"创建 Codex queue 失败")}async function gl(k){if(k.preventDefault(),K.current){uf("任务正在提交中,请等待当前请求完成,已阻止重复提交。");return}if(j1.length>1&&!$f){X0(`检测到将创建 ${j1.length} 个任务;请先勾选“确认批量入队”,避免误传多个任务。`);return}K.current=!0,Yf(!0),uf("正在提交 Codex Queue 任务,请等待后端确认,输入已临时锁定。"),await Tu(async()=>{if(j1.length===0)throw Error("prompt 不能为空");let a=D4(p),Qf=_f.trim()||"default",Kf=[...j1],Df=(nf)=>({prompt:nf,queueId:Qf,model:zf,cwd:Wf,maxAttempts:Number(Zf),...a.length>0?{referenceTaskIds:a}:{}}),Xf=Kf.length===1?Df(Kf[0]):{tasks:Kf.map(Df)},Sf=await M0(S0(_,Kf.length===1?"/api/tasks":"/api/tasks/batch"),{method:"POST",body:Xf}),Rf=Sf?.tasks?.[0]?.id||"",cf=Array.isArray(Sf?.tasks)?Sf.tasks.map((nf)=>String(nf?.id||"")).filter(Boolean):[];if(uf(`已创建 ${cf.length||Kf.length} 个任务${cf.length>0?`:${cf.join(" / ")}`:""}`),m(""),n(""),lf(!1),U.current=Rf,ff!==Qf)i1(null);Gf(Qf),t(Qf),await gu(Rf,!0,Qf)},"Codex 任务入队失败"),K.current=!1,Yf(!1)}async function hH(k){if(k.preventDefault(),!r?.id)return;await Tu(async()=>{await M0(S0(_,`/api/tasks/${encodeURIComponent(r.id)}/steer`),{method:"POST",body:{prompt:xf}}),sf(""),await gu(r.id)},"追加 prompt 失败")}async function IH(){if(!r?.id)return;await Tu(async()=>{await M0(S0(_,`/api/tasks/${encodeURIComponent(r.id)}/interrupt`),{method:"POST",body:{}}),await gu(r.id)},"打断 Codex session 失败")}async function cH(){if(!r?.id)return;await Tu(async()=>{await M0(S0(_,`/api/tasks/${encodeURIComponent(r.id)}/retry`),{method:"POST",body:{}}),await gu(r.id)},"重新入队失败")}async function pH(k){let a=String(r?.id||""),Qf=String(k||"").trim();if(!a||!Qf)return;let Kf=M4(r);if(Qf===Kf){uf(`任务 ${a} 已在 queue=${Qf}`);return}await Tu(async()=>{let Xf=(await M0(S0(_,`/api/tasks/${encodeURIComponent(a)}/move`),{method:"POST",body:{queueId:Qf}}))?.task||{...r,queueId:Qf};if(N.current.set(a,{...N.current.get(a)||{},task:Xf}),U.current=a,S(Xf),w(a),t(Qf),!vu(ff))i1(null),Gf(Qf);uf(`已将任务 ${a} 从 ${Kf} 移动到 ${Qf}`),await gu(a,!0,vu(ff)?v_:Qf)},"移动任务 queue 失败")}async function mH(){let k=U.current;if(!k)return;let a=performance.now();await Tu(async()=>{iu({phase:"session",taskId:k,queueMs:0,totalMs:0,partial:!0,startedAt:new Date}),await Y$(k,!0,a,0)},"刷新 Trace Summary 失败")}function kH(k){U.current=k,W.current+=1,w(k);let a=N.current.get(k);if(a?.task)S(a.task),Y(!1);else{Y(!0);let Qf=qf.find((Kf)=>Kf.id===k);if(Qf)S(Qf);else S(null)}gu(k).catch((Qf)=>X0(Ty(Qf,"切换 Codex session 失败")))}function Y2(k){if(kH(k),HX())Fu(!1)}C6(()=>{if(M.current){M.current=!1;return}Tu(()=>gu(U.current),"Codex Queue 加载失败")},[l?.id,ff]),C6(()=>{if(!l)return;let k=()=>{if(!Tz())return;gu(U.current,!1).catch((Kf)=>X0(Ty(Kf,"Codex Queue 轮询失败")))},a=window.setInterval(()=>{k()},1500),Qf=()=>{if(Tz())k()};return document.addEventListener("visibilitychange",Qf),()=>{window.clearInterval(a),document.removeEventListener("visibilitychange",Qf)}},[l?.id,ff]),C6(()=>{if(!l||!r||T)return;let k=String(r.id||"");if(!k)return;let a=String(r.updatedAt||""),Qf=String(r._traceSummaryUpdatedAt||"");if(r._traceSummaryLoaded===!0&&Qf===a)return;let Kf=`${k}:${a||"unknown"}`;if(V.current.has(Kf))return;V.current.add(Kf),Y$(k,!0).catch((Df)=>X0(Ty(Df,"自动加载 Trace Summary 失败")))},[l?.id,r?.id,r?.updatedAt,r?._traceSummaryUpdatedAt,r?._traceSummaryLoaded,T]);let iH=qf.length===0?B(ry,{title:"队列为空",text:"提交一个任务后,Codex 会串行执行并保存输出。"}):[Cf.length>0?B(Wj,{key:"unread",title:"已结束未读",tasks:Cf,selectedId:P,emptyText:"暂无已结束未读任务。",onSelect:Y2,onCopy:$3,onReference:B$,onMarkRead:w$,copiedTaskId:vf,markingReadTaskId:Bf}):null,B(Wj,{key:"active",title:"运行 / 排队",tasks:_0,selectedId:P,emptyText:"当前没有运行或排队任务。",onSelect:Y2,onCopy:$3,onReference:B$,onMarkRead:w$,copiedTaskId:vf,markingReadTaskId:Bf}),B(Wj,{key:"history",title:"历史 session",tasks:G0,selectedId:P,emptyText:"最近没有完成、失败或取消的 session。",onSelect:Y2,onCopy:$3,onReference:B$,onMarkRead:w$,copiedTaskId:vf,markingReadTaskId:Bf}),B("div",{key:"pagination",className:"codex-task-pagination","data-testid":"codex-task-pagination"},B("span",null,`已加载 ${qf.length} / ${Number.isFinite(L1)?L1:qf.length}`),vl?B("button",{type:"button",className:"ghost-btn",disabled:s,onClick:()=>void kl(),"data-testid":"codex-load-more-tasks-button"},s?"加载中":"加载更早任务"):B("code",null,"已到队列末尾"))],qQ=(k,a=!1)=>B("label",{className:`codex-queue-switcher ${a?"compact":""}`},B("span",null,a?"Queue":"查看 queue"),B("select",{value:ff,onChange:(Qf)=>N2(String(Qf.target.value||v_)),"data-testid":k},B("option",{value:v_},`All queues · ${Number.isFinite(L1)?L1:qf.length} tasks · ${_3.length} running`),Au.map((Qf)=>B("option",{key:String(Qf?.id||""),value:String(Qf?.id||"")},Gj(Qf))))),gH=B("div",{className:"codex-trace-status","data-testid":"codex-trace-status-summary"},B("span",{className:"codex-trace-status-chip queued"},B("b",null,"排队"),String(Z2)),B("span",{className:"codex-trace-status-chip running"},B("b",null,"运行"),String(hl)),B("span",{className:`codex-trace-status-chip unread ${k1>0?"warn":""}`},B("b",null,"结束未读"),String(k1))),nH=B(Sy,{title:r?`Trace ${String(r.id).slice(0,22)}`:"Trace 输出",eyebrow:r?`${r.status} / view=${jy} / task queue=${M4(r)} / ${r.model} / agent loop trace`:`Agent loop trace / view=${jy}`,summary:gH,actions:B("div",{className:"panel-actions"},qQ("codex-queue-filter-select"),B("button",{type:"button",className:"ghost-btn codex-mark-all-read-btn",disabled:k1===0||O0||i0,onClick:()=>void D$(),"data-testid":"codex-mark-all-read-button"},i0?"标记中":`全部标已读${k1>0?` (${k1})`:""}`),r?B("button",{type:"button",className:"ghost-btn",disabled:T||O0,onClick:()=>void mH(),"data-testid":"codex-load-full-trace-button"},T?"加载中":Cy(r)?"刷新 Summary":"加载 Summary"):null,B("button",{type:"button",className:"codex-session-title-toggle",onClick:()=>Fu((k)=>!k),"data-testid":"codex-queue-sidebar-toggle"},D0?"收起队列":"展开队列"),B("label",{className:"inline-check"},B("input",{type:"checkbox",checked:j0,onChange:(k)=>u0(Boolean(k.target.checked))}),"自动滚动"),B("button",{type:"button",className:"ghost-btn",disabled:!E2||O0,onClick:()=>void IH(),"data-testid":"codex-interrupt-button"},"打断"),B("button",{type:"button",className:"ghost-btn",disabled:!V2||O0,onClick:()=>void cH()},"重试"),r?B(Mz,{title:"Codex Task",data:r,onOpen:u,testId:"raw-codex-task"}):null),className:"codex-output-panel"},B("div",{className:`codex-session-shell ${D0?"":"queue-collapsed"}`},D0?B("aside",{className:"codex-session-sidebar","data-testid":"codex-session-sidebar"},B("div",{className:"codex-session-sidebar-head"},B("div",null,B("span",null,vu(ff)?"All queues":"Queue lane"),B("strong",null,`${jy} · ${qf.length}/${Number.isFinite(L1)?L1:qf.length} sessions · 未读 ${k1}`)),B("button",{type:"button",className:"ghost-btn",onClick:()=>Fu(!1)},"收起")),qQ("codex-queue-filter-sidebar",!0),B("div",{className:"codex-task-list codex-task-list-session",onScroll:il,"data-testid":"codex-task-list-scroll"},iH)):null,B("div",{className:"codex-session-main"},B("div",{className:"codex-output-stack"},B(_N,{task:r,loading:T,onLoadPromptPart:ml,onLoadSteps:O2,onLoadStep:X2}),B($N,{task:r})))));if(!l)return B(ry,{title:"Codex Queue 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=codex-queue"});let HQ=Number(ef?.totalMs),EQ=Number(ef?.queueMs),VQ=Number(ef?.detailMs),OQ=Number(ef?.transcriptRows),tH=ef?.phase==="complete"?"complete":String(ef?.phase||"idle");return B("div",{className:`codex-queue-page ${$?"codex-standalone-page":""}`,"data-testid":"codex-queue-page","data-load-state":tH,"data-load-total-ms":Number.isFinite(HQ)?String(Math.round(HQ*10)/10):"","data-load-queue-ms":Number.isFinite(EQ)?String(Math.round(EQ*10)/10):"","data-load-detail-ms":Number.isFinite(VQ)?String(Math.round(VQ*10)/10):"","data-load-transcript-rows":Number.isFinite(OQ)?String(OQ):"","data-load-task-id":String(ef?.taskId||P||""),"data-load-partial":ef?.partial?"true":"false"},B(H0,{error:ku,wide:!0}),Qu?B("div",{className:"form-success wide","data-testid":"codex-create-success"},Qu):null,B("div",{className:"codex-session-stage codex-session-stage-top"},nH),B("div",{className:"codex-queue-layout"},B("div",{className:"codex-left-rail"},B(Sy,{title:"提交任务",eyebrow:Af?"Submitting...":j1.length>1?`${j1.length} tasks`:"Single or Batch",className:"codex-compose-panel"},B("form",{className:`codex-task-form ${Af?"is-submitting":""}`,onSubmit:gl,"data-testid":"codex-queue-task-form","aria-busy":Af?"true":"false"},B("label",null,"Prompt / 多任务用单独一行 --- 分隔",B("textarea",{value:R,rows:8,disabled:Af,onChange:(k)=>m(k.target.value),placeholder:"写入 Codex 任务;多个任务之间用 --- 分隔。"})),B("label",{className:"codex-reference-field"},"引用任务 ID(可选)",B("input",{value:p,disabled:Af,onChange:(k)=>n(k.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-reference-task-id"}),D4(p).length>0?B("code",null,`后端将解析并注入:${D4(p).join(" / ")}`):null),B("div",{className:"codex-form-grid"},B("label",{className:"codex-submit-queue-field"},"Queue",B("div",{className:"codex-submit-queue-row"},B("select",{value:_f,disabled:Af,onChange:(k)=>t(String(k.target.value||"default")),"data-testid":"codex-queue-id-select"},Au.map((k)=>B("option",{key:String(k?.id||""),value:String(k?.id||"")},Gj(k)))),B("button",{type:"button",className:"ghost-btn codex-create-queue-btn",onClick:()=>void L2(),disabled:O0||Af,"data-testid":"codex-create-queue-button"},"创建 queue"))),B("label",null,"模型",B("select",{value:zf,disabled:Af,onChange:(k)=>jf(k.target.value),"data-testid":"codex-model-select"},cl.map((k)=>B("option",{key:k,value:k},k)))),B("label",null,"工作目录",B("input",{value:Wf,disabled:Af,onChange:(k)=>Vf(k.target.value),placeholder:If?.defaultWorkdir||"/root/unidesk"})),B("label",null,"最大尝试",B("input",{type:"number",min:1,max:99,value:Zf,disabled:Af,onChange:(k)=>h(Number(k.target.value)),"data-testid":"codex-max-attempts-input"})),B("label",null,"入队份数",B("input",{type:"number",min:1,max:50,value:g,disabled:Af,onChange:(k)=>I(Number(k.target.value)),"data-testid":"codex-repeat-count-input"}))),Jy>1?B("label",{className:`codex-batch-confirm ${$f?"confirmed":""}`,"data-testid":"codex-batch-confirm-row"},B("input",{type:"checkbox",checked:$f,disabled:Af,onChange:(k)=>lf(Boolean(k.target.checked)),"data-testid":"codex-batch-confirm-checkbox"}),B("span",null,`确认批量入队 ${Jy} 个任务(prompt 分段 ${O$.length} × 入队份数 ${Cz(g)})`)):null,Af?B("div",{className:"codex-submit-wait","data-testid":"codex-submit-wait"},"正在提交到后端,已锁定输入以防重复提交..."):null,B("div",{className:"codex-form-actions"},B("button",{type:"button",className:"ghost-btn",disabled:O0||Af||R.length===0&&p.length===0,onClick:()=>{m(""),n(""),lf(!1),uf("已清空任务输入栏")},"data-testid":"codex-clear-input-button"},"清空输入"),B("button",{type:"submit",className:"primary-btn",disabled:H2,"data-testid":"codex-enqueue-button"},Af?"提交中,请等待...":X$?`请确认批量入队 ${Jy} 个任务`:j1.length>1?`批量入队 ${j1.length} 个任务`:"入队并运行"))))),B("div",{className:"codex-main-stage"},B("div",{className:"codex-detail-grid"},B(Sy,{title:"Prompt 全量",eyebrow:r?String(r.id):"selected task",className:"codex-prompt-panel"},B(yN,{task:r,loading:T,onLoadPromptPart:ml})),B(Sy,{title:"运行控制",eyebrow:N$?"Active turn steer":"Steer when running"},B("div",{className:"codex-run-control-stack"},B(aX,{task:r,queueRows:Au,busy:O0,onMove:pH}),B("form",{className:"codex-steer-form",onSubmit:hH},B("label",null,"追加 prompt",B("textarea",{value:xf,rows:4,onChange:(k)=>sf(k.target.value),placeholder:"给正在运行的 Codex session 推入新的指令或纠偏。",disabled:!N$})),B("button",{type:"submit",className:"primary-btn",disabled:!N$||O0||xf.trim().length===0,"data-testid":"codex-steer-button"},"推入运行中 session")))),B(Sy,{title:"完成判定",eyebrow:r?.lastJudge?r.lastJudge.source:"judge"},r?.lastJudge?B("div",{className:"codex-judge-card","data-testid":"codex-task-judge-card"},B(y_,{status:r.lastJudge.decision},r.lastJudge.decision),B("strong",null,`${Math.round(Number(r.lastJudge.confidence||0)*100)}% confidence`),B("p",{"data-testid":"codex-task-judge-reason"},r.lastJudge.reason||"--"),r.lastJudge.continuePrompt?B("code",{"data-testid":"codex-task-judge-continue-prompt"},hz(r.lastJudge.continuePrompt,220)):null):B(ry,{title:"尚未判定",text:"Codex turn 结束后会由 MiniMax M2.7 或 fallback judge 判定 complete/retry/fail;retry 会在已有 thread 追加继续执行 prompt。"}))),B(Sy,{title:"Attempts",eyebrow:"terminal vs interruption"},B(lN,{task:r})))),B(Sy,{title:"运行概要",eyebrow:"用户服务",actions:B("div",{className:"panel-actions"},B("button",{type:"button",className:"ghost-btn",onClick:()=>void Tu(()=>gu(P),"刷新失败"),disabled:O0,"data-testid":"codex-refresh-button"},O0?"同步中":"刷新"),B(Mz,{title:"Codex Queue 用户服务",data:l,onOpen:u,testId:"raw-codex-queue-service"}))},B("div",{className:"codex-queue-hero"},B("div",null,B("div",{className:"node-version-line"},B(y_,{status:Il.providerStatus==="online"?"online":"warn"},Il.providerStatus||"unknown"),B("span",null,l.providerId),B("span",null,V$.public?"公网暴露":"仅 UniDesk frontend 代理访问"),B("span",null,If?.judgeConfigured?`MiniMax ${If?.minimaxModel||"M2.7"}`:"Fallback judge")),B("p",{className:"muted paragraph"},l.description)),B("div",{className:"microservice-ref-card"},B("span",null,"Queue view"),B("strong",null,jy),B("code",null,`${qf.length}/${Number.isFinite(L1)?L1:qf.length} loaded / ${_3.length} active lanes`),B("code",null,`models: ${cl.join(" / ")}`)),B("div",{className:"microservice-ref-card"},B("span",null,"Backend"),B("strong",null,`${V$.nodeBindHost||"--"}:${V$.nodePort||"--"}`),B("code",null,q2.containerName||"codex-queue-backend")))),B("div",{className:"codex-queue-metrics"},B(My,{label:"Queues",value:String(If?.queueCount??Au.length??1),hint:`${Number(y3.length||0)} active lanes`,tone:y3.length>1?"warn":""}),B(My,{label:"排队",value:Uj(W_,"queued"),hint:"waiting turns"}),B(My,{label:"运行",value:Uj(W_,"running"),hint:y3.length>1?`${y3.length} parallel`:ly?`active ${String(ly).slice(0,16)}`:"idle",tone:ly?"warn":"ok"}),B(My,{label:"成功",value:Uj(W_,"succeeded"),hint:"completed tasks",tone:"ok"}),B(My,{label:"异常/取消",value:String(Number(W_.failed||0)+Number(W_.canceled||0)),hint:"terminal non-success",tone:Number(W_.failed||0)>0?"fail":""}),B(My,{label:"加载耗时",value:Jj(ef?.totalMs),hint:ef?.phase==="complete"?`queue ${Jj(ef?.queueMs)} / session ${Jj(ef?.detailMs)} / ${ef?.chunks??0} chunks${ef?.partial?" / preview":""}`:`${ef?.phase||"idle"}...`,tone:Number(ef?.totalMs||0)>1000?"warn":"ok"}),B(My,{label:"最近刷新",value:f3?WX(f3):"--",hint:"1.5s polling"})))}var x4=rf(I0(),1);var Jf=x4.default.createElement,{useEffect:jN}=x4.default,JN=x4.default.useState;function FN(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return u.toLocaleString("zh-CN",{hour12:!1})}function QN(f){return f.toLocaleTimeString("zh-CN",{hour12:!1})}function P4({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return Jf("span",{className:`status-badge ${_}`},u||f||"unknown")}function h_({label:f,value:u,hint:_,tone:y}){return Jf("article",{className:`metric-card ${y||""}`},Jf("div",{className:"metric-label"},f),Jf("div",{className:"metric-value"},u),Jf("div",{className:"metric-hint"},_))}function C4({title:f,eyebrow:u,actions:_,children:y,className:$}){return Jf("section",{className:`panel ${$||""}`},Jf("div",{className:"panel-head"},Jf("div",null,u?Jf("p",{className:"panel-eyebrow"},u):null,Jf("h2",null,f)),_?Jf("div",{className:"panel-actions"},_):null),Jf("div",{className:"panel-body"},y))}function R4({title:f,data:u,onOpen:_,testId:y}){return Jf("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function Oj({title:f,text:u}){return Jf("div",{className:"empty-state"},Jf("strong",null,f),Jf("span",null,u))}function AN(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function UN(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function WN(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function Ry(f,u){let _=f&&typeof f==="object"?f[u]:void 0;return Number.isFinite(Number(_))?String(_):"--"}function zN(f){return(Array.isArray(f?.jobs)?f.jobs:[]).slice(0,40)}function GN(f){return(Array.isArray(f?.drafts)?f.drafts:[]).slice(0,12)}function fG({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((q)=>q.id==="findjob")||null,[$,l]=JN({loading:!1,error:"",health:null,summary:null,jobs:null,drafts:null,refreshedAt:null});async function j(){if(!y)return;l((q)=>({...q,loading:!0,error:""}));try{let[q,E,O,G]=await Promise.all([wf(`${_}/microservices/findjob/health`),wf(`${_}/microservices/findjob/proxy/api/summary`),wf(`${_}/microservices/findjob/proxy/api/jobs?__unideskArrayLimit=jobs:40`),wf(`${_}/microservices/findjob/proxy/api/drafts`)]);l({loading:!1,error:"",health:q,summary:E,jobs:O,drafts:G,refreshedAt:new Date})}catch(q){l((E)=>({...E,loading:!1,error:Mf(q,"FindJob 加载失败")}))}}if(jN(()=>{j()},[y?.id,y?.runtime?.providerStatus]),!y)return Jf(Oj,{title:"FindJob 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=findjob"});let J=AN(y),F=WN(y),A=UN(y),U=$.summary||{},z=zN($.jobs),W=GN($.drafts),K=$.jobs?._unidesk?.arrayLimits?.jobs;return Jf("div",{className:"findjob-page","data-testid":"findjob-page"},Jf(C4,{title:"FindJob 工作台",eyebrow:"D601 用户服务",actions:Jf("div",{className:"panel-actions"},Jf("button",{type:"button",className:"ghost-btn",onClick:j,disabled:$.loading,"data-testid":"findjob-refresh-button"},$.loading?"刷新中":"刷新"),Jf(R4,{title:"FindJob 用户服务",data:y,onOpen:u,testId:"raw-findjob-service"}))},Jf("div",{className:"findjob-hero"},Jf("div",null,Jf("div",{className:"node-version-line"},Jf(P4,{status:J.providerStatus==="online"?"online":"warn"},J.providerStatus||"unknown"),Jf("span",null,y.providerId),Jf("span",null,A.public?"公网暴露":"仅 UniDesk frontend 代理访问")),Jf("p",{className:"muted paragraph"},y.description)),Jf("div",{className:"microservice-ref-card"},Jf("span",null,"Repo"),Jf("strong",null,F.url||"--"),Jf("code",null,F.commitId||"--")),Jf("div",{className:"microservice-ref-card"},Jf("span",null,"D601 Docker"),Jf("strong",null,`${A.nodeBindHost||"--"}:${A.nodePort||"--"}`),Jf("code",null,`${F.composeFile||"--"} / ${F.composeService||"--"}`))),Jf(H0,{error:$.error,wide:!0})),Jf("div",{className:"findjob-grid"},Jf(C4,{title:"岗位指标",eyebrow:$.refreshedAt?`Updated ${QN($.refreshedAt)}`:"Summary"},Jf("div",{className:"metric-grid"},Jf(h_,{label:"岗位总量",value:Ry(U,"totalJobs"),hint:"tracked jobs",tone:"ok"}),Jf(h_,{label:"原始岗位",value:Ry(U,"rawJobs"),hint:"raw queue"}),Jf(h_,{label:"已验证",value:Ry(U,"verifiedJobs"),hint:"verified set"}),Jf(h_,{label:"优先处理",value:Ry(U,"prioritizedJobs"),hint:"prioritized"}),Jf(h_,{label:"过期",value:Ry(U,"staleJobs"),hint:"stale jobs",tone:"warn"}),Jf(h_,{label:"无效",value:Ry(U,"invalidJobs"),hint:"invalid jobs",tone:"warn"}),Jf(h_,{label:"上海",value:Ry(U,"shanghaiJobs"),hint:"city filter"}),Jf(h_,{label:"Health",value:$.health?.ok?"OK":"--",hint:"D601 /api/health"})),Jf("div",{className:"panel-actions inline-actions"},Jf(R4,{title:"FindJob Summary",data:U,onOpen:u,testId:"raw-findjob-summary"}))),Jf(C4,{title:"近期岗位",eyebrow:K?`${K.returnedLength}/${K.originalLength} Preview`:`${z.length} Preview`},z.length===0?Jf(Oj,{title:"暂无岗位预览",text:"等待 D601 findjob backend 返回 /api/jobs"}):Jf("div",{className:"table-wrap findjob-job-table"},Jf("table",null,Jf("thead",null,Jf("tr",null,Jf("th",null,"优先级"),Jf("th",null,"状态"),Jf("th",null,"单位"),Jf("th",null,"职位"),Jf("th",null,"城市"),Jf("th",null,"阶段"),Jf("th",null,"截止"),Jf("th",null,"证据"))),Jf("tbody",null,z.map((q)=>Jf("tr",{key:q.id},Jf("td",null,Jf(P4,{status:String(q.priority||"").toLowerCase()||"unknown"},q.priority||"--")),Jf("td",null,Jf(P4,{status:String(q.status||"").toLowerCase()||"unknown"},q.status||"--")),Jf("td",null,q.organization_name||"--",Jf("code",null,q.id||"--")),Jf("td",null,q.display_title||q.title||"--"),Jf("td",null,q.display_city||q.city||"--"),Jf("td",null,q.workflow_stage||"--"),Jf("td",null,q.deadline||"--"),Jf("td",null,q.evidence_url?Jf("a",{href:q.evidence_url,target:"_blank",rel:"noreferrer"},"打开"):Jf("span",{className:"muted"},"无"))))))),Jf("div",{className:"panel-actions inline-actions"},Jf(R4,{title:"FindJob Jobs Preview",data:$.jobs,onOpen:u,testId:"raw-findjob-jobs"}))),Jf(C4,{title:"草稿与报告",eyebrow:`${W.length} Drafts`},W.length===0?Jf(Oj,{title:"暂无草稿",text:"D601 findjob backend 未返回 drafts"}):Jf("div",{className:"draft-list"},W.map((q)=>Jf("article",{key:q.id,className:"draft-card"},Jf("div",{className:"node-card-head"},Jf("strong",null,q.id),Jf(P4,{status:q.status},q.status||"--")),Jf("div",{className:"docker-meta compact"},Jf("span",null,q.workflow_stage||"--"),Jf("span",null,`jobs ${q.counts?.jobs??0}`),Jf("span",null,`reports ${q.counts?.reports??0}`)),Jf("span",null,q.latestReportPath||"暂无报告"),Jf("code",null,FN(q.updated_at||q.updatedAt))))),Jf("div",{className:"panel-actions inline-actions"},Jf(R4,{title:"FindJob Drafts",data:$.drafts,onOpen:u,testId:"raw-findjob-drafts"})))))}var I6=rf(I0(),1);var b=I6.default.createElement,{useEffect:KN}=I6.default,Xj=I6.default.useState;function ZN(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return u.toLocaleString("zh-CN",{hour12:!1})}function qN(f){return f.toLocaleTimeString("zh-CN",{hour12:!1})}function v6(f){let u=Number(f);return Number.isFinite(u)?`${Math.max(0,Math.min(100,u)).toFixed(1)}%`:"--"}function Lj(f){if(f===null||f===void 0||f==="")return"--";let u=Number(f);if(!Number.isFinite(u))return"--";if(u<60)return`${Math.max(0,Math.round(u))}s`;if(u<3600)return`${Math.floor(u/60)}m ${Math.round(u%60)}s`;return`${Math.floor(u/3600)}h ${Math.floor(u%3600/60)}m`}function Yj(f,u=2){let _=Number(f);if(!Number.isFinite(_))return f===!1?"false":f===!0?"true":"--";let y=Math.abs(_);if(Number.isInteger(_)||y>=1000)return _.toLocaleString("zh-CN",{maximumFractionDigits:0});if(y>=1)return _.toLocaleString("zh-CN",{maximumFractionDigits:u});return _.toLocaleString("zh-CN",{maximumFractionDigits:Math.max(u,6)})}function h6(f){if(f===null||f===void 0||f==="")return"--";if(typeof f==="boolean")return f?"true":"false";if(typeof f==="number")return Yj(f,4);if(Array.isArray(f))return f.map((u)=>h6(u)).join(" x ");if(typeof f==="object")return"已上报";return String(f)}function v4(f){let u=Number(f);if(!Number.isFinite(u)||u<=0)return"--";let _=u>=100?0:u>=10?1:2;return`${u.toLocaleString("zh-CN",{maximumFractionDigits:_})} epoch/h`}function b4(f){return f.replace(/[^a-zA-Z0-9_-]/g,"-")}function Lu(f){return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function b6({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return b("span",{className:`status-badge ${_}`},u||f||"unknown")}function I_({label:f,value:u,hint:_,tone:y}){return b("article",{className:`metric-card ${y||""}`},b("div",{className:"metric-label"},f),b("div",{className:"metric-value"},u),b("div",{className:"metric-hint"},_))}function Nj({title:f,eyebrow:u,actions:_,children:y,className:$}){return b("section",{className:`panel ${$||""}`},b("div",{className:"panel-head"},b("div",null,u?b("p",{className:"panel-eyebrow"},u):null,b("h2",null,f)),_?b("div",{className:"panel-actions"},_):null),b("div",{className:"panel-body"},y))}function p3({title:f,data:u,onOpen:_,testId:y}){return b("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:($)=>{$?.stopPropagation?.(),_(f,u)}},"查看原始JSON")}function $_({title:f,text:u}){return b("div",{className:"empty-state"},b("strong",null,f),b("span",null,u))}function HN(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function EN(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function VN(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function ON(f){return f?.counts&&typeof f.counts==="object"&&!Array.isArray(f.counts)?f.counts:{}}function XN(f){return Array.isArray(f?.jobs)?f.jobs.slice(0,240):[]}function NN(f){return Array.isArray(f?.projects)?f.projects.slice(0,1000):[]}function h4(f){return Array.isArray(f?.projects)?f.projects:[]}function LN(f,u){if(Array.isArray(u?.gpu))return u.gpu;if(Array.isArray(f?.gpu))return f.gpu;return[]}function bu(f,u){return`${f}/microservices/met-nonlinear/proxy${u}`}function uG(f){return f.startedAt&&f.finishedAt?Lj((Date.parse(f.finishedAt)-Date.parse(f.startedAt))/1000):"--"}function YN(f){let u=f.progress||{};if(u.etaSeconds!==null&&u.etaSeconds!==void 0&&u.etaSeconds!==""){let j=Number(u.etaSeconds);if(Number.isFinite(j))return Math.max(0,j)}let _=Number(u.currentEpoch),y=Number(u.epochTarget??f.epochTarget),$=Date.parse(f.startedAt||"");if(!Number.isFinite(_)||_<=0||!Number.isFinite(y)||y<=_||!Number.isFinite($))return null;let l=Math.max(0,(Date.now()-$)/1000);if(l<=0)return null;return Math.max(0,l/_*(y-_))}function _G(f){let u=f.progress||{},_=Number(u.epochPerHour);if(Number.isFinite(_)&&_>0)return _;let y=Date.parse(f.startedAt||""),$=["succeeded","failed","canceled"].includes(f.status)?Date.parse(f.finishedAt||""):Date.now();if(!Number.isFinite(y)||!Number.isFinite($)||$<=y)return null;let l=Number(u.currentEpoch??f.epochTarget);if(!Number.isFinite(l)||l<=0)return null;return l/(($-y)/3600000)}function yG(f){if(f==="staged")return"待启动";if(f==="queued")return"排队中";if(f==="running")return"训练中";if(f==="succeeded")return"已完成";if(f==="failed")return"失败";if(f==="canceled")return"已取消";return f||"unknown"}function $G(f,u,_){return{name:f,path:u,depth:_,count:0,children:[],project:null}}function BN(f){let u=$G("","",-1);for(let y of f){let l=String(y?.projectPath||"").replace(/\\/g,"/").split("/").filter(Boolean);if(l.length===0)continue;let j=u,J=[];for(let[F,A]of l.entries()){J.push(A);let U=J.join("/"),z=j.children.find((W)=>W.path===U);if(!z)z=$G(A,U,F),j.children.push(z);if(F===l.length-1)z.project=y;j=z}}let _=(y)=>{let $=y.children.reduce((l,j)=>l+_(j),0);return y.count=(y.project?1:0)+$,y.children.sort((l,j)=>{if(Boolean(l.project)!==Boolean(j.project))return l.project?1:-1;return l.name.localeCompare(j.name,"zh-CN",{numeric:!0,sensitivity:"base"})}),y.count};return _(u),u}function wN(f){let u=Lu(f.data);return Lu(u.project).projectPath?Lu(u.project):u}function DN(f){return Lu(Lu(f.data).job)}function lG({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((h)=>h.id==="met-nonlinear")||null,[$,l]=Xj({loading:!1,actionBusy:!1,error:"",health:null,summary:null,queue:null,projects:null,history:null,images:null,refreshedAt:null}),[j,J]=Xj({loading:!1,error:"",kind:"",key:"",title:"",data:null}),[F,A]=Xj(()=>({activeTab:"projects",selectedProjects:{},expandedProjectDirs:{},sourceProject:"",forkCount:1,forkEpochs:200,forkPrefix:`ui_fork_${Date.now()}`,maxConcurrency:3,targetGpuName:"2080 Ti",actionMessage:""}));function U(h){A((g)=>({...g,...h}))}async function z(h=F.activeTab){if(!y)return;l((g)=>({...g,loading:!0,error:""}));try{let g=[["health",wf(`${_}/microservices/met-nonlinear/health`)],["summary",wf(bu(_,"/api/summary"))]];if(h==="projects")g.push(["projectsRoot",wf(bu(_,"/api/projects?root=projects&limit=500"))]),g.push(["exProjectsRoot",wf(bu(_,"/api/projects?root=ex_projects&limit=500"))]);if(h==="current"||h==="completed"||h==="failed")g.push(["queue",wf(bu(_,"/api/queue"))]);if(h==="completed"||h==="failed")g.push(["history",wf(bu(_,"/api/history"))]);if(h==="gpu")g.push(["images",wf(bu(_,"/api/images"))]);let I=Object.fromEntries(await Promise.all(g.map(async([lf,Af])=>[lf,await Af]))),$f={loading:!1,actionBusy:!1,error:"",health:I.health,summary:I.summary,refreshedAt:new Date};if(I.projectsRoot||I.exProjectsRoot){let{projectsRoot:lf,exProjectsRoot:Af}=I;$f.projects={ok:lf?.ok!==!1&&Af?.ok!==!1,roots:[{root:"projects",count:h4(lf).length},{root:"ex_projects",count:h4(Af).length}],projects:[...h4(lf),...h4(Af)]}}if(I.queue)$f.queue=I.queue;if(I.history)$f.history=I.history;if(I.images)$f.images=I.images;l((lf)=>({...lf,...$f}))}catch(g){l((I)=>({...I,loading:!1,actionBusy:!1,error:Mf(g,"MET Nonlinear 加载失败")}))}}async function W(h,g){l((I)=>({...I,actionBusy:!0,error:""})),U({actionMessage:`${h}...`});try{let I=await g();U({actionMessage:I||`${h}完成`}),await z()}catch(I){l(($f)=>({...$f,actionBusy:!1,error:Mf(I,`${h}失败`)}))}}async function K(){await W("保存并发设置",async()=>{await wf(bu(_,"/api/queue/settings"),{method:"PUT",body:JSON.stringify({maxConcurrency:Number(F.maxConcurrency),targetGpuName:F.targetGpuName})})})}function q(){return Object.entries(F.selectedProjects).filter(([,h])=>h).map(([h])=>h)}async function E(){let h=q();if(h.length===0)throw Error("请先选择至少一个 project");await W("加入待启动队列",async()=>{await wf(bu(_,"/api/queue"),{method:"POST",body:JSON.stringify({projectPaths:h,maxConcurrency:Number(F.maxConcurrency),targetGpuName:F.targetGpuName,start:!1})}),U({activeTab:"current",selectedProjects:{}})})}async function O(){let h=F.sourceProject||P[0]?.projectPath;if(!h)throw Error("请先选择源 project");await W("Fork Project",async()=>{let g=await wf(bu(_,"/api/projects/fork"),{method:"POST",body:JSON.stringify({sourceProject:h,count:Number(F.forkCount),epochs:Number(F.forkEpochs),prefix:F.forkPrefix})}),I=Array.isArray(g.projectPaths)?g.projectPaths:[],$f=I.reduce((lf,Af)=>{return lf[Af]=!0,lf},{...F.selectedProjects});return U({selectedProjects:$f}),`已 fork ${I.length} 个 project,并已自动勾选;请确认后点击加入待启动队列。`})}async function G(){await W("启动队列",async()=>{await wf(bu(_,"/api/queue/start"),{method:"POST",body:JSON.stringify({maxConcurrency:Number(F.maxConcurrency),targetGpuName:F.targetGpuName})}),U({activeTab:"current"})})}async function H(h){await W("取消任务",async()=>{await wf(bu(_,`/api/jobs/${encodeURIComponent(h.id)}/cancel`),{method:"POST",body:JSON.stringify({})})})}async function Z(h){let g=String(h?.projectPath||"");if(!g)return;J({loading:!0,error:"",kind:"project",key:g,title:g,data:null});try{let I=await wf(bu(_,`/api/projects/config?path=${encodeURIComponent(g)}`));J({loading:!1,error:"",kind:"project",key:g,title:g,data:I})}catch(I){J({loading:!1,error:Mf(I,"Project 详情加载失败"),kind:"project",key:g,title:g,data:null})}}async function V(h){let g=String(h?.id||"");if(!g)return;J({loading:!0,error:"",kind:"job",key:g,title:h.projectPath||g,data:null});try{let I=await wf(bu(_,`/api/jobs/${encodeURIComponent(g)}`));J({loading:!1,error:"",kind:"job",key:g,title:I?.job?.projectPath||h.projectPath||g,data:I})}catch(I){J({loading:!1,error:Mf(I,"Job 详情加载失败"),kind:"job",key:g,title:h.projectPath||g,data:null})}}if(KN(()=>{z(F.activeTab)},[y?.id,y?.runtime?.providerStatus,F.activeTab]),!y)return b($_,{title:"MET Nonlinear 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=met-nonlinear"});let L=HN(y),M=VN(y),N=EN(y),D=ON($.queue?.queue||$.summary?.queue),x=LN($.health,$.queue),c=$.health?.targetGpu||$.summary?.targetGpu||x.find((h)=>String(h.name||"").includes("2080")),v=$.images?.mlImage||$.health?.image||{},C=XN($.queue),P=NN($.projects),w=BN(P),r=F.sourceProject||P[0]?.projectPath||"",S=C.filter((h)=>["staged","queued","running"].includes(h.status)),T=C.filter((h)=>h.status==="succeeded"),Y=C.filter((h)=>["failed","canceled"].includes(h.status)),R=Array.isArray($.history?.jobs)?$.history.jobs.slice(0,120):[],m=[{id:"projects",label:"项目库",count:P.length},{id:"current",label:"当前队列",count:S.length||Number(D.staged||0)+Number(D.queued||0)+Number(D.running||0)},{id:"completed",label:"已完成",count:T.length||Number(D.succeeded||0)},{id:"failed",label:"失败诊断",count:Y.length||Number(D.failed||0)+Number(D.canceled||0)},{id:"gpu",label:"GPU/镜像",count:x.length}];function p(h,g){if(h.length===0)return b($_,{title:g==="current"?"当前队列为空":"暂无记录",text:g==="current"?"从项目库选择或 fork project 后先加入待启动队列,再启动队列。":"终态任务会显示耗时、exit code 和失败诊断。"});return b("div",{className:"table-wrap met-job-table"},b("table",null,b("thead",null,b("tr",null,b("th",null,"状态"),b("th",null,"Project"),b("th",null,"Epoch"),b("th",null,"速度"),b("th",null,"ETA/耗时"),b("th",null,"GPU"),b("th",null,"Exit"),b("th",null,"更新时间"),b("th",null,"操作"))),b("tbody",null,h.map((I)=>{let $f=I.progress||{},lf=["staged","queued","running"].includes(I.status),Af=j.kind==="job"&&j.key===I.id;return b("tr",{key:I.id,className:`met-click-row ${Af?"active":""}`,onClick:()=>V(I),"data-testid":`met-job-row-${b4(I.id)}`},b("td",null,b(b6,{status:I.status},yG(I.status))),b("td",null,b("button",{type:"button",className:"met-inline-link",onClick:(Yf)=>{Yf.stopPropagation(),V(I)}},I.projectPath),b("code",null,I.id)),b("td",null,b("span",null,`${$f.currentEpoch??"--"} / ${$f.epochTarget??I.epochTarget??"--"}`),b("div",{className:"met-progress"},b("span",{style:{width:v6($f.progressPercent)}}))),b("td",null,b("strong",null,v4(_G(I)))),b("td",null,I.status==="succeeded"||I.status==="failed"||I.status==="canceled"?uG(I):I.status==="running"?`ETA ${Lj(YN(I))}`:"--"),b("td",null,I.gpuName||"--"),b("td",null,I.exitCode??"--"),b("td",null,ZN(I.updatedAt)),b("td",null,lf?b("button",{type:"button",className:"ghost-btn mini",onClick:(Yf)=>{Yf.stopPropagation(),H(I)},disabled:$.actionBusy},"取消"):null,b(p3,{title:`MET Job ${I.id}`,data:I,onOpen:u,testId:`raw-met-job-${I.id}`})))}))))}function n(){return b("div",{className:"met-queue-summary","data-testid":"met-current-summary"},b(b6,{status:"staged"},`待启动 ${D.staged??0}`),b(b6,{status:"queued"},`排队中 ${D.queued??0}`),b(b6,{status:"running"},`训练中 ${D.running??0}`),b("span",null,`最大并发 ${$.summary?.queue?.maxConcurrency??$.queue?.queue?.maxConcurrency??F.maxConcurrency}`),b("span",null,`目标 GPU ${$.summary?.queue?.targetGpuName??$.queue?.queue?.targetGpuName??F.targetGpuName}`))}function _f(h,g){let I=F.expandedProjectDirs[h];return I===void 0?g<2:Boolean(I)}function t(h,g){let I=_f(h,g);U({expandedProjectDirs:{...F.expandedProjectDirs,[h]:!I}})}function ff(h){let g=8+Math.max(0,h.depth)*16;if(Boolean(h.project)){let lf=h.project,Af=Boolean(F.selectedProjects[lf.projectPath]),Yf=j.kind==="project"&&j.key===lf.projectPath;return b("div",{key:h.path,className:`met-tree-row project ${Af?"selected":""} ${Yf?"active":""}`,style:{paddingLeft:g},onClick:()=>Z(lf),"data-testid":`met-project-node-${b4(lf.projectPath)}`},b("div",{className:"met-tree-name"},b("input",{type:"checkbox",checked:Af,onClick:(xf)=>xf.stopPropagation(),onChange:(xf)=>U({selectedProjects:{...F.selectedProjects,[lf.projectPath]:xf.target.checked}}),"data-testid":`met-project-checkbox-${b4(lf.projectPath)}`}),b("button",{type:"button",className:"met-inline-link project-path",onClick:(xf)=>{xf.stopPropagation(),Z(lf)}},h.name)),b("span",null,lf.useModel||"--"),b("span",null,lf.epochTrain??"--"),b("span",null,v6(lf.progress?.progressPercent)),b("span",null,v4(lf.progress?.epochPerHour)))}let $f=_f(h.path,h.depth);return b(I6.default.Fragment,{key:h.path},b("div",{className:"met-tree-row folder",style:{paddingLeft:g},"data-testid":`met-project-folder-${b4(h.path)}`},b("button",{type:"button",className:"met-tree-toggle",onClick:()=>t(h.path,h.depth),"aria-label":$f?`折叠 ${h.path}`:`展开 ${h.path}`},$f?"-":"+"),b("strong",null,h.name),b("span",{className:"met-tree-count"},`${h.count} projects`)),$f?h.children.map((lf)=>ff(lf)):null)}function Gf(h){return b("div",{className:"met-detail-kv"},h.map((g)=>b("div",{key:g.label,className:"met-detail-kv-item"},b("span",null,g.label),b("strong",null,h6(g.value)),g.hint?b("small",null,g.hint):null)))}function zf(h,g){return b("div",{className:"met-detail-section"},b("h3",null,h),Gf(g))}function jf(h){if(!Array.isArray(h)||h.length===0)return b($_,{title:"模型层未上报",text:"等待 data/model_info.json 或 compute_analysis.json 生成。"});return b("div",{className:"table-wrap met-layer-table"},b("table",null,b("thead",null,b("tr",null,b("th",null,"Layer"),b("th",null,"Type"),b("th",null,"Params"),b("th",null,"Trainable"),b("th",null,"Compute"))),b("tbody",null,h.slice(0,18).map((g,I)=>b("tr",{key:`${g.name||"layer"}-${I}`},b("td",null,g.name||`#${I+1}`),b("td",null,g.type||"--"),b("td",null,Yj(g.num_params)),b("td",null,g.trainable===void 0?"--":String(Boolean(g.trainable))),b("td",null,Yj(g.compute?.total??g.estimated_cost?.weighted_units?.total)))))))}function Wf(h){let g=Array.isArray(h)?h:[];if(g.length===0)return b($_,{title:"data/ 暂无文件",text:"训练或评估完成后会生成 training_state、metrics、model_info 等文件。"});return b("div",{className:"met-file-chip-grid"},g.slice(0,48).map((I)=>b("span",{key:I},I)),g.length>48?b("span",null,`+${g.length-48}`):null)}function Vf(h){let g=String(h||"").replace(/\x1b\[[0-9;]*[A-Za-z]/g,"").split(/\r?\n/).map((I)=>I.trim()).filter(Boolean).slice(-12);if(g.length===0)return b($_,{title:"暂无日志尾部",text:"该任务未上报 logTail 或日志已轮转。"});return b("div",{className:"met-log-lines"},g.map((I,$f)=>b("div",{key:`${$f}-${I.slice(0,16)}`},I)))}function Zf(){if(j.loading)return b("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},b($_,{title:"详情加载中",text:j.title||"正在读取 D601 data/ 和 config.json"}));if(j.error)return b("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},b(H0,{error:j.error,wide:!0}));if(!j.data)return b("section",{className:"met-detail-panel muted","data-testid":"met-detail-panel"},b($_,{title:"选择一个项目或任务查看详情",text:"项目库、当前队列、已完成和失败诊断中的行都可以点击;默认只展示结构化字段,原始 JSON 需显式点击按钮。"}));let h=wN(j),g=DN(j),I=Lu(h.config),$f=Lu(h.progress||g.progress),lf=Lu(h.data),Af=Lu(h.metrics||lf.metrics||$f.trainingInfo?.evaluation_metrics),Yf=Lu(lf.trainingInfo||$f.trainingInfo),xf=Lu(lf.trainingState),sf=Lu(h.model||lf.model),j0=Array.isArray(sf.modelSummary)&&sf.modelSummary.length>0?sf.modelSummary:sf.computeLayers,u0=Lu(Yf.evaluation_metrics),D0=j.kind==="job"?"训练任务详情":"Project 详情";return b("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},b("div",{className:"panel-head compact"},b("div",null,b("p",{className:"panel-eyebrow"},j.kind==="job"?"Job + Project Detail":"Project Library Detail"),b("h2",null,D0),b("code",null,h.projectPath||g.projectPath||j.title)),b("div",{className:"panel-actions"},b(p3,{title:`MET ${D0}`,data:j.data,onOpen:u,testId:"raw-met-detail"}))),j.kind==="job"?zf("任务状态",[{label:"Job ID",value:g.id},{label:"状态",value:yG(g.status)},{label:"GPU",value:g.gpuName},{label:"Exit Code",value:g.exitCode},{label:"耗时",value:uG(g)},{label:"训练速度",value:v4(_G({...g,progress:$f}))}]):null,zf("config.json",[{label:"use_model",value:I.use_model},{label:"epoch_train",value:I.epoch_train},{label:"step_per_epoch",value:I.step_per_epoch},{label:"learning_rate",value:I.learning_rate},{label:"using_gpu",value:I.using_gpu},{label:"use_points",value:I.use_points},{label:"sample_rate",value:I.sample_rate},{label:"time_clipped_s",value:I.time_clipped_s},{label:"H_UNITS",value:I.H_UNITS},{label:"INNER_KAN_UNITS",value:I.INNER_KAN_UNITS},{label:"INNER_KAN_LAYERS",value:I.INNER_KAN_LAYERS},{label:"GRID_SIZE",value:I.GRID_SIZE},{label:"SPLINE_ORDER",value:I.SPLINE_ORDER},{label:"USE_FAST_MODEL",value:I.USE_FAST_MODEL},{label:"IIR_TRAINABLE",value:I.IIR_TRAINABLE}]),zf("data/ 训练状态",[{label:"Epoch",value:`${$f.currentEpoch??xf.current_epoch??xf.completed_epoch??"--"} / ${$f.epochTarget??I.epoch_train??"--"}`},{label:"Progress",value:v6($f.progressPercent)},{label:"Last Loss",value:$f.lastLoss??xf.loss},{label:"Last Val Loss",value:$f.lastValLoss??xf.val_loss},{label:"Min Loss",value:Yf.min_loss??xf.min_loss},{label:"Min Val Loss",value:Yf.min_val_loss??xf.min_val_loss},{label:"Log Lines",value:$f.logLineCount},{label:"ETA",value:Lj($f.etaSeconds??xf.remaining_time)},{label:"训练速度",value:v4($f.epochPerHour??xf.smoothed_speed)},{label:"Training Alive",value:xf.training_alive}]),zf("模型参数",[{label:"Model Type",value:sf.modelType??I.use_model},{label:"Total Params",value:sf.totalParams,hint:sf.totalParams===null||sf.totalParams===void 0?"未上报":"data/model_info.json"},{label:"Trainable",value:sf.trainableParams},{label:"Non-trainable",value:sf.nonTrainableParams},{label:"Compute Cost",value:sf.computeCost},{label:"Estimate Status",value:sf.estimateStatus},{label:"Unsupported Layers",value:sf.unsupportedLayerCount}]),zf("指标",[{label:"train_loss",value:Af.train_loss??u0.train_loss},{label:"val_loss",value:Af.val_loss??u0.val_loss},{label:"train_mae",value:Af.train_mae??u0.train_mae},{label:"val_mae",value:Af.val_mae??u0.val_mae},{label:"train_afmae",value:Af.train_afmae??u0.train_afmae},{label:"val_afmae",value:Af.val_afmae??u0.val_afmae},{label:"freq_drift_hz",value:Af.freq_drift_hz},{label:"sens_drift_percent",value:Af.sens_drift_percent},{label:"linearity_percent",value:Af.linearity_percent},{label:"weights_source",value:Af.weights_source??u0.weights_source},{label:"lr min/mean/max",value:`${h6(Yf.learning_rate_min)} / ${h6(Yf.learning_rate_mean)} / ${h6(Yf.learning_rate_max)}`}]),b("div",{className:"met-detail-section"},b("h3",null,"模型层"),jf(j0)),b("div",{className:"met-detail-section"},b("h3",null,"data/ 文件"),Wf(lf.files)),j.kind==="job"?b("div",{className:"met-detail-section"},b("h3",null,"日志尾部"),Vf(Lu(j.data).logTail)):null)}return b("div",{className:"met-page","data-testid":"met-nonlinear-page"},b(Nj,{title:"MET Nonlinear 训练编排",eyebrow:"D601 GPU 用户服务",actions:b("div",{className:"panel-actions"},b("button",{type:"button",className:"ghost-btn",onClick:z,disabled:$.loading,"data-testid":"met-refresh-button"},$.loading?"刷新中":"刷新"),b(p3,{title:"MET Nonlinear 用户服务",data:y,onOpen:u,testId:"raw-met-service"}))},b("div",{className:"findjob-hero"},b("div",null,b("div",{className:"node-version-line"},b(b6,{status:L.providerStatus==="online"?"online":"warn"},L.providerStatus||"unknown"),b("span",null,y.providerId),b("span",null,N.public?"公网暴露":"仅 UniDesk frontend 代理访问")),b("p",{className:"muted paragraph"},y.description)),b("div",{className:"microservice-ref-card"},b("span",null,"Repo"),b("strong",null,M.url||"--"),b("code",null,M.commitId||"--")),b("div",{className:"microservice-ref-card"},b("span",null,"D601 Docker"),b("strong",null,`${N.nodeBindHost||"--"}:${N.nodePort||"--"}`),b("code",null,`${M.composeFile||"--"} / ${M.containerName||"--"}`))),b(H0,{error:$.error,wide:!0}),F.actionMessage?b("div",{className:"met-action-log","data-testid":"met-action-message"},F.actionMessage):null),b("div",{className:"met-grid"},b(Nj,{title:"核心状态",eyebrow:$.refreshedAt?`Updated ${qN($.refreshedAt)}`:"Queue + GPU"},b("div",{className:"metric-grid"},b(I_,{label:"Staged",value:D.staged??0,hint:"加入队列未开始",tone:Number(D.staged||0)>0?"warn":""}),b(I_,{label:"Queued",value:D.queued??0,hint:"排队等待调度",tone:Number(D.queued||0)>0?"warn":""}),b(I_,{label:"Running",value:D.running??0,hint:`max ${$.summary?.queue?.maxConcurrency??$.queue?.queue?.maxConcurrency??"--"}`,tone:Number(D.running||0)>0?"ok":""}),b(I_,{label:"Succeeded",value:D.succeeded??0,hint:"已完成"}),b(I_,{label:"Failed",value:D.failed??0,hint:"需要诊断",tone:Number(D.failed||0)>0?"warn":""}),b(I_,{label:"2080Ti Free",value:c?v6(Number(c.freeRatio)*100):"--",hint:c?`${c.memoryFreeMiB}/${c.memoryTotalMiB} MiB`:"等待 GPU 上报"}),b(I_,{label:"ML Image",value:v.present?"READY":"MISSING",hint:v.image||"met-nonlinear-ml:tf26",tone:v.present?"ok":"warn"}),b(I_,{label:"Health",value:$.health?.ok?"OK":"--",hint:"D601 /health"}))),b(Nj,{title:"队列控制",eyebrow:"Downloader-like staging"},b("div",{className:"met-control-strip"},b("label",null,"最大并发",b("input",{type:"number",min:1,max:16,value:F.maxConcurrency,"data-testid":"met-max-concurrency-input",onChange:(h)=>U({maxConcurrency:h.target.value})})),b("label",null,"目标 GPU",b("input",{value:F.targetGpuName,"data-testid":"met-target-gpu-input",onChange:(h)=>U({targetGpuName:h.target.value})})),b("button",{type:"button",className:"ghost-btn",onClick:K,disabled:$.actionBusy,"data-testid":"met-save-settings-button"},"保存设置"),b("button",{type:"button",className:"primary-btn",onClick:G,disabled:$.actionBusy||Number(D.staged||0)===0,"data-testid":"met-start-queue-button"},"启动队列")),b("p",{className:"muted paragraph"},"Project 先进入待启动队列,不会立即训练;点击启动队列后才切换为排队中,并由 D601 scheduler 按最大并发和 2080Ti 显存策略调度。")),b("section",{className:"panel met-workspace"},b("div",{className:"met-tabs",role:"tablist"},m.map((h)=>b("button",{key:h.id,type:"button",className:F.activeTab===h.id?"active":"",onClick:()=>U({activeTab:h.id}),"data-testid":`met-tab-${h.id}`},`${h.label} ${h.count}`))),b("div",{className:"panel-body"},F.activeTab==="projects"?b("div",{className:"met-form-grid","data-testid":"met-projects-pane"},b("div",{className:"met-fork-card"},b("h3",null,"Fork Project"),b("label",null,"源 Project",b("select",{value:r,"data-testid":"met-source-project-select",onChange:(h)=>U({sourceProject:h.target.value})},P.map((h)=>b("option",{key:h.projectPath,value:h.projectPath},`${h.projectPath} · ${h.useModel||"model?"}`)))),b("label",null,"Fork 数量",b("input",{type:"number",min:1,max:100,value:F.forkCount,"data-testid":"met-fork-count-input",onChange:(h)=>U({forkCount:h.target.value})})),b("label",null,"训练轮数",b("input",{type:"number",min:1,max:1e5,value:F.forkEpochs,"data-testid":"met-fork-epochs-input",onChange:(h)=>U({forkEpochs:h.target.value})})),b("label",null,"目标前缀",b("input",{value:F.forkPrefix,"data-testid":"met-fork-prefix-input",onChange:(h)=>U({forkPrefix:h.target.value})})),b("button",{type:"button",className:"primary-btn",onClick:O,disabled:$.actionBusy||!r,"data-testid":"met-fork-button"},"Fork Project"),b("p",{className:"muted paragraph"},"Fork 只创建新 Project 并自动勾选,不会直接训练;需要在右侧确认后加入待启动队列。")),b("div",{className:"met-project-list"},b("div",{className:"panel-head compact"},b("div",null,b("p",{className:"panel-eyebrow"},`Existing Projects · ${($.projects?.roots||[]).map((h)=>`${h.root} ${h.count}`).join(" / ")}`),b("h2",null,"选择已有 Project")),b("button",{type:"button",className:"ghost-btn",onClick:E,disabled:$.actionBusy||q().length===0,"data-testid":"met-stage-selected-button"},`加入待启动队列 (${q().length})`)),P.length===0?b($_,{title:"暂无 project",text:"等待 D601 返回 /api/projects"}):b("div",{className:"met-project-table","data-testid":"met-project-tree"},b("div",{className:"met-tree-header"},b("span",null,"文件树 Project"),b("span",null,"Model"),b("span",null,"Epochs"),b("span",null,"Progress"),b("span",null,"速度")),w.children.map((h)=>ff(h)))),Zf()):null,F.activeTab==="current"?b("div",{"data-testid":"met-current-pane"},n(),p(S,"current"),Zf(),b("div",{className:"panel-actions inline-actions"},b(p3,{title:"MET Queue",data:$.queue,onOpen:u,testId:"raw-met-queue"}))):null,F.activeTab==="completed"?b("div",{"data-testid":"met-completed-pane"},p(T.length>0?T:R.filter((h)=>h.status==="succeeded"),"completed"),Zf()):null,F.activeTab==="failed"?b("div",{"data-testid":"met-failed-pane"},p(Y.length>0?Y:R.filter((h)=>["failed","canceled"].includes(h.status)),"failed"),Zf(),b("div",{className:"panel-actions inline-actions"},b(p3,{title:"MET History",data:$.history,onOpen:u,testId:"raw-met-history"}))):null,F.activeTab==="gpu"?b("div",{className:"met-gpu-pane","data-testid":"met-gpu-pane"},x.length===0?b($_,{title:"暂无 GPU 上报",text:"等待 D601 met-nonlinear-ts 或 ML image 提供 nvidia-smi 数据"}):b("div",{className:"table-wrap"},b("table",null,b("thead",null,b("tr",null,b("th",null,"Index"),b("th",null,"Name"),b("th",null,"Free"),b("th",null,"Policy"))),b("tbody",null,x.map((h)=>b("tr",{key:h.index},b("td",null,h.index),b("td",null,h.name),b("td",null,`${h.memoryFreeMiB} / ${h.memoryTotalMiB} MiB`,b("div",{className:"met-progress"},b("span",{style:{width:v6(Number(h.freeRatio)*100)}}))),b("td",null,String(h.name||"").includes("2080")?"target 2080Ti, <20% 限制并发":"non-target")))))),b("div",{className:"panel-actions inline-actions"},b(p3,{title:"MET Images",data:$.images,onOpen:u,testId:"raw-met-images"}))):null))))}var c4=[{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:"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:"codex-queue",label:"Codex Queue"},{id:"project-manager",label:"Project Manager"}]},{id:"config",label:"系统配置",code:"CFG",tabs:[{id:"topology",label:"连接拓扑"},{id:"auth",label:"认证策略"},{id:"security",label:"安全边界"}]}],m3=Object.fromEntries(c4.map((f)=>[f.id,f.tabs[0]?.id??""]));function TN(f){let u=String(f||"").trim();if(!u)return"";try{return decodeURIComponent(u)}catch{return u}}function I4(f){let u=String(f||"/"),[_]=u.split(/[?#]/u,1);if(_==="/")return"/";let $=`/${_.split("/").map(TN).filter(Boolean).join("/")}`;return $.endsWith("/")?$:`${$}/`}function MN(f){let u=2166136261;for(let _ of f)u^=_.charCodeAt(0),u=Math.imul(u,16777619);return Math.abs(u>>>0).toString(36)}function Bj(f){return String(f||"").normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"")}function jG(f){return String(f||"").trim().toLowerCase().replace(/[\s/\\?#%]+/gu,"-").replace(/-+/gu,"-").replace(/^-+|-+$/gu,"")}function JG(f){let u=Bj(f.routeSegment||"")||jG(f.routeSegment||"");if(u)return u;let _=Bj(f.id||"");if(_)return _;let y=Bj(f.label||"")||jG(f.label||"");if(y)return y;return`route-${MN(JSON.stringify(f))}`}function wj(f,u){return`${f}:${u}`}function FG(f){let u=f.map((F)=>{let A=JG(F);return{...F,routeSegment:A,tabs:F.tabs.map((U)=>({...U,routeSegment:JG(U)}))}}),_={},y={},$={},l=u.map((F)=>{let A=F.tabs[0]?.id??"";$[F.id]=A;let U=F.tabs.map((K)=>{let q=`/${F.routeSegment}/${K.routeSegment}/`,E=[q],O={moduleId:F.id,tabId:K.id};for(let G of E)_[I4(G)]=O;return y[wj(F.id,K.id)]=q,{...K,canonicalPath:q,aliases:E}}),z=`/${F.routeSegment}/`,W={moduleId:F.id,tabId:A};return _[I4(z)]=W,{...F,routeSegment:F.routeSegment,canonicalPath:z,tabs:U}}),j=l[0],J={moduleId:j?.id||"",tabId:j?.tabs[0]?.id||""};return _["/"]=J,{modules:l,moduleById:Object.fromEntries(l.map((F)=>[F.id,F])),defaultActiveTabs:$,routeMap:_,canonicalPathByTarget:y,fallbackTarget:J}}function Dj(f,u){return f.routeMap[I4(u)]||f.fallbackTarget}function c6(f,u,_){return f.canonicalPathByTarget[wj(u,_)]||f.canonicalPathByTarget[wj(f.fallbackTarget.moduleId,f.fallbackTarget.tabId)]||"/"}function QG(f,u){let _=f.routeMap[I4(u)];if(!_)return null;return c6(f,_.moduleId,_.tabId)}var fy=rf(I0(),1);var o=rf(zG(),1),d=rf(I0(),1);function Y0(f){if(typeof f==="string"||typeof f==="number")return""+f;let u="";if(Array.isArray(f)){for(let _=0,y;_{}};function KG(){for(var f=0,u=arguments.length,_={},y;f=0)y=_.slice($+1),_=_.slice(0,$);if(_&&!u.hasOwnProperty(_))throw Error("unknown type: "+_);return{type:_,name:y}})}m4.prototype=KG.prototype={constructor:m4,on:function(f,u){var _=this._,y=bN(f+"",_),$,l=-1,j=y.length;if(arguments.length<2){while(++l0)for(var _=Array($),y=0,$,l;y<$;++y)_[y]=arguments[y+2];if(!this._.hasOwnProperty(f))throw Error("unknown type: "+f);for(l=this._[f],y=0,$=l.length;y<$;++y)l[y].value.apply(u,_)},apply:function(f,u,_){if(!this._.hasOwnProperty(f))throw Error("unknown type: "+f);for(var y=this._[f],$=0,l=y.length;$=0&&(u=f.slice(0,_))!=="xmlns")f=f.slice(_+1);return Tj.hasOwnProperty(u)?{space:Tj[u],local:f}:f}function Mj(f){let u;while(u=f.sourceEvent)f=u;return f}function lu(f,u){if(f=Mj(f),u===void 0)u=f.currentTarget;if(u){var _=u.ownerSVGElement||u;if(_.createSVGPoint){var y=_.createSVGPoint();return y.x=f.clientX,y.y=f.clientY,y=y.matrixTransform(u.getScreenCTM().inverse()),[y.x,y.y]}if(u.getBoundingClientRect){var $=u.getBoundingClientRect();return[f.clientX-$.left-u.clientLeft,f.clientY-$.top-u.clientTop]}}return[f.pageX,f.pageY]}function IN(){}function c_(f){return f==null?IN:function(){return this.querySelector(f)}}function Sj(f){if(typeof f!=="function")f=c_(f);for(var u=this._groups,_=u.length,y=Array(_),$=0;$<_;++$)for(var l=u[$],j=l.length,J=y[$]=Array(j),F,A,U=0;U=Z)Z=H+1;while(!(L=O[Z])&&++Z=0;)if(j=y[$]){if(l&&j.compareDocumentPosition(l)^4)l.parentNode.insertBefore(j,l);l=j}return this}function kj(f){if(!f)f=eN;function u(z,W){return z&&W?f(z.__data__,W.__data__):!z-!W}for(var _=this._groups,y=_.length,$=Array(y),l=0;lu?1:f>=u?0:NaN}function ij(){var f=arguments[0];return arguments[0]=this,f.apply(null,arguments),this}function gj(){return Array.from(this)}function nj(){for(var f=this._groups,u=0,_=f.length;u<_;++u)for(var y=f[u],$=0,l=y.length;$1?this.each((u==null?jL:typeof u==="function"?FL:JL)(f,u,_==null?"":_)):p_(this.node(),f)}function p_(f,u){return f.style.getPropertyValue(u)||k6(f).getComputedStyle(f,null).getPropertyValue(u)}function QL(f){return function(){delete this[f]}}function AL(f,u){return function(){this[f]=u}}function UL(f,u){return function(){var _=u.apply(this,arguments);if(_==null)delete this[f];else this[f]=_}}function ej(f,u){return arguments.length>1?this.each((u==null?QL:typeof u==="function"?UL:AL)(f,u)):this.node()[f]}function ZG(f){return f.trim().split(/^|\s+/)}function fJ(f){return f.classList||new qG(f)}function qG(f){this._node=f,this._names=ZG(f.getAttribute("class")||"")}qG.prototype={add:function(f){var u=this._names.indexOf(f);if(u<0)this._names.push(f),this._node.setAttribute("class",this._names.join(" "))},remove:function(f){var u=this._names.indexOf(f);if(u>=0)this._names.splice(u,1),this._node.setAttribute("class",this._names.join(" "))},contains:function(f){return this._names.indexOf(f)>=0}};function HG(f,u){var _=fJ(f),y=-1,$=u.length;while(++y<$)_.add(u[y])}function EG(f,u){var _=fJ(f),y=-1,$=u.length;while(++y<$)_.remove(u[y])}function WL(f){return function(){HG(this,f)}}function zL(f){return function(){EG(this,f)}}function GL(f,u){return function(){(u.apply(this,arguments)?HG:EG)(this,f)}}function uJ(f,u){var _=ZG(f+"");if(arguments.length<2){var y=fJ(this.node()),$=-1,l=_.length;while(++$=0)_=u.slice(y+1),u=u.slice(0,y);return{type:u,name:_}})}function SL(f){return function(){var u=this.__on;if(!u)return;for(var _=0,y=-1,$=u.length,l;_<$;++_)if(l=u[_],(!f.type||l.type===f.type)&&l.name===f.name)this.removeEventListener(l.type,l.listener,l.options);else u[++y]=l;if(++y)u.length=y;else delete this.__on}}function rL(f,u,_){return function(){var y=this.__on,$,l=TL(u);if(y){for(var j=0,J=y.length;j()=>f;function t6(f,{sourceEvent:u,subject:_,target:y,identifier:$,active:l,x:j,y:J,dx:F,dy:A,dispatch:U}){Object.defineProperties(this,{type:{value:f,enumerable:!0,configurable:!0},sourceEvent:{value:u,enumerable:!0,configurable:!0},subject:{value:_,enumerable:!0,configurable:!0},target:{value:y,enumerable:!0,configurable:!0},identifier:{value:$,enumerable:!0,configurable:!0},active:{value:l,enumerable:!0,configurable:!0},x:{value:j,enumerable:!0,configurable:!0},y:{value:J,enumerable:!0,configurable:!0},dx:{value:F,enumerable:!0,configurable:!0},dy:{value:A,enumerable:!0,configurable:!0},_:{value:U}})}t6.prototype.on=function(){var f=this._.on.apply(this._,arguments);return f===this._?this:f};function mL(f){return!f.ctrlKey&&!f.button}function kL(){return this.parentNode}function iL(f,u){return u==null?{x:f.x,y:f.y}:u}function gL(){return navigator.maxTouchPoints||"ontouchstart"in this}function s6(){var f=mL,u=kL,_=iL,y=gL,$={},l=xy("start","drag","end"),j=0,J,F,A,U,z=0;function W(V){V.on("mousedown.drag",K).filter(y).on("touchstart.drag",O).on("touchmove.drag",G,XG).on("touchend.drag touchcancel.drag",H).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function K(V,L){if(U||!f.call(this,V,L))return;var M=Z(this,u.call(this,V,L),V,L,"mouse");if(!M)return;C0(V.view).on("mousemove.drag",q,vy).on("mouseup.drag",E,vy),g3(V.view),g4(V),A=!1,J=V.clientX,F=V.clientY,M("start",V)}function q(V){if(j_(V),!A){var L=V.clientX-J,M=V.clientY-F;A=L*L+M*M>z}$.mouse("drag",V)}function E(V){C0(V.view).on("mousemove.drag mouseup.drag",null),g6(V.view,A),j_(V),$.mouse("end",V)}function O(V,L){if(!f.call(this,V,L))return;var M=V.changedTouches,N=u.call(this,V,L),D=M.length,x,c;for(x=0;x>8&15|u>>4&240,u>>4&15|u&240,(u&15)<<4|u&15,1):_===8?n4(u>>24&255,u>>16&255,u>>8&255,(u&255)/255):_===4?n4(u>>12&15|u>>8&240,u>>8&15|u>>4&240,u>>4&15|u&240,((u&15)<<4|u&15)/255):null):(u=tL.exec(f))?new Yu(u[1],u[2],u[3],1):(u=sL.exec(f))?new Yu(u[1]*255/100,u[2]*255/100,u[3]*255/100,1):(u=oL.exec(f))?n4(u[1],u[2],u[3],u[4]):(u=aL.exec(f))?n4(u[1]*255/100,u[2]*255/100,u[3]*255/100,u[4]):(u=dL.exec(f))?TG(u[1],u[2]/100,u[3]/100,1):(u=eL.exec(f))?TG(u[1],u[2]/100,u[3]/100,u[4]):NG.hasOwnProperty(f)?BG(NG[f]):f==="transparent"?new Yu(NaN,NaN,NaN,0):null}function BG(f){return new Yu(f>>16&255,f>>8&255,f&255,1)}function n4(f,u,_,y){if(y<=0)f=u=_=NaN;return new Yu(f,u,_,y)}function _Y(f){if(!(f instanceof e6))f=E1(f);if(!f)return new Yu;return f=f.rgb(),new Yu(f.r,f.g,f.b,f.opacity)}function t3(f,u,_,y){return arguments.length===1?_Y(f):new Yu(f,u,_,y==null?1:y)}function Yu(f,u,_,y){this.r=+f,this.g=+u,this.b=+_,this.opacity=+y}o6(Yu,t3,KJ(e6,{brighter(f){return f=f==null?s4:Math.pow(s4,f),new Yu(this.r*f,this.g*f,this.b*f,this.opacity)},darker(f){return f=f==null?a6:Math.pow(a6,f),new Yu(this.r*f,this.g*f,this.b*f,this.opacity)},rgb(){return this},clamp(){return new Yu(hy(this.r),hy(this.g),hy(this.b),o4(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:wG,formatHex:wG,formatHex8:yY,formatRgb:DG,toString:DG}));function wG(){return`#${by(this.r)}${by(this.g)}${by(this.b)}`}function yY(){return`#${by(this.r)}${by(this.g)}${by(this.b)}${by((isNaN(this.opacity)?1:this.opacity)*255)}`}function DG(){let f=o4(this.opacity);return`${f===1?"rgb(":"rgba("}${hy(this.r)}, ${hy(this.g)}, ${hy(this.b)}${f===1?")":`, ${f})`}`}function o4(f){return isNaN(f)?1:Math.max(0,Math.min(1,f))}function hy(f){return Math.max(0,Math.min(255,Math.round(f)||0))}function by(f){return f=hy(f),(f<16?"0":"")+f.toString(16)}function TG(f,u,_,y){if(y<=0)f=u=_=NaN;else if(_<=0||_>=1)f=u=NaN;else if(u<=0)f=NaN;return new H1(f,u,_,y)}function SG(f){if(f instanceof H1)return new H1(f.h,f.s,f.l,f.opacity);if(!(f instanceof e6))f=E1(f);if(!f)return new H1;if(f instanceof H1)return f;f=f.rgb();var u=f.r/255,_=f.g/255,y=f.b/255,$=Math.min(u,_,y),l=Math.max(u,_,y),j=NaN,J=l-$,F=(l+$)/2;if(J){if(u===l)j=(_-y)/J+(_0&&F<1?0:j;return new H1(j,J,F,f.opacity)}function rG(f,u,_,y){return arguments.length===1?SG(f):new H1(f,u,_,y==null?1:y)}function H1(f,u,_,y){this.h=+f,this.s=+u,this.l=+_,this.opacity=+y}o6(H1,rG,KJ(e6,{brighter(f){return f=f==null?s4:Math.pow(s4,f),new H1(this.h,this.s,this.l*f,this.opacity)},darker(f){return f=f==null?a6:Math.pow(a6,f),new H1(this.h,this.s,this.l*f,this.opacity)},rgb(){var f=this.h%360+(this.h<0)*360,u=isNaN(f)||isNaN(this.s)?0:this.s,_=this.l,y=_+(_<0.5?_:1-_)*u,$=2*_-y;return new Yu(ZJ(f>=240?f-240:f+120,$,y),ZJ(f,$,y),ZJ(f<120?f+240:f-120,$,y),this.opacity)},clamp(){return new H1(MG(this.h),t4(this.s),t4(this.l),o4(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 f=o4(this.opacity);return`${f===1?"hsl(":"hsla("}${MG(this.h)}, ${t4(this.s)*100}%, ${t4(this.l)*100}%${f===1?")":`, ${f})`}`}}));function MG(f){return f=(f||0)%360,f<0?f+360:f}function t4(f){return Math.max(0,Math.min(1,f||0))}function ZJ(f,u,_){return(f<60?u+(_-u)*f/60:f<180?_:f<240?u+(_-u)*(240-f)/60:u)*255}function qJ(f,u,_,y,$){var l=f*f,j=l*f;return((1-3*f+3*l-j)*u+(4-6*l+3*j)*_+(1+3*f+3*l-3*j)*y+j*$)/6}function HJ(f){var u=f.length-1;return function(_){var y=_<=0?_=0:_>=1?(_=1,u-1):Math.floor(_*u),$=f[y],l=f[y+1],j=y>0?f[y-1]:2*$-l,J=y()=>f;function lY(f,u){return function(_){return f+_*u}}function jY(f,u,_){return f=Math.pow(f,_),u=Math.pow(u,_)-f,_=1/_,function(y){return Math.pow(f+y*u,_)}}function PG(f){return(f=+f)===1?d4:function(u,_){return _-u?jY(u,_,f):fl(isNaN(u)?_:u)}}function d4(f,u){var _=u-f;return _?lY(f,_):fl(isNaN(f)?u:f)}var Iy=function f(u){var _=PG(u);function y($,l){var j=_(($=t3($)).r,(l=t3(l)).r),J=_($.g,l.g),F=_($.b,l.b),A=d4($.opacity,l.opacity);return function(U){return $.r=j(U),$.g=J(U),$.b=F(U),$.opacity=A(U),$+""}}return y.gamma=f,y}(1);function CG(f){return function(u){var _=u.length,y=Array(_),$=Array(_),l=Array(_),j,J;for(j=0;j<_;++j)J=t3(u[j]),y[j]=J.r||0,$[j]=J.g||0,l[j]=J.b||0;return y=f(y),$=f($),l=f(l),J.opacity=1,function(F){return J.r=y(F),J.g=$(F),J.b=l(F),J+""}}}var JY=CG(HJ),FY=CG(EJ);function VJ(f,u){if(!u)u=[];var _=f?Math.min(u.length,f.length):0,y=u.slice(),$;return function(l){for($=0;$<_;++$)y[$]=f[$]*(1-l)+u[$]*l;return y}}function RG(f){return ArrayBuffer.isView(f)&&!(f instanceof DataView)}function xG(f,u){var _=u?u.length:0,y=f?Math.min(_,f.length):0,$=Array(y),l=Array(_),j;for(j=0;j_)if(l=u.slice(_,l),J[j])J[j]+=l;else J[++j]=l;if((y=y[0])===($=$[0]))if(J[j])J[j]+=$;else J[++j]=$;else J[++j]=null,F.push({i:j,x:ju(y,$)});_=NJ.lastIndex}if(_180)U+=360;else if(U-A>180)A+=360;W.push({i:z.push($(z)+"rotate(",null,y)-2,x:ju(A,U)})}else if(U)z.push($(z)+"rotate("+U+y)}function J(A,U,z,W){if(A!==U)W.push({i:z.push($(z)+"skewX(",null,y)-2,x:ju(A,U)});else if(U)z.push($(z)+"skewX("+U+y)}function F(A,U,z,W,K,q){if(A!==z||U!==W){var E=K.push($(K)+"scale(",null,",",null,")");q.push({i:E-4,x:ju(A,z)},{i:E-2,x:ju(U,W)})}else if(z!==1||W!==1)K.push($(K)+"scale("+z+","+W+")")}return function(A,U){var z=[],W=[];return A=f(A),U=f(U),l(A.translateX,A.translateY,U.translateX,U.translateY,z,W),j(A.rotate,U.rotate,z,W),J(A.skewX,U.skewX,z,W),F(A.scaleX,A.scaleY,U.scaleX,U.scaleY,z,W),A=U=null,function(K){var q=-1,E=W.length,O;while(++q=0)f._call.call(void 0,u);f=f._next}--o3}function iG(){py=(y5=$l.now())+$5,o3=_l=0;try{tG()}finally{o3=0,DY(),py=0}}function wY(){var f=$l.now(),u=f-y5;if(u>gG)$5-=u,y5=f}function DY(){var f,u=_5,_,y=1/0;while(u)if(u._call){if(y>u._time)y=u._time;f=u,u=u._next}else _=u._next,u._next=null,u=f?f._next=_:_5=_;yl=f,wJ(y)}function wJ(f){if(o3)return;if(_l)_l=clearTimeout(_l);var u=f-py;if(u>24){if(f<1/0)_l=setTimeout(iG,f-$l.now()-$5);if(ul)ul=clearInterval(ul)}else{if(!ul)y5=$l.now(),ul=setInterval(wY,gG);o3=1,nG(iG)}}function Jl(f,u,_){var y=new ll;return u=u==null?0:+u,y.restart(($)=>{y.stop(),f($+u)},u,_),y}var MY=xy("start","end","cancel","interrupt"),SY=[],aG=0,sG=1,J5=2,j5=3,oG=4,F5=5,Fl=6;function J_(f,u,_,y,$,l){var j=f.__transition;if(!j)f.__transition={};else if(_ in j)return;rY(f,_,{name:u,index:y,group:$,on:MY,tween:SY,time:l.time,delay:l.delay,duration:l.duration,ease:l.ease,timer:null,state:aG})}function Ql(f,u){var _=R0(f,u);if(_.state>aG)throw Error("too late; already scheduled");return _}function o0(f,u){var _=R0(f,u);if(_.state>j5)throw Error("too late; already running");return _}function R0(f,u){var _=f.__transition;if(!_||!(_=_[u]))throw Error("transition not found");return _}function rY(f,u,_){var y=f.__transition,$;y[u]=_,_.timer=l5(l,0,_.time);function l(A){if(_.state=sG,_.timer.restart(j,_.delay,_.time),_.delay<=A)j(A-_.delay)}function j(A){var U,z,W,K;if(_.state!==sG)return F();for(U in y){if(K=y[U],K.name!==_.name)continue;if(K.state===j5)return Jl(j);if(K.state===oG)K.state=Fl,K.timer.stop(),K.on.call("interrupt",f,f.__data__,K.index,K.group),delete y[U];else if(+UJ5&&y.state=0)u=u.slice(0,_);return!u||u==="start"})}function dY(f,u,_){var y,$,l=aY(u)?Ql:o0;return function(){var j=l(this,f),J=j.on;if(J!==y)($=(y=J).copy()).on(u,_);j.on=$}}function bJ(f,u){var _=this._id;return arguments.length<2?R0(this.node(),_).on.on(f):this.each(dY(_,f,u))}function eY(f){return function(){var u=this.parentNode;for(var _ in this.__transition)if(+_!==f)return;if(u)u.removeChild(this)}}function hJ(){return this.on("end.remove",eY(this._id))}function IJ(f){var u=this._name,_=this._id;if(typeof f!=="function")f=c_(f);for(var y=this._groups,$=y.length,l=Array($),j=0;j<$;++j)for(var J=y[j],F=J.length,A=l[j]=Array(F),U,z,W=0;W()=>f;function oJ(f,{sourceEvent:u,target:_,transform:y,dispatch:$}){Object.defineProperties(this,{type:{value:f,enumerable:!0,configurable:!0},sourceEvent:{value:u,enumerable:!0,configurable:!0},target:{value:_,enumerable:!0,configurable:!0},transform:{value:y,enumerable:!0,configurable:!0},_:{value:$}})}function V1(f,u,_){this.k=f,this.x=u,this.y=_}V1.prototype={constructor:V1,scale:function(f){return f===1?this:new V1(this.k*f,this.x,this.y)},translate:function(f,u){return f===0&u===0?this:new V1(this.k,this.x+this.k*f,this.y+this.k*u)},apply:function(f){return[f[0]*this.k+this.x,f[1]*this.k+this.y]},applyX:function(f){return f*this.k+this.x},applyY:function(f){return f*this.k+this.y},invert:function(f){return[(f[0]-this.x)/this.k,(f[1]-this.y)/this.k]},invertX:function(f){return(f-this.x)/this.k},invertY:function(f){return(f-this.y)/this.k},rescaleX:function(f){return f.copy().domain(f.range().map(this.invertX,this).map(f.invert,f))},rescaleY:function(f){return f.copy().domain(f.range().map(this.invertY,this).map(f.invert,f))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var my=new V1(1,0,0);Wl.prototype=V1.prototype;function Wl(f){while(!f.__zoom)if(!(f=f.parentNode))return my;return f.__zoom}function E5(f){f.stopImmediatePropagation()}function ky(f){f.preventDefault(),f.stopImmediatePropagation()}function KB(f){return(!f.ctrlKey||f.type==="wheel")&&!f.button}function ZB(){var f=this;if(f instanceof SVGElement){if(f=f.ownerSVGElement||f,f.hasAttribute("viewBox"))return f=f.viewBox.baseVal,[[f.x,f.y],[f.x+f.width,f.y+f.height]];return[[0,0],[f.width.baseVal.value,f.height.baseVal.value]]}return[[0,0],[f.clientWidth,f.clientHeight]]}function fK(){return this.__zoom||my}function qB(f){return-f.deltaY*(f.deltaMode===1?0.05:f.deltaMode?1:0.002)*(f.ctrlKey?10:1)}function HB(){return navigator.maxTouchPoints||"ontouchstart"in this}function EB(f,u,_){var y=f.invertX(u[0][0])-_[0][0],$=f.invertX(u[1][0])-_[1][0],l=f.invertY(u[0][1])-_[0][1],j=f.invertY(u[1][1])-_[1][1];return f.translate($>y?(y+$)/2:Math.min(0,y)||Math.max(0,$),j>l?(l+j)/2:Math.min(0,l)||Math.max(0,j))}function zl(){var f=KB,u=ZB,_=EB,y=qB,$=HB,l=[0,1/0],j=[[-1/0,-1/0],[1/0,1/0]],J=250,F=cy,A=xy("start","zoom","end"),U,z,W,K=500,q=150,E=0,O=10;function G(w){w.property("__zoom",fK).on("wheel.zoom",D,{passive:!1}).on("mousedown.zoom",x).on("dblclick.zoom",c).filter($).on("touchstart.zoom",v).on("touchmove.zoom",C).on("touchend.zoom touchcancel.zoom",P).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}G.transform=function(w,r,S,T){var Y=w.selection?w.selection():w;if(Y.property("__zoom",fK),w!==Y)L(w,r,S,T);else Y.interrupt().each(function(){M(this,arguments).event(T).start().zoom(null,typeof r==="function"?r.apply(this,arguments):r).end()})},G.scaleBy=function(w,r,S,T){G.scaleTo(w,function(){var Y=this.__zoom.k,R=typeof r==="function"?r.apply(this,arguments):r;return Y*R},S,T)},G.scaleTo=function(w,r,S,T){G.transform(w,function(){var Y=u.apply(this,arguments),R=this.__zoom,m=S==null?V(Y):typeof S==="function"?S.apply(this,arguments):S,p=R.invert(m),n=typeof r==="function"?r.apply(this,arguments):r;return _(Z(H(R,n),m,p),Y,j)},S,T)},G.translateBy=function(w,r,S,T){G.transform(w,function(){return _(this.__zoom.translate(typeof r==="function"?r.apply(this,arguments):r,typeof S==="function"?S.apply(this,arguments):S),u.apply(this,arguments),j)},null,T)},G.translateTo=function(w,r,S,T,Y){G.transform(w,function(){var R=u.apply(this,arguments),m=this.__zoom,p=T==null?V(R):typeof T==="function"?T.apply(this,arguments):T;return _(my.translate(p[0],p[1]).scale(m.k).translate(typeof r==="function"?-r.apply(this,arguments):-r,typeof S==="function"?-S.apply(this,arguments):-S),R,j)},T,Y)};function H(w,r){return r=Math.max(l[0],Math.min(l[1],r)),r===w.k?w:new V1(r,w.x,w.y)}function Z(w,r,S){var T=r[0]-S[0]*w.k,Y=r[1]-S[1]*w.k;return T===w.x&&Y===w.y?w:new V1(w.k,T,Y)}function V(w){return[(+w[0][0]+ +w[1][0])/2,(+w[0][1]+ +w[1][1])/2]}function L(w,r,S,T){w.on("start.zoom",function(){M(this,arguments).event(T).start()}).on("interrupt.zoom end.zoom",function(){M(this,arguments).event(T).end()}).tween("zoom",function(){var Y=this,R=arguments,m=M(Y,R).event(T),p=u.apply(Y,R),n=S==null?V(p):typeof S==="function"?S.apply(Y,R):S,_f=Math.max(p[1][0]-p[0][0],p[1][1]-p[0][1]),t=Y.__zoom,ff=typeof r==="function"?r.apply(Y,R):r,Gf=F(t.invert(n).concat(_f/t.k),ff.invert(n).concat(_f/ff.k));return function(zf){if(zf===1)zf=ff;else{var jf=Gf(zf),Wf=_f/jf[2];zf=new V1(Wf,n[0]-jf[0]*Wf,n[1]-jf[1]*Wf)}m.zoom(null,zf)}})}function M(w,r,S){return!S&&w.__zooming||new N(w,r)}function N(w,r){this.that=w,this.args=r,this.active=0,this.sourceEvent=null,this.extent=u.apply(w,r),this.taps=0}N.prototype={event:function(w){if(w)this.sourceEvent=w;return this},start:function(){if(++this.active===1)this.that.__zooming=this,this.emit("start");return this},zoom:function(w,r){if(this.mouse&&w!=="mouse")this.mouse[1]=r.invert(this.mouse[0]);if(this.touch0&&w!=="touch")this.touch0[1]=r.invert(this.touch0[0]);if(this.touch1&&w!=="touch")this.touch1[1]=r.invert(this.touch1[0]);return this.that.__zoom=r,this.emit("zoom"),this},end:function(){if(--this.active===0)delete this.that.__zooming,this.emit("end");return this},emit:function(w){var r=C0(this.that).datum();A.call(w,this.that,new oJ(w,{sourceEvent:this.sourceEvent,target:G,type:w,transform:this.that.__zoom,dispatch:A}),r)}};function D(w,...r){if(!f.apply(this,arguments))return;var S=M(this,r).event(w),T=this.__zoom,Y=Math.max(l[0],Math.min(l[1],T.k*Math.pow(2,y.apply(this,arguments)))),R=lu(w);if(S.wheel){if(S.mouse[0][0]!==R[0]||S.mouse[0][1]!==R[1])S.mouse[1]=T.invert(S.mouse[0]=R);clearTimeout(S.wheel)}else if(T.k===Y)return;else S.mouse=[R,T.invert(R)],m_(this),S.start();ky(w),S.wheel=setTimeout(m,q),S.zoom("mouse",_(Z(H(T,Y),S.mouse[0],S.mouse[1]),S.extent,j));function m(){S.wheel=null,S.end()}}function x(w,...r){if(W||!f.apply(this,arguments))return;var S=w.currentTarget,T=M(this,r,!0).event(w),Y=C0(w.view).on("mousemove.zoom",n,!0).on("mouseup.zoom",_f,!0),R=lu(w,S),m=w.clientX,p=w.clientY;g3(w.view),E5(w),T.mouse=[R,this.__zoom.invert(R)],m_(this),T.start();function n(t){if(ky(t),!T.moved){var ff=t.clientX-m,Gf=t.clientY-p;T.moved=ff*ff+Gf*Gf>E}T.event(t).zoom("mouse",_(Z(T.that.__zoom,T.mouse[0]=lu(t,S),T.mouse[1]),T.extent,j))}function _f(t){Y.on("mousemove.zoom mouseup.zoom",null),g6(t.view,T.moved),ky(t),T.event(t).end()}}function c(w,...r){if(!f.apply(this,arguments))return;var S=this.__zoom,T=lu(w.changedTouches?w.changedTouches[0]:w,this),Y=S.invert(T),R=S.k*(w.shiftKey?0.5:2),m=_(Z(H(S,R),T,Y),u.apply(this,r),j);if(ky(w),J>0)C0(this).transition().duration(J).call(L,m,T,w);else C0(this).call(G.transform,m,T,w)}function v(w,...r){if(!f.apply(this,arguments))return;var S=w.touches,T=S.length,Y=M(this,r,w.changedTouches.length===T).event(w),R,m,p,n;E5(w);for(m=0;m"[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:(f)=>`Node type "${f}" 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:(f)=>`The old edge with id=${f} does not exist.`,error009:(f)=>`Marker type "${f}" doesn't exist.`,error008:(f,{id:u,sourceHandle:_,targetHandle:y})=>`Couldn't create edge for ${f} handle id: "${f==="source"?_:y}", edge id: ${u}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:(f)=>`Edge type "${f}" not found. Using fallback type "default".`,error012:(f)=>`Node with id "${f}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(f="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${f}/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."},_$=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],uF=["Enter"," ","Escape"],_F={"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:f,x:u,y:_})=>`Moved selected node ${f}. New position, x: ${u}, y: ${_}`,"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"},g_;(function(f){f.Strict="strict",f.Loose="loose"})(g_||(g_={}));var Q_;(function(f){f.Free="free",f.Vertical="vertical",f.Horizontal="horizontal"})(Q_||(Q_={}));var iy;(function(f){f.Partial="partial",f.Full="full"})(iy||(iy={}));var yF={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null},v1;(function(f){f.Bezier="default",f.Straight="straight",f.Step="step",f.SmoothStep="smoothstep",f.SimpleBezier="simplebezier"})(v1||(v1={}));var n_;(function(f){f.Arrow="arrow",f.ArrowClosed="arrowclosed"})(n_||(n_={}));var Uf;(function(f){f.Left="left",f.Top="top",f.Right="right",f.Bottom="bottom"})(Uf||(Uf={}));var uK={[Uf.Left]:Uf.Right,[Uf.Right]:Uf.Left,[Uf.Top]:Uf.Bottom,[Uf.Bottom]:Uf.Top};function $F(f){return f===null?null:f?"valid":"invalid"}var lF=(f)=>("id"in f)&&("source"in f)&&("target"in f),GK=(f)=>("id"in f)&&("position"in f)&&!("source"in f)&&!("target"in f),jF=(f)=>("id"in f)&&("internals"in f)&&!("source"in f)&&!("target"in f);var Zl=(f,u=[0,0])=>{let{width:_,height:y}=b1(f),$=f.origin??u,l=_*$[0],j=y*$[1];return{x:f.position.x-l,y:f.position.y-j}},JF=(f,u={nodeOrigin:[0,0]})=>{if(f.length===0)return{x:0,y:0,width:0,height:0};let _=f.reduce((y,$)=>{let l=typeof $==="string",j=!u.nodeLookup&&!l?$:void 0;if(u.nodeLookup)j=l?u.nodeLookup.get($):!jF($)?u.nodeLookup.get($.id):$;let J=j?X5(j,u.nodeOrigin):{x:0,y:0,x2:0,y2:0};return L5(y,J)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return Y5(_)},y$=(f,u={})=>{let _={x:1/0,y:1/0,x2:-1/0,y2:-1/0},y=!1;return f.forEach(($)=>{if(u.filter===void 0||u.filter($))_=L5(_,X5($)),y=!0}),y?Y5(_):{x:0,y:0,width:0,height:0}},N5=(f,u,[_,y,$]=[0,0,1],l=!1,j=!1)=>{let J={...j$(u,[_,y,$]),width:u.width/$,height:u.height/$},F=[];for(let A of f.values()){let{measured:U,selectable:z=!0,hidden:W=!1}=A;if(j&&!z||W)continue;let K=U.width??A.width??A.initialWidth??null,q=U.height??A.height??A.initialHeight??null,E=$$(J,ny(A)),O=(K??0)*(q??0),G=l&&E>0;if(!A.internals.handleBounds||G||E>=O||A.dragging)F.push(A)}return F},KK=(f,u)=>{let _=new Set;return f.forEach((y)=>{_.add(y.id)}),u.filter((y)=>_.has(y.source)||_.has(y.target))};function VB(f,u){let _=new Map,y=u?.nodes?new Set(u.nodes.map(($)=>$.id)):null;return f.forEach(($)=>{if($.measured.width&&$.measured.height&&(u?.includeHiddenNodes||!$.hidden)&&(!y||y.has($.id)))_.set($.id,$)}),_}async function ZK({nodes:f,width:u,height:_,panZoom:y,minZoom:$,maxZoom:l},j){if(f.size===0)return Promise.resolve(!0);let J=VB(f,j),F=y$(J),A=ql(F,u,_,j?.minZoom??$,j?.maxZoom??l,j?.padding??0.1);return await y.setViewport(A,{duration:j?.duration,ease:j?.ease,interpolate:j?.interpolate}),Promise.resolve(!0)}function FF({nodeId:f,nextPosition:u,nodeLookup:_,nodeOrigin:y=[0,0],nodeExtent:$,onError:l}){let j=_.get(f),J=j.parentId?_.get(j.parentId):void 0,{x:F,y:A}=J?J.internals.positionAbsolute:{x:0,y:0},U=j.origin??y,z=j.extent||$;if(j.extent==="parent"&&!j.expandParent)if(!J)l?.("005",hu.error005());else{let K=J.measured.width,q=J.measured.height;if(K&&q)z=[[F,A],[F+K,A+q]]}else if(J&&u$(j.extent))z=[[j.extent[0][0]+F,j.extent[0][1]+A],[j.extent[1][0]+F,j.extent[1][1]+A]];let W=u$(z)?gy(u,z,j.measured):u;if(j.measured.width===void 0||j.measured.height===void 0)l?.("015",hu.error015());return{position:{x:W.x-F+(j.measured.width??0)*U[0],y:W.y-A+(j.measured.height??0)*U[1]},positionAbsolute:W}}async function qK({nodesToRemove:f=[],edgesToRemove:u=[],nodes:_,edges:y,onBeforeDelete:$}){let l=new Set(f.map((W)=>W.id)),j=[];for(let W of _){if(W.deletable===!1)continue;let K=l.has(W.id),q=!K&&W.parentId&&j.find((E)=>E.id===W.parentId);if(K||q)j.push(W)}let J=new Set(u.map((W)=>W.id)),F=y.filter((W)=>W.deletable!==!1),U=KK(j,F);for(let W of F)if(J.has(W.id)&&!U.find((q)=>q.id===W.id))U.push(W);if(!$)return{edges:U,nodes:j};let z=await $({nodes:j,edges:U});if(typeof z==="boolean")return z?{edges:U,nodes:j}:{edges:[],nodes:[]};return z}var f$=(f,u=0,_=1)=>Math.min(Math.max(f,u),_),gy=(f={x:0,y:0},u,_)=>({x:f$(f.x,u[0][0],u[1][0]-(_?.width??0)),y:f$(f.y,u[0][1],u[1][1]-(_?.height??0))});function HK(f,u,_){let{width:y,height:$}=b1(_),{x:l,y:j}=_.internals.positionAbsolute;return gy(f,[[l,j],[l+y,j+$]],u)}var _K=(f,u,_)=>{if(f_)return-f$(Math.abs(f-_),1,u)/u;return 0},EK=(f,u,_=15,y=40)=>{let $=_K(f.x,y,u.width-y)*_,l=_K(f.y,y,u.height-y)*_;return[$,l]},L5=(f,u)=>({x:Math.min(f.x,u.x),y:Math.min(f.y,u.y),x2:Math.max(f.x2,u.x2),y2:Math.max(f.y2,u.y2)}),fF=({x:f,y:u,width:_,height:y})=>({x:f,y:u,x2:f+_,y2:u+y}),Y5=({x:f,y:u,x2:_,y2:y})=>({x:f,y:u,width:_-f,height:y-u}),ny=(f,u=[0,0])=>{let{x:_,y}=jF(f)?f.internals.positionAbsolute:Zl(f,u);return{x:_,y,width:f.measured?.width??f.width??f.initialWidth??0,height:f.measured?.height??f.height??f.initialHeight??0}},X5=(f,u=[0,0])=>{let{x:_,y}=jF(f)?f.internals.positionAbsolute:Zl(f,u);return{x:_,y,x2:_+(f.measured?.width??f.width??f.initialWidth??0),y2:y+(f.measured?.height??f.height??f.initialHeight??0)}},QF=(f,u)=>Y5(L5(fF(f),fF(u))),$$=(f,u)=>{let _=Math.max(0,Math.min(f.x+f.width,u.x+u.width)-Math.max(f.x,u.x)),y=Math.max(0,Math.min(f.y+f.height,u.y+u.height)-Math.max(f.y,u.y));return Math.ceil(_*y)},AF=(f)=>u1(f.width)&&u1(f.height)&&u1(f.x)&&u1(f.y),u1=(f)=>!isNaN(f)&&isFinite(f),UF=(f,u)=>{},l$=(f,u=[1,1])=>{return{x:u[0]*Math.round(f.x/u[0]),y:u[1]*Math.round(f.y/u[1])}},j$=({x:f,y:u},[_,y,$],l=!1,j=[1,1])=>{let J={x:(f-_)/$,y:(u-y)/$};return l?l$(J,j):J},Kl=({x:f,y:u},[_,y,$])=>{return{x:f*$+_,y:u*$+y}};function d3(f,u){if(typeof f==="number")return Math.floor((u-u/(1+f))*0.5);if(typeof f==="string"&&f.endsWith("px")){let _=parseFloat(f);if(!Number.isNaN(_))return Math.floor(_)}if(typeof f==="string"&&f.endsWith("%")){let _=parseFloat(f);if(!Number.isNaN(_))return Math.floor(u*_*0.01)}return console.error(`[React Flow] The padding value "${f}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function OB(f,u,_){if(typeof f==="string"||typeof f==="number"){let y=d3(f,_),$=d3(f,u);return{top:y,right:$,bottom:y,left:$,x:$*2,y:y*2}}if(typeof f==="object"){let y=d3(f.top??f.y??0,_),$=d3(f.bottom??f.y??0,_),l=d3(f.left??f.x??0,u),j=d3(f.right??f.x??0,u);return{top:y,right:j,bottom:$,left:l,x:l+j,y:y+$}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function XB(f,u,_,y,$,l){let{x:j,y:J}=Kl(f,[u,_,y]),{x:F,y:A}=Kl({x:f.x+f.width,y:f.y+f.height},[u,_,y]),U=$-F,z=l-A;return{left:Math.floor(j),top:Math.floor(J),right:Math.floor(U),bottom:Math.floor(z)}}var ql=(f,u,_,y,$,l)=>{let j=OB(l,u,_),J=(u-j.x)/f.width,F=(_-j.y)/f.height,A=Math.min(J,F),U=f$(A,y,$),z=f.x+f.width/2,W=f.y+f.height/2,K=u/2-z*U,q=_/2-W*U,E=XB(f,K,q,U,u,_),O={left:Math.min(E.left-j.left,0),top:Math.min(E.top-j.top,0),right:Math.min(E.right-j.right,0),bottom:Math.min(E.bottom-j.bottom,0)};return{x:K-O.left+O.right,y:q-O.top+O.bottom,zoom:U}},J$=()=>typeof navigator<"u"&&navigator?.userAgent?.indexOf("Mac")>=0;function u$(f){return f!==void 0&&f!==null&&f!=="parent"}function b1(f){return{width:f.measured?.width??f.width??f.initialWidth??0,height:f.measured?.height??f.height??f.initialHeight??0}}function WF(f){return(f.measured?.width??f.width??f.initialWidth)!==void 0&&(f.measured?.height??f.height??f.initialHeight)!==void 0}function zF(f,u={width:0,height:0},_,y,$){let l={...f},j=y.get(_);if(j){let J=j.origin||$;l.x+=j.internals.positionAbsolute.x-(u.width??0)*J[0],l.y+=j.internals.positionAbsolute.y-(u.height??0)*J[1]}return l}function GF(f,u){if(f.size!==u.size)return!1;for(let _ of f)if(!u.has(_))return!1;return!0}function VK(){let f,u;return{promise:new Promise((y,$)=>{f=y,u=$}),resolve:f,reject:u}}function OK(f){return{..._F,...f||{}}}function Gl(f,{snapGrid:u=[0,0],snapToGrid:_=!1,transform:y,containerBounds:$}){let{x:l,y:j}=_1(f),J=j$({x:l-($?.left??0),y:j-($?.top??0)},y),{x:F,y:A}=_?l$(J,u):J;return{xSnapped:F,ySnapped:A,...J}}var B5=(f)=>({width:f.offsetWidth,height:f.offsetHeight}),KF=(f)=>f?.getRootNode?.()||window?.document,NB=["INPUT","SELECT","TEXTAREA"];function ZF(f){let u=f.composedPath?.()?.[0]||f.target;if(u?.nodeType!==1)return!1;return NB.includes(u.nodeName)||u.hasAttribute("contenteditable")||!!u.closest(".nokey")}var qF=(f)=>("clientX"in f),_1=(f,u)=>{let _=qF(f),y=_?f.clientX:f.touches?.[0].clientX,$=_?f.clientY:f.touches?.[0].clientY;return{x:y-(u?.left??0),y:$-(u?.top??0)}},yK=(f,u,_,y,$)=>{let l=u.querySelectorAll(`.${f}`);if(!l||!l.length)return null;return Array.from(l).map((j)=>{let J=j.getBoundingClientRect();return{id:j.getAttribute("data-handleid"),type:f,nodeId:$,position:j.getAttribute("data-handlepos"),x:(J.left-_.left)/y,y:(J.top-_.top)/y,...B5(j)}})};function w5({sourceX:f,sourceY:u,targetX:_,targetY:y,sourceControlX:$,sourceControlY:l,targetControlX:j,targetControlY:J}){let F=f*0.125+$*0.375+j*0.375+_*0.125,A=u*0.125+l*0.375+J*0.375+y*0.125,U=Math.abs(F-f),z=Math.abs(A-u);return[F,A,U,z]}function V5(f,u){if(f>=0)return 0.5*f;return u*25*Math.sqrt(-f)}function $K({pos:f,x1:u,y1:_,x2:y,y2:$,c:l}){switch(f){case Uf.Left:return[u-V5(u-y,l),_];case Uf.Right:return[u+V5(y-u,l),_];case Uf.Top:return[u,_-V5(_-$,l)];case Uf.Bottom:return[u,_+V5($-_,l)]}}function D5({sourceX:f,sourceY:u,sourcePosition:_=Uf.Bottom,targetX:y,targetY:$,targetPosition:l=Uf.Top,curvature:j=0.25}){let[J,F]=$K({pos:_,x1:f,y1:u,x2:y,y2:$,c:j}),[A,U]=$K({pos:l,x1:y,y1:$,x2:f,y2:u,c:j}),[z,W,K,q]=w5({sourceX:f,sourceY:u,targetX:y,targetY:$,sourceControlX:J,sourceControlY:F,targetControlX:A,targetControlY:U});return[`M${f},${u} C${J},${F} ${A},${U} ${y},${$}`,z,W,K,q]}function HF({sourceX:f,sourceY:u,targetX:_,targetY:y}){let $=Math.abs(_-f)/2,l=_0}var LB=({source:f,sourceHandle:u,target:_,targetHandle:y})=>`xy-edge__${f}${u||""}-${_}${y||""}`,YB=(f,u)=>{return u.some((_)=>_.source===f.source&&_.target===f.target&&(_.sourceHandle===f.sourceHandle||!_.sourceHandle&&!f.sourceHandle)&&(_.targetHandle===f.targetHandle||!_.targetHandle&&!f.targetHandle))},EF=(f,u,_={})=>{if(!f.source||!f.target)return UF("006",hu.error006()),u;let y=_.getEdgeId||LB,$;if(lF(f))$={...f};else $={...f,id:y(f)};if(YB($,u))return u;if($.sourceHandle===null)delete $.sourceHandle;if($.targetHandle===null)delete $.targetHandle;return u.concat($)};function T5({sourceX:f,sourceY:u,targetX:_,targetY:y}){let[$,l,j,J]=HF({sourceX:f,sourceY:u,targetX:_,targetY:y});return[`M ${f},${u}L ${_},${y}`,$,l,j,J]}var lK={[Uf.Left]:{x:-1,y:0},[Uf.Right]:{x:1,y:0},[Uf.Top]:{x:0,y:-1},[Uf.Bottom]:{x:0,y:1}},BB=({source:f,sourcePosition:u=Uf.Bottom,target:_})=>{if(u===Uf.Left||u===Uf.Right)return f.x<_.x?{x:1,y:0}:{x:-1,y:0};return f.y<_.y?{x:0,y:1}:{x:0,y:-1}},jK=(f,u)=>Math.sqrt(Math.pow(u.x-f.x,2)+Math.pow(u.y-f.y,2));function wB({source:f,sourcePosition:u=Uf.Bottom,target:_,targetPosition:y=Uf.Top,center:$,offset:l,stepPosition:j}){let J=lK[u],F=lK[y],A={x:f.x+J.x*l,y:f.y+J.y*l},U={x:_.x+F.x*l,y:_.y+F.y*l},z=BB({source:A,sourcePosition:u,target:U}),W=z.x!==0?"x":"y",K=z[W],q=[],E,O,G={x:0,y:0},H={x:0,y:0},[,,Z,V]=HF({sourceX:f.x,sourceY:f.y,targetX:_.x,targetY:_.y});if(J[W]*F[W]===-1){if(W==="x")E=$.x??A.x+(U.x-A.x)*j,O=$.y??(A.y+U.y)/2;else E=$.x??(A.x+U.x)/2,O=$.y??A.y+(U.y-A.y)*j;let D=[{x:E,y:A.y},{x:E,y:U.y}],x=[{x:A.x,y:O},{x:U.x,y:O}];if(J[W]===K)q=W==="x"?D:x;else q=W==="x"?x:D}else{let D=[{x:A.x,y:U.y}],x=[{x:U.x,y:A.y}];if(W==="x")q=J.x===K?x:D;else q=J.y===K?D:x;if(u===y){let w=Math.abs(f[W]-_[W]);if(w<=l){let r=Math.min(l-1,l-w);if(J[W]===K)G[W]=(A[W]>f[W]?-1:1)*r;else H[W]=(U[W]>_[W]?-1:1)*r}}if(u!==y){let w=W==="x"?"y":"x",r=J[W]===F[w],S=A[w]>U[w],T=A[w]=P)E=(c.x+v.x)/2,O=q[0].y;else E=q[0].x,O=(c.y+v.y)/2}let L={x:A.x+G.x,y:A.y+G.y},M={x:U.x+H.x,y:U.y+H.y};return[[f,...L.x!==q[0].x||L.y!==q[0].y?[L]:[],...q,...M.x!==q[q.length-1].x||M.y!==q[q.length-1].y?[M]:[],_],E,O,Z,V]}function DB(f,u,_,y){let $=Math.min(jK(f,u)/2,jK(u,_)/2,y),{x:l,y:j}=u;if(f.x===l&&l===_.x||f.y===j&&j===_.y)return`L${l} ${j}`;if(f.y===j){let A=f.x<_.x?-1:1,U=f.y<_.y?1:-1;return`L ${l+$*A},${j}Q ${l},${j} ${l},${j+$*U}`}let J=f.x<_.x?1:-1,F=f.y<_.y?-1:1;return`L ${l},${j+$*F}Q ${l},${j} ${l+$*J},${j}`}function Hl({sourceX:f,sourceY:u,sourcePosition:_=Uf.Bottom,targetX:y,targetY:$,targetPosition:l=Uf.Top,borderRadius:j=5,centerX:J,centerY:F,offset:A=20,stepPosition:U=0.5}){let[z,W,K,q,E]=wB({source:{x:f,y:u},sourcePosition:_,target:{x:y,y:$},targetPosition:l,center:{x:J,y:F},offset:A,stepPosition:U}),O=`M${z[0].x} ${z[0].y}`;for(let G=1;G_.id===u))||null}function M5(f,u){if(!f)return"";if(typeof f==="string")return f;return`${u?`${u}__`:""}${Object.keys(f).sort().map((y)=>`${y}=${f[y]}`).join("&")}`}function YK(f,{id:u,defaultColor:_,defaultMarkerStart:y,defaultMarkerEnd:$}){let l=new Set;return f.reduce((j,J)=>{return[J.markerStart||y,J.markerEnd||$].forEach((F)=>{if(F&&typeof F==="object"){let A=M5(F,u);if(!l.has(A))j.push({id:A,color:F.color||_,...F}),l.add(A)}}),j},[]).sort((j,J)=>j.id.localeCompare(J.id))}var BK=1000,TB=10,VF={nodeOrigin:[0,0],nodeExtent:_$,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},MB={...VF,checkEquality:!0};function OF(f,u){let _={...f};for(let y in u)if(u[y]!==void 0)_[y]=u[y];return _}function wK(f,u,_){let y=OF(VF,_);for(let $ of f.values())if($.parentId)NF($,f,u,y);else{let l=Zl($,y.nodeOrigin),j=u$($.extent)?$.extent:y.nodeExtent,J=gy(l,j,b1($));$.internals.positionAbsolute=J}}function SB(f,u){if(!f.handles)return!f.measured?void 0:u?.internals.handleBounds;let _=[],y=[];for(let $ of f.handles){let l={id:$.id,width:$.width??1,height:$.height??1,nodeId:f.id,x:$.x,y:$.y,position:$.position,type:$.type};if($.type==="source")_.push(l);else if($.type==="target")y.push(l)}return{source:_,target:y}}function XF(f){return f==="manual"}function S5(f,u,_,y={}){let $=OF(MB,y),l={i:0},j=new Map(u),J=$?.elevateNodesOnSelect&&!XF($.zIndexMode)?BK:0,F=f.length>0,A=!1;u.clear(),_.clear();for(let U of f){let z=j.get(U.id);if($.checkEquality&&U===z?.internals.userNode)u.set(U.id,z);else{let W=Zl(U,$.nodeOrigin),K=u$(U.extent)?U.extent:$.nodeExtent,q=gy(W,K,b1(U));z={...$.defaults,...U,measured:{width:U.measured?.width,height:U.measured?.height},internals:{positionAbsolute:q,handleBounds:SB(U,z),z:DK(U,J,$.zIndexMode),userNode:U}},u.set(U.id,z)}if((z.measured===void 0||z.measured.width===void 0||z.measured.height===void 0)&&!z.hidden)F=!1;if(U.parentId)NF(z,u,_,y,l);A||=U.selected??!1}return{nodesInitialized:F,hasSelectedNodes:A}}function rB(f,u){if(!f.parentId)return;let _=u.get(f.parentId);if(_)_.set(f.id,f);else u.set(f.parentId,new Map([[f.id,f]]))}function NF(f,u,_,y,$){let{elevateNodesOnSelect:l,nodeOrigin:j,nodeExtent:J,zIndexMode:F}=OF(VF,y),A=f.parentId,U=u.get(A);if(!U){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(rB(f,_),$&&!U.parentId&&U.internals.rootParentIndex===void 0&&F==="auto")U.internals.rootParentIndex=++$.i,U.internals.z=U.internals.z+$.i*TB;if($&&U.internals.rootParentIndex!==void 0)$.i=U.internals.rootParentIndex;let z=l&&!XF(F)?BK:0,{x:W,y:K,z:q}=PB(f,U,j,J,z,F),{positionAbsolute:E}=f.internals,O=W!==E.x||K!==E.y;if(O||q!==f.internals.z)u.set(f.id,{...f,internals:{...f.internals,positionAbsolute:O?{x:W,y:K}:E,z:q}})}function DK(f,u,_){let y=u1(f.zIndex)?f.zIndex:0;if(XF(_))return y;return y+(f.selected?u:0)}function PB(f,u,_,y,$,l){let{x:j,y:J}=u.internals.positionAbsolute,F=b1(f),A=Zl(f,_),U=u$(f.extent)?gy(A,f.extent,F):A,z=gy({x:j+U.x,y:J+U.y},y,F);if(f.extent==="parent")z=HK(z,F,u);let W=DK(f,$,l),K=u.internals.z??0;return{x:z.x,y:z.y,z:K>=W?K+1:W}}function r5(f,u,_,y=[0,0]){let $=[],l=new Map;for(let j of f){let J=u.get(j.parentId);if(!J)continue;let F=l.get(j.parentId)?.expandedRect??ny(J),A=QF(F,j.rect);l.set(j.parentId,{expandedRect:A,parent:J})}if(l.size>0)l.forEach(({expandedRect:j,parent:J},F)=>{let A=J.internals.positionAbsolute,U=b1(J),z=J.origin??y,W=j.x0||K>0||O||G)$.push({id:F,type:"position",position:{x:J.position.x-W+O,y:J.position.y-K+G}}),_.get(F)?.forEach((H)=>{if(!f.some((Z)=>Z.id===H.id))$.push({id:H.id,type:"position",position:{x:H.position.x+W,y:H.position.y+K}})});if(U.width0){let K=r5(W,u,_,$);A.push(...K)}return{changes:A,updatedInternals:F}}async function MK({delta:f,panZoom:u,transform:_,translateExtent:y,width:$,height:l}){if(!u||!f.x&&!f.y)return Promise.resolve(!1);let j=await u.setViewportConstrained({x:_[0]+f.x,y:_[1]+f.y,zoom:_[2]},[[0,0],[$,l]],y),J=!!j&&(j.x!==_[0]||j.y!==_[1]||j.k!==_[2]);return Promise.resolve(J)}function AK(f,u,_,y,$,l){let j=$,J=y.get(j)||new Map;y.set(j,J.set(_,u)),j=`${$}-${f}`;let F=y.get(j)||new Map;if(y.set(j,F.set(_,u)),l){j=`${$}-${f}-${l}`;let A=y.get(j)||new Map;y.set(j,A.set(_,u))}}function LF(f,u,_){f.clear(),u.clear();for(let y of _){let{source:$,target:l,sourceHandle:j=null,targetHandle:J=null}=y,F={edgeId:y.id,source:$,target:l,sourceHandle:j,targetHandle:J},A=`${$}-${j}--${l}-${J}`,U=`${l}-${J}--${$}-${j}`;AK("source",F,U,f,$,j),AK("target",F,A,f,l,J),u.set(y.id,y)}}function SK(f,u){if(!f.parentId)return!1;let _=u.get(f.parentId);if(!_)return!1;if(_.selected)return!0;return SK(_,u)}function UK(f,u,_){let y=f;do{if(y?.matches?.(u))return!0;if(y===_)return!1;y=y?.parentElement}while(y);return!1}function CB(f,u,_,y){let $=new Map;for(let[l,j]of f)if((j.selected||j.id===y)&&(!j.parentId||!SK(j,f))&&(j.draggable||u&&typeof j.draggable>"u")){let J=f.get(l);if(J)$.set(l,{id:l,position:J.position||{x:0,y:0},distance:{x:_.x-J.internals.positionAbsolute.x,y:_.y-J.internals.positionAbsolute.y},extent:J.extent,parentId:J.parentId,origin:J.origin,expandParent:J.expandParent,internals:{positionAbsolute:J.internals.positionAbsolute||{x:0,y:0}},measured:{width:J.measured.width??0,height:J.measured.height??0}})}return $}function aJ({nodeId:f,dragItems:u,nodeLookup:_,dragging:y=!0}){let $=[];for(let[j,J]of u){let F=_.get(j)?.internals.userNode;if(F)$.push({...F,position:J.position,dragging:y})}if(!f)return[$[0],$];let l=_.get(f)?.internals.userNode;return[!l?$[0]:{...l,position:u.get(f)?.position||l.position,dragging:y},$]}function RB({dragItems:f,snapGrid:u,x:_,y}){let $=f.values().next().value;if(!$)return null;let l={x:_-$.distance.x,y:y-$.distance.y},j=l$(l,u);return{x:j.x-l.x,y:j.y-l.y}}function rK({onNodeMouseDown:f,getStoreItems:u,onDragStart:_,onDrag:y,onDragStop:$}){let l={x:null,y:null},j=0,J=new Map,F=!1,A={x:0,y:0},U=null,z=!1,W=null,K=!1,q=!1,E=null;function O({noDragClassName:H,handleSelector:Z,domNode:V,isSelectable:L,nodeId:M,nodeClickDistance:N=0}){W=C0(V);function D({x:C,y:P}){let{nodeLookup:w,nodeExtent:r,snapGrid:S,snapToGrid:T,nodeOrigin:Y,onNodeDrag:R,onSelectionDrag:m,onError:p,updateNodePositions:n}=u();l={x:C,y:P};let _f=!1,t=J.size>1,ff=t&&r?fF(y$(J)):null,Gf=t&&T?RB({dragItems:J,snapGrid:S,x:C,y:P}):null;for(let[zf,jf]of J){if(!w.has(zf))continue;let Wf={x:C-jf.distance.x,y:P-jf.distance.y};if(T)Wf=Gf?{x:Math.round(Wf.x+Gf.x),y:Math.round(Wf.y+Gf.y)}:l$(Wf,S);let Vf=null;if(t&&r&&!jf.extent&&ff){let{positionAbsolute:g}=jf.internals,I=g.x-ff.x+r[0][0],$f=g.x+jf.measured.width-ff.x2+r[1][0],lf=g.y-ff.y+r[0][1],Af=g.y+jf.measured.height-ff.y2+r[1][1];Vf=[[I,lf],[$f,Af]]}let{position:Zf,positionAbsolute:h}=FF({nodeId:zf,nextPosition:Wf,nodeLookup:w,nodeExtent:Vf?Vf:r,nodeOrigin:Y,onError:p});_f=_f||jf.position.x!==Zf.x||jf.position.y!==Zf.y,jf.position=Zf,jf.internals.positionAbsolute=h}if(q=q||_f,!_f)return;if(n(J,!0),E&&(y||R||!M&&m)){let[zf,jf]=aJ({nodeId:M,dragItems:J,nodeLookup:w});if(y?.(E,J,zf,jf),R?.(E,zf,jf),!M)m?.(E,jf)}}async function x(){if(!U)return;let{transform:C,panBy:P,autoPanSpeed:w,autoPanOnNodeDrag:r}=u();if(!r){F=!1,cancelAnimationFrame(j);return}let[S,T]=EK(A,U,w);if(S!==0||T!==0){if(l.x=(l.x??0)-S/C[2],l.y=(l.y??0)-T/C[2],await P({x:S,y:T}))D(l)}j=requestAnimationFrame(x)}function c(C){let{nodeLookup:P,multiSelectionActive:w,nodesDraggable:r,transform:S,snapGrid:T,snapToGrid:Y,selectNodesOnDrag:R,onNodeDragStart:m,onSelectionDragStart:p,unselectNodesAndEdges:n}=u();if(z=!0,(!R||!L)&&!w&&M){if(!P.get(M)?.selected)n()}if(L&&R&&M)f?.(M);let _f=Gl(C.sourceEvent,{transform:S,snapGrid:T,snapToGrid:Y,containerBounds:U});if(l=_f,J=CB(P,r,_f,M),J.size>0&&(_||m||!M&&p)){let[t,ff]=aJ({nodeId:M,dragItems:J,nodeLookup:P});if(_?.(C.sourceEvent,J,t,ff),m?.(C.sourceEvent,t,ff),!M)p?.(C.sourceEvent,ff)}}let v=s6().clickDistance(N).on("start",(C)=>{let{domNode:P,nodeDragThreshold:w,transform:r,snapGrid:S,snapToGrid:T}=u();if(U=P?.getBoundingClientRect()||null,K=!1,q=!1,E=C.sourceEvent,w===0)c(C);l=Gl(C.sourceEvent,{transform:r,snapGrid:S,snapToGrid:T,containerBounds:U}),A=_1(C.sourceEvent,U)}).on("drag",(C)=>{let{autoPanOnNodeDrag:P,transform:w,snapGrid:r,snapToGrid:S,nodeDragThreshold:T,nodeLookup:Y}=u(),R=Gl(C.sourceEvent,{transform:w,snapGrid:r,snapToGrid:S,containerBounds:U});if(E=C.sourceEvent,C.sourceEvent.type==="touchmove"&&C.sourceEvent.touches.length>1||M&&!Y.has(M))K=!0;if(K)return;if(!F&&P&&z)F=!0,x();if(!z){let m=_1(C.sourceEvent,U),p=m.x-A.x,n=m.y-A.y;if(Math.sqrt(p*p+n*n)>T)c(C)}if((l.x!==R.xSnapped||l.y!==R.ySnapped)&&J&&z)A=_1(C.sourceEvent,U),D(R)}).on("end",(C)=>{if(!z||K)return;if(F=!1,z=!1,cancelAnimationFrame(j),J.size>0){let{nodeLookup:P,updateNodePositions:w,onNodeDragStop:r,onSelectionDragStop:S}=u();if(q)w(J,!1),q=!1;if($||r||!M&&S){let[T,Y]=aJ({nodeId:M,dragItems:J,nodeLookup:P,dragging:!1});if($?.(C.sourceEvent,J,T,Y),r?.(C.sourceEvent,T,Y),!M)S?.(C.sourceEvent,Y)}}}).filter((C)=>{let P=C.target;return!C.button&&(!H||!UK(P,`.${H}`,V))&&(!Z||UK(P,Z,V))});W.call(v)}function G(){W?.on(".drag",null)}return{update:O,destroy:G}}function xB(f,u,_){let y=[],$={x:f.x-_,y:f.y-_,width:_*2,height:_*2};for(let l of u.values())if($$($,ny(l))>0)y.push(l);return y}var vB=250;function bB(f,u,_,y){let $=[],l=1/0,j=xB(f,_,u+vB);for(let J of j){let F=[...J.internals.handleBounds?.source??[],...J.internals.handleBounds?.target??[]];for(let A of F){if(y.nodeId===A.nodeId&&y.type===A.type&&y.id===A.id)continue;let{x:U,y:z}=t_(J,A,A.position,!0),W=Math.sqrt(Math.pow(U-f.x,2)+Math.pow(z-f.y,2));if(W>u)continue;if(W1){let J=y.type==="source"?"target":"source";return $.find((F)=>F.type===J)??$[0]}return $[0]}function PK(f,u,_,y,$,l=!1){let j=y.get(f);if(!j)return null;let J=$==="strict"?j.internals.handleBounds?.[u]:[...j.internals.handleBounds?.source??[],...j.internals.handleBounds?.target??[]],F=(_?J?.find((A)=>A.id===_):J?.[0])??null;return F&&l?{...F,...t_(j,F,F.position,!0)}:F}function CK(f,u){if(f)return f;else if(u?.classList.contains("target"))return"target";else if(u?.classList.contains("source"))return"source";return null}function hB(f,u){let _=null;if(u)_=!0;else if(f&&!u)_=!1;return _}var RK=()=>!0;function IB(f,{connectionMode:u,connectionRadius:_,handleId:y,nodeId:$,edgeUpdaterType:l,isTarget:j,domNode:J,nodeLookup:F,lib:A,autoPanOnConnect:U,flowId:z,panBy:W,cancelConnection:K,onConnectStart:q,onConnect:E,onConnectEnd:O,isValidConnection:G=RK,onReconnectEnd:H,updateConnection:Z,getTransform:V,getFromHandle:L,autoPanSpeed:M,dragThreshold:N=1,handleDomNode:D}){let x=KF(f.target),c=0,v,{x:C,y:P}=_1(f),w=CK(l,D),r=J?.getBoundingClientRect(),S=!1;if(!r||!w)return;let T=PK($,w,y,F,u);if(!T)return;let Y=_1(f,r),R=!1,m=null,p=!1,n=null;function _f(){if(!U||!r)return;let[Zf,h]=EK(Y,r,M);W({x:Zf,y:h}),c=requestAnimationFrame(_f)}let t={...T,nodeId:$,type:w,position:T.position},ff=F.get($),zf={inProgress:!0,isValid:null,from:t_(ff,t,Uf.Left,!0),fromHandle:t,fromPosition:t.position,fromNode:ff,to:Y,toHandle:null,toPosition:uK[t.position],toNode:null,pointer:Y};function jf(){S=!0,Z(zf),q?.(f,{nodeId:$,handleId:y,handleType:w})}if(N===0)jf();function Wf(Zf){if(!S){let{x:Af,y:Yf}=_1(Zf),xf=Af-C,sf=Yf-P;if(!(xf*xf+sf*sf>N*N))return;jf()}if(!L()||!t){Vf(Zf);return}let h=V();if(Y=_1(Zf,r),v=bB(j$(Y,h,!1,[1,1]),_,F,t),!R)_f(),R=!0;let g=xK(Zf,{handle:v,connectionMode:u,fromNodeId:$,fromHandleId:y,fromType:j?"target":"source",isValidConnection:G,doc:x,lib:A,flowId:z,nodeLookup:F});n=g.handleDomNode,m=g.connection,p=hB(!!v,g.isValid);let I=F.get($),$f=I?t_(I,t,Uf.Left,!0):zf.from,lf={...zf,from:$f,isValid:p,to:g.toHandle&&p?Kl({x:g.toHandle.x,y:g.toHandle.y},h):Y,toHandle:g.toHandle,toPosition:p&&g.toHandle?g.toHandle.position:uK[t.position],toNode:g.toHandle?F.get(g.toHandle.nodeId):null,pointer:Y};Z(lf),zf=lf}function Vf(Zf){if("touches"in Zf&&Zf.touches.length>0)return;if(S){if((v||n)&&m&&p)E?.(m);let{inProgress:h,...g}=zf,I={...g,toPosition:zf.toHandle?zf.toPosition:null};if(O?.(Zf,I),l)H?.(Zf,I)}K(),cancelAnimationFrame(c),R=!1,p=!1,m=null,n=null,x.removeEventListener("mousemove",Wf),x.removeEventListener("mouseup",Vf),x.removeEventListener("touchmove",Wf),x.removeEventListener("touchend",Vf)}x.addEventListener("mousemove",Wf),x.addEventListener("mouseup",Vf),x.addEventListener("touchmove",Wf),x.addEventListener("touchend",Vf)}function xK(f,{handle:u,connectionMode:_,fromNodeId:y,fromHandleId:$,fromType:l,doc:j,lib:J,flowId:F,isValidConnection:A=RK,nodeLookup:U}){let z=l==="target",W=u?j.querySelector(`.${J}-flow__handle[data-id="${F}-${u?.nodeId}-${u?.id}-${u?.type}"]`):null,{x:K,y:q}=_1(f),E=j.elementFromPoint(K,q),O=E?.classList.contains(`${J}-flow__handle`)?E:W,G={handleDomNode:O,isValid:!1,connection:null,toHandle:null};if(O){let H=CK(void 0,O),Z=O.getAttribute("data-nodeid"),V=O.getAttribute("data-handleid"),L=O.classList.contains("connectable"),M=O.classList.contains("connectableend");if(!Z||!H)return G;let N={source:z?Z:y,sourceHandle:z?V:$,target:z?y:Z,targetHandle:z?$:V};G.connection=N;let x=L&&M&&(_===g_.Strict?z&&H==="source"||!z&&H==="target":Z!==y||V!==$);G.isValid=x&&A(N),G.toHandle=PK(Z,H,V,U,_,!0)}return G}var P5={onPointerDown:IB,isValid:xK};function vK({domNode:f,panZoom:u,getTransform:_,getViewScale:y}){let $=C0(f);function l({translateExtent:J,width:F,height:A,zoomStep:U=1,pannable:z=!0,zoomable:W=!0,inversePan:K=!1}){let q=(Z)=>{if(Z.sourceEvent.type!=="wheel"||!u)return;let V=_(),L=Z.sourceEvent.ctrlKey&&J$()?10:1,M=-Z.sourceEvent.deltaY*(Z.sourceEvent.deltaMode===1?0.05:Z.sourceEvent.deltaMode?1:0.002)*U,N=V[2]*Math.pow(2,M*L);u.scaleTo(N)},E=[0,0],O=(Z)=>{if(Z.sourceEvent.type==="mousedown"||Z.sourceEvent.type==="touchstart")E=[Z.sourceEvent.clientX??Z.sourceEvent.touches[0].clientX,Z.sourceEvent.clientY??Z.sourceEvent.touches[0].clientY]},G=(Z)=>{let V=_();if(Z.sourceEvent.type!=="mousemove"&&Z.sourceEvent.type!=="touchmove"||!u)return;let L=[Z.sourceEvent.clientX??Z.sourceEvent.touches[0].clientX,Z.sourceEvent.clientY??Z.sourceEvent.touches[0].clientY],M=[L[0]-E[0],L[1]-E[1]];E=L;let N=y()*Math.max(V[2],Math.log(V[2]))*(K?-1:1),D={x:V[0]-M[0]*N,y:V[1]-M[1]*N},x=[[0,0],[F,A]];u.setViewportConstrained({x:D.x,y:D.y,zoom:V[2]},x,J)},H=zl().on("start",O).on("zoom",z?G:null).on("zoom.wheel",W?q:null);$.call(H,{})}function j(){$.on("zoom",null)}return{update:l,destroy:j,pointer:lu}}var C5=(f)=>({x:f.x,y:f.y,zoom:f.k}),dJ=({x:f,y:u,zoom:_})=>my.translate(f,u).scale(_),e3=(f,u)=>f.target.closest(`.${u}`),bK=(f,u)=>u===2&&Array.isArray(f)&&f.includes(2),cB=(f)=>((f*=2)<=1?f*f*f:(f-=2)*f*f+2)/2,eJ=(f,u=0,_=cB,y=()=>{})=>{let $=typeof u==="number"&&u>0;if(!$)y();return $?f.transition().duration(u).ease(_).on("end",y):f},hK=(f)=>{let u=f.ctrlKey&&J$()?10:1;return-f.deltaY*(f.deltaMode===1?0.05:f.deltaMode?1:0.002)*u};function pB({zoomPanValues:f,noWheelClassName:u,d3Selection:_,d3Zoom:y,panOnScrollMode:$,panOnScrollSpeed:l,zoomOnPinch:j,onPanZoomStart:J,onPanZoom:F,onPanZoomEnd:A}){return(U)=>{if(e3(U,u)){if(U.ctrlKey)U.preventDefault();return!1}U.preventDefault(),U.stopImmediatePropagation();let z=_.property("__zoom").k||1;if(U.ctrlKey&&j){let O=lu(U),G=hK(U),H=z*Math.pow(2,G);y.scaleTo(_,H,O,U);return}let W=U.deltaMode===1?20:1,K=$===Q_.Vertical?0:U.deltaX*W,q=$===Q_.Horizontal?0:U.deltaY*W;if(!J$()&&U.shiftKey&&$!==Q_.Vertical)K=U.deltaY*W,q=0;y.translateBy(_,-(K/z)*l,-(q/z)*l,{internal:!0});let E=C5(_.property("__zoom"));if(clearTimeout(f.panScrollTimeout),!f.isPanScrolling)f.isPanScrolling=!0,J?.(U,E);else F?.(U,E),f.panScrollTimeout=setTimeout(()=>{A?.(U,E),f.isPanScrolling=!1},150)}}function mB({noWheelClassName:f,preventScrolling:u,d3ZoomHandler:_}){return function(y,$){let l=y.type==="wheel",j=!u&&l&&!y.ctrlKey,J=e3(y,f);if(y.ctrlKey&&l&&J)y.preventDefault();if(j||J)return null;y.preventDefault(),_.call(this,y,$)}}function kB({zoomPanValues:f,onDraggingChange:u,onPanZoomStart:_}){return(y)=>{if(y.sourceEvent?.internal)return;let $=C5(y.transform);if(f.mouseButton=y.sourceEvent?.button||0,f.isZoomingOrPanning=!0,f.prevViewport=$,y.sourceEvent?.type==="mousedown")u(!0);if(_)_?.(y.sourceEvent,$)}}function iB({zoomPanValues:f,panOnDrag:u,onPaneContextMenu:_,onTransformChange:y,onPanZoom:$}){return(l)=>{if(f.usedRightMouseButton=!!(_&&bK(u,f.mouseButton??0)),!l.sourceEvent?.sync)y([l.transform.x,l.transform.y,l.transform.k]);if($&&!l.sourceEvent?.internal)$?.(l.sourceEvent,C5(l.transform))}}function gB({zoomPanValues:f,panOnDrag:u,panOnScroll:_,onDraggingChange:y,onPanZoomEnd:$,onPaneContextMenu:l}){return(j)=>{if(j.sourceEvent?.internal)return;if(f.isZoomingOrPanning=!1,l&&bK(u,f.mouseButton??0)&&!f.usedRightMouseButton&&j.sourceEvent)l(j.sourceEvent);if(f.usedRightMouseButton=!1,y(!1),$){let J=C5(j.transform);f.prevViewport=J,clearTimeout(f.timerId),f.timerId=setTimeout(()=>{$?.(j.sourceEvent,J)},_?150:0)}}}function nB({zoomActivationKeyPressed:f,zoomOnScroll:u,zoomOnPinch:_,panOnDrag:y,panOnScroll:$,zoomOnDoubleClick:l,userSelectionActive:j,noWheelClassName:J,noPanClassName:F,lib:A,connectionInProgress:U}){return(z)=>{let W=f||u,K=_&&z.ctrlKey,q=z.type==="wheel";if(z.button===1&&z.type==="mousedown"&&(e3(z,`${A}-flow__node`)||e3(z,`${A}-flow__edge`)))return!0;if(!y&&!W&&!$&&!l&&!_)return!1;if(j)return!1;if(U&&!q)return!1;if(e3(z,J)&&q)return!1;if(e3(z,F)&&(!q||$&&q&&!f))return!1;if(!_&&z.ctrlKey&&q)return!1;if(!_&&z.type==="touchstart"&&z.touches?.length>1)return z.preventDefault(),!1;if(!W&&!$&&!K&&q)return!1;if(!y&&(z.type==="mousedown"||z.type==="touchstart"))return!1;if(Array.isArray(y)&&!y.includes(z.button)&&z.type==="mousedown")return!1;let E=Array.isArray(y)&&y.includes(z.button)||!z.button||z.button<=1;return(!z.ctrlKey||q)&&E}}function IK({domNode:f,minZoom:u,maxZoom:_,translateExtent:y,viewport:$,onPanZoom:l,onPanZoomStart:j,onPanZoomEnd:J,onDraggingChange:F}){let A={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},U=f.getBoundingClientRect(),z=zl().scaleExtent([u,_]).translateExtent(y),W=C0(f).call(z);H({x:$.x,y:$.y,zoom:f$($.zoom,u,_)},[[0,0],[U.width,U.height]],y);let K=W.on("wheel.zoom"),q=W.on("dblclick.zoom");z.wheelDelta(hK);function E(v,C){if(W)return new Promise((P)=>{z?.interpolate(C?.interpolate==="linear"?x1:cy).transform(eJ(W,C?.duration,C?.ease,()=>P(!0)),v)});return Promise.resolve(!1)}function O({noWheelClassName:v,noPanClassName:C,onPaneContextMenu:P,userSelectionActive:w,panOnScroll:r,panOnDrag:S,panOnScrollMode:T,panOnScrollSpeed:Y,preventScrolling:R,zoomOnPinch:m,zoomOnScroll:p,zoomOnDoubleClick:n,zoomActivationKeyPressed:_f,lib:t,onTransformChange:ff,connectionInProgress:Gf,paneClickDistance:zf,selectionOnDrag:jf}){if(w&&!A.isZoomingOrPanning)G();let Wf=r&&!_f&&!w;z.clickDistance(jf?1/0:!u1(zf)||zf<0?0:zf);let Vf=Wf?pB({zoomPanValues:A,noWheelClassName:v,d3Selection:W,d3Zoom:z,panOnScrollMode:T,panOnScrollSpeed:Y,zoomOnPinch:m,onPanZoomStart:j,onPanZoom:l,onPanZoomEnd:J}):mB({noWheelClassName:v,preventScrolling:R,d3ZoomHandler:K});if(W.on("wheel.zoom",Vf,{passive:!1}),!w){let h=kB({zoomPanValues:A,onDraggingChange:F,onPanZoomStart:j});z.on("start",h);let g=iB({zoomPanValues:A,panOnDrag:S,onPaneContextMenu:!!P,onPanZoom:l,onTransformChange:ff});z.on("zoom",g);let I=gB({zoomPanValues:A,panOnDrag:S,panOnScroll:r,onPaneContextMenu:P,onPanZoomEnd:J,onDraggingChange:F});z.on("end",I)}let Zf=nB({zoomActivationKeyPressed:_f,panOnDrag:S,zoomOnScroll:p,panOnScroll:r,zoomOnDoubleClick:n,zoomOnPinch:m,userSelectionActive:w,noPanClassName:C,noWheelClassName:v,lib:t,connectionInProgress:Gf});if(z.filter(Zf),n)W.on("dblclick.zoom",q);else W.on("dblclick.zoom",null)}function G(){z.on("zoom",null)}async function H(v,C,P){let w=dJ(v),r=z?.constrain()(w,C,P);if(r)await E(r);return new Promise((S)=>S(r))}async function Z(v,C){let P=dJ(v);return await E(P,C),new Promise((w)=>w(P))}function V(v){if(W){let C=dJ(v),P=W.property("__zoom");if(P.k!==v.zoom||P.x!==v.x||P.y!==v.y)z?.transform(W,C,null,{sync:!0})}}function L(){let v=W?Wl(W.node()):{x:0,y:0,k:1};return{x:v.x,y:v.y,zoom:v.k}}function M(v,C){if(W)return new Promise((P)=>{z?.interpolate(C?.interpolate==="linear"?x1:cy).scaleTo(eJ(W,C?.duration,C?.ease,()=>P(!0)),v)});return Promise.resolve(!1)}function N(v,C){if(W)return new Promise((P)=>{z?.interpolate(C?.interpolate==="linear"?x1:cy).scaleBy(eJ(W,C?.duration,C?.ease,()=>P(!0)),v)});return Promise.resolve(!1)}function D(v){z?.scaleExtent(v)}function x(v){z?.translateExtent(v)}function c(v){let C=!u1(v)||v<0?0:v;z?.clickDistance(C)}return{update:O,destroy:G,setViewport:Z,setViewportConstrained:H,getViewport:L,scaleTo:M,scaleBy:N,setScaleExtent:D,setTranslateExtent:x,syncViewport:V,setClickDistance:c}}var s_;(function(f){f.Line="line",f.Handle="handle"})(s_||(s_={}));function tB({width:f,prevWidth:u,height:_,prevHeight:y,affectsX:$,affectsY:l}){let j=f-u,J=_-y,F=[j>0?1:j<0?-1:0,J>0?1:J<0?-1:0];if(j&&$)F[0]=F[0]*-1;if(J&&l)F[1]=F[1]*-1;return F}function WK(f){let u=f.includes("right")||f.includes("left"),_=f.includes("bottom")||f.includes("top"),y=f.includes("left"),$=f.includes("top");return{isHorizontal:u,isVertical:_,affectsX:y,affectsY:$}}function k_(f,u){return Math.max(0,u-f)}function i_(f,u){return Math.max(0,f-u)}function O5(f,u,_){return Math.max(0,u-f,f-_)}function zK(f,u){return f?!u:u}function sB(f,u,_,y,$,l,j,J){let{affectsX:F,affectsY:A}=u,{isHorizontal:U,isVertical:z}=u,W=U&&z,{xSnapped:K,ySnapped:q}=_,{minWidth:E,maxWidth:O,minHeight:G,maxHeight:H}=y,{x:Z,y:V,width:L,height:M,aspectRatio:N}=f,D=Math.floor(U?K-f.pointerX:0),x=Math.floor(z?q-f.pointerY:0),c=L+(F?-D:D),v=M+(A?-x:x),C=-l[0]*L,P=-l[1]*M,w=O5(c,E,O),r=O5(v,G,H);if(j){let Y=0,R=0;if(F&&D<0)Y=k_(Z+D+C,j[0][0]);else if(!F&&D>0)Y=i_(Z+c+C,j[1][0]);if(A&&x<0)R=k_(V+x+P,j[0][1]);else if(!A&&x>0)R=i_(V+v+P,j[1][1]);w=Math.max(w,Y),r=Math.max(r,R)}if(J){let Y=0,R=0;if(F&&D>0)Y=i_(Z+D,J[0][0]);else if(!F&&D<0)Y=k_(Z+c,J[1][0]);if(A&&x>0)R=i_(V+x,J[0][1]);else if(!A&&x<0)R=k_(V+v,J[1][1]);w=Math.max(w,Y),r=Math.max(r,R)}if($){if(U){let Y=O5(c/N,G,H)*N;if(w=Math.max(w,Y),j){let R=0;if(!F&&!A||F&&!A&&W)R=i_(V+P+c/N,j[1][1])*N;else R=k_(V+P+(F?D:-D)/N,j[0][1])*N;w=Math.max(w,R)}if(J){let R=0;if(!F&&!A||F&&!A&&W)R=k_(V+c/N,J[1][1])*N;else R=i_(V+(F?D:-D)/N,J[0][1])*N;w=Math.max(w,R)}}if(z){let Y=O5(v*N,E,O)/N;if(r=Math.max(r,Y),j){let R=0;if(!F&&!A||A&&!F&&W)R=i_(Z+v*N+C,j[1][0])/N;else R=k_(Z+(A?x:-x)*N+C,j[0][0])/N;r=Math.max(r,R)}if(J){let R=0;if(!F&&!A||A&&!F&&W)R=k_(Z+v*N,J[1][0])/N;else R=i_(Z+(A?x:-x)*N,J[0][0])/N;r=Math.max(r,R)}}}if(x=x+(x<0?r:-r),D=D+(D<0?w:-w),$)if(W)if(c>v*N)x=(zK(F,A)?-D:D)/N;else D=(zK(F,A)?-x:x)*N;else if(U)x=D/N,A=F;else D=x*N,F=A;let S=F?Z+D:Z,T=A?V+x:V;return{width:L+(F?-D:D),height:M+(A?-x:x),x:l[0]*D*(!F?1:-1)+S,y:l[1]*x*(!A?1:-1)+T}}var cK={width:0,height:0,x:0,y:0},oB={...cK,pointerX:0,pointerY:0,aspectRatio:1};function aB(f){return[[0,0],[f.measured.width,f.measured.height]]}function dB(f,u,_){let y=u.position.x+f.position.x,$=u.position.y+f.position.y,l=f.measured.width??0,j=f.measured.height??0,J=_[0]*l,F=_[1]*j;return[[y-J,$-F],[y+l-J,$+j-F]]}function pK({domNode:f,nodeId:u,getStoreItems:_,onChange:y,onEnd:$}){let l=C0(f),j={controlDirection:WK("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function J({controlPosition:A,boundaries:U,keepAspectRatio:z,resizeDirection:W,onResizeStart:K,onResize:q,onResizeEnd:E,shouldResize:O}){let G={...cK},H={...oB};j={boundaries:U,resizeDirection:W,keepAspectRatio:z,controlDirection:WK(A)};let Z=void 0,V=null,L=[],M=void 0,N=void 0,D=void 0,x=!1,c=s6().on("start",(v)=>{let{nodeLookup:C,transform:P,snapGrid:w,snapToGrid:r,nodeOrigin:S,paneDomNode:T}=_();if(Z=C.get(u),!Z)return;V=T?.getBoundingClientRect()??null;let{xSnapped:Y,ySnapped:R}=Gl(v.sourceEvent,{transform:P,snapGrid:w,snapToGrid:r,containerBounds:V});if(G={width:Z.measured.width??0,height:Z.measured.height??0,x:Z.position.x??0,y:Z.position.y??0},H={...G,pointerX:Y,pointerY:R,aspectRatio:G.width/G.height},M=void 0,Z.parentId&&(Z.extent==="parent"||Z.expandParent))M=C.get(Z.parentId),N=M&&Z.extent==="parent"?aB(M):void 0;L=[],D=void 0;for(let[m,p]of C)if(p.parentId===u){if(L.push({id:m,position:{...p.position},extent:p.extent}),p.extent==="parent"||p.expandParent){let n=dB(p,Z,p.origin??S);if(D)D=[[Math.min(n[0][0],D[0][0]),Math.min(n[0][1],D[0][1])],[Math.max(n[1][0],D[1][0]),Math.max(n[1][1],D[1][1])]];else D=n}}K?.(v,{...G})}).on("drag",(v)=>{let{transform:C,snapGrid:P,snapToGrid:w,nodeOrigin:r}=_(),S=Gl(v.sourceEvent,{transform:C,snapGrid:P,snapToGrid:w,containerBounds:V}),T=[];if(!Z)return;let{x:Y,y:R,width:m,height:p}=G,n={},_f=Z.origin??r,{width:t,height:ff,x:Gf,y:zf}=sB(H,j.controlDirection,S,j.boundaries,j.keepAspectRatio,_f,N,D),jf=t!==m,Wf=ff!==p,Vf=Gf!==Y&&jf,Zf=zf!==R&&Wf;if(!Vf&&!Zf&&!jf&&!Wf)return;if(Vf||Zf||_f[0]===1||_f[1]===1){if(n.x=Vf?Gf:G.x,n.y=Zf?zf:G.y,G.x=n.x,G.y=n.y,L.length>0){let $f=Gf-Y,lf=zf-R;for(let Af of L)Af.position={x:Af.position.x-$f+_f[0]*(t-m),y:Af.position.y-lf+_f[1]*(ff-p)},T.push(Af)}}if(jf||Wf)n.width=jf&&(!j.resizeDirection||j.resizeDirection==="horizontal")?t:G.width,n.height=Wf&&(!j.resizeDirection||j.resizeDirection==="vertical")?ff:G.height,G.width=n.width,G.height=n.height;if(M&&Z.expandParent){let $f=_f[0]*(n.width??0);if(n.x&&n.x<$f)G.x=$f,H.x=H.x-(n.x-$f);let lf=_f[1]*(n.height??0);if(n.y&&n.y{if(!x)return;E?.(v,{...G}),$?.({...G}),x=!1});l.call(c)}function F(){l.on(".drag",null)}return{update:J,destroy:F}}var fZ=rf(I0(),1),uZ=rf(oK(),1);var aK=(f)=>{let u,_=new Set,y=(U,z)=>{let W=typeof U==="function"?U(u):U;if(!Object.is(W,u)){let K=u;u=(z!=null?z:typeof W!=="object"||W===null)?W:Object.assign({},u,W),_.forEach((q)=>q(u,K))}},$=()=>u,F={setState:y,getState:$,getInitialState:()=>A,subscribe:(U)=>{return _.add(U),()=>_.delete(U)},destroy:()=>{_.clear()}},A=u=f(y,$,F);return F},dK=(f)=>f?aK(f):aK;var{useDebugValue:Zw}=fZ.default,{useSyncExternalStoreWithSelector:qw}=uZ.default,Hw=(f)=>f;function BF(f,u=Hw,_){let y=qw(f.subscribe,f.getState,f.getServerState||f.getInitialState,u,_);return Zw(y),y}var eK=(f,u)=>{let _=dK(f),y=($,l=u)=>BF(_,$,l);return Object.assign(y,_),y},_Z=(f,u)=>f?eK(f,u):eK;function A0(f,u){if(Object.is(f,u))return!0;if(typeof f!=="object"||f===null||typeof u!=="object"||u===null)return!1;if(f instanceof Map&&u instanceof Map){if(f.size!==u.size)return!1;for(let[y,$]of f)if(!Object.is($,u.get(y)))return!1;return!0}if(f instanceof Set&&u instanceof Set){if(f.size!==u.size)return!1;for(let y of f)if(!u.has(y))return!1;return!0}let _=Object.keys(f);if(_.length!==Object.keys(u).length)return!1;for(let y of _)if(!Object.prototype.hasOwnProperty.call(u,y)||!Object.is(f[y],u[y]))return!1;return!0}var Ew=rf(g7(),1),h5=d.createContext(null),Vw=h5.Provider,BZ=hu.error001();function mf(f,u){let _=d.useContext(h5);if(_===null)throw Error(BZ);return BF(_,f,u)}function W0(){let f=d.useContext(h5);if(f===null)throw Error(BZ);return d.useMemo(()=>({getState:f.getState,setState:f.setState,subscribe:f.subscribe}),[f])}var yZ={display:"none"},Ow={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},wZ="react-flow__node-desc",DZ="react-flow__edge-desc",Xw="react-flow__aria-live",Nw=(f)=>f.ariaLiveMessage,Lw=(f)=>f.ariaLabelConfig;function Yw({rfId:f}){let u=mf(Nw);return o.jsx("div",{id:`${Xw}-${f}`,"aria-live":"assertive","aria-atomic":"true",style:Ow,children:u})}function Bw({rfId:f,disableKeyboardA11y:u}){let _=mf(Lw);return o.jsxs(o.Fragment,{children:[o.jsx("div",{id:`${wZ}-${f}`,style:yZ,children:u?_["node.a11yDescription.default"]:_["node.a11yDescription.keyboardDisabled"]}),o.jsx("div",{id:`${DZ}-${f}`,style:yZ,children:_["edge.a11yDescription.default"]}),!u&&o.jsx(Yw,{rfId:f})]})}var I5=d.forwardRef(({position:f="top-left",children:u,className:_,style:y,...$},l)=>{let j=`${f}`.split("-");return o.jsx("div",{className:Y0(["react-flow__panel",_,...j]),style:y,ref:l,...$,children:u})});I5.displayName="Panel";function ww({proOptions:f,position:u="bottom-right"}){if(f?.hideAttribution)return null;return o.jsx(I5,{position:u,className:"react-flow__attribution","data-message":"Please only hide this attribution when you are subscribed to React Flow Pro: https://pro.reactflow.dev",children:o.jsx("a",{href:"https://reactflow.dev",target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}var Dw=(f)=>{let u=[],_=[];for(let[,y]of f.nodeLookup)if(y.selected)u.push(y.internals.userNode);for(let[,y]of f.edgeLookup)if(y.selected)_.push(y);return{selectedNodes:u,selectedEdges:_}},x5=(f)=>f.id;function Tw(f,u){return A0(f.selectedNodes.map(x5),u.selectedNodes.map(x5))&&A0(f.selectedEdges.map(x5),u.selectedEdges.map(x5))}function Mw({onSelectionChange:f}){let u=W0(),{selectedNodes:_,selectedEdges:y}=mf(Dw,Tw);return d.useEffect(()=>{let $={nodes:_,edges:y};f?.($),u.getState().onSelectionChangeHandlers.forEach((l)=>l($))},[_,y,f]),null}var Sw=(f)=>!!f.onSelectionChangeHandlers;function rw({onSelectionChange:f}){let u=mf(Sw);if(f||u)return o.jsx(Mw,{onSelectionChange:f});return null}var TF=typeof window<"u"?d.useLayoutEffect:d.useEffect,TZ=[0,0],Pw={x:0,y:0,zoom:1},Cw=["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"],$Z=[...Cw,"rfId"],Rw=(f)=>({setNodes:f.setNodes,setEdges:f.setEdges,setMinZoom:f.setMinZoom,setMaxZoom:f.setMaxZoom,setTranslateExtent:f.setTranslateExtent,setNodeExtent:f.setNodeExtent,reset:f.reset,setDefaultNodesAndEdges:f.setDefaultNodesAndEdges}),lZ={translateExtent:_$,nodeOrigin:TZ,minZoom:0.5,maxZoom:2,elementsSelectable:!0,noPanClassName:"nopan",rfId:"1"};function xw(f){let{setNodes:u,setEdges:_,setMinZoom:y,setMaxZoom:$,setTranslateExtent:l,setNodeExtent:j,reset:J,setDefaultNodesAndEdges:F}=mf(Rw,A0),A=W0();TF(()=>{return F(f.defaultNodes,f.defaultEdges),()=>{U.current=lZ,J()}},[]);let U=d.useRef(lZ);return TF(()=>{for(let z of $Z){let W=f[z],K=U.current[z];if(W===K)continue;if(typeof f[z]>"u")continue;if(z==="nodes")u(W);else if(z==="edges")_(W);else if(z==="minZoom")y(W);else if(z==="maxZoom")$(W);else if(z==="translateExtent")l(W);else if(z==="nodeExtent")j(W);else if(z==="ariaLabelConfig")A.setState({ariaLabelConfig:OK(W)});else if(z==="fitView")A.setState({fitViewQueued:W});else if(z==="fitViewOptions")A.setState({fitViewOptions:W});else A.setState({[z]:W})}U.current=f},$Z.map((z)=>f[z])),null}function jZ(){if(typeof window>"u"||!window.matchMedia)return null;return window.matchMedia("(prefers-color-scheme: dark)")}function vw(f){let[u,_]=d.useState(f==="system"?null:f);return d.useEffect(()=>{if(f!=="system"){_(f);return}let y=jZ(),$=()=>_(y?.matches?"dark":"light");return $(),y?.addEventListener("change",$),()=>{y?.removeEventListener("change",$)}},[f]),u!==null?u:jZ()?.matches?"dark":"light"}var JZ=typeof document<"u"?document:null;function El(f=null,u={target:JZ,actInsideInputWithModifier:!0}){let[_,y]=d.useState(!1),$=d.useRef(!1),l=d.useRef(new Set([])),[j,J]=d.useMemo(()=>{if(f!==null){let A=(Array.isArray(f)?f:[f]).filter((z)=>typeof z==="string").map((z)=>z.replace("+",` +本次任务:`,y=u.indexOf(_);if(y===-1)return f;return u.slice(y+_.length).trimStart()}function ry(f){return f.length>0?f.split(/\r\n|\r|\n/u).length:0}function tG(f){let u=String(f?.displayPrompt||"");if(u.length>0)return u;let _=String(f?.prompt||"");return SX(PX(_).userPrompt)}function b_(f){return f?._traceSummary&&typeof f._traceSummary==="object"&&!Array.isArray(f._traceSummary)?f._traceSummary:null}function B4(f){return f?._promptDetails&&typeof f._promptDetails==="object"&&!Array.isArray(f._promptDetails)?f._promptDetails:{}}function Xj(f){let u=b_(f)?.prompt;return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function Zj(f){let u=b_(f)?.execution;return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function CX(f){let u=Xj(f),_=String(u.basePrompt||"");return _.length>0?_:tG(f)}function qj(f){let u=b_(f);return String(u?.finalResponse||f?.finalResponse||"").trimEnd()}function Ej(f){let _=b_(f)?.lastJudge||f?.lastJudge;return _&&typeof _==="object"&&!Array.isArray(_)?_:null}function v_(f){return f&&typeof f==="object"&&!Array.isArray(f)?f:null}function RX(f){let u=b_(f)?.attempts;if(Array.isArray(u)&&u.length>0)return u;let _=nG(f);if(_.length>0)return _.map((j,J)=>({...j,index:Number(j?.index||J+1),execution:J===_.length-1?Zj(f):v_(j?.execution)||{},finalResponse:String(j?.finalResponse||j?.finalResponsePreview||(J===_.length-1?qj(f):"")),judge:v_(j?.judge)||(J===_.length-1?Ej(f):null)}));let y=Zj(f),l=qj(f),$=Ej(f);if(Object.keys(y).length===0&&l.length===0&&$===null)return[];return[{index:Number(f?.currentAttempt||1),mode:f?.currentMode||"initial",startedAt:f?.startedAt,finishedAt:f?.finishedAt,terminalStatus:f?.status,execution:y,finalResponse:l,finalResponseChars:l.length,judge:$}]}function xX(f,u){return v_(u?.execution)||Zj(f)}function vX(f,u,_,y){let l=b_(f),$=Number(l?.currentAttempt||f?.currentAttempt||0),j=Number(_),J=Number.isFinite(j)&&j>0&&j===$,F=WX(f?.updatedAt,l?.updatedAt);if(J&&!u?.finishedAt&&F.length>0)return F;return String(u?.updatedAt||u?.finishedAt||y.effectiveEndAt||(J?F:"")||F||f?.finishedAt||f?.startedAt||"")}function bX(f,u){let _=String(u?.finalResponse||u?.finalResponsePreview||"");if(Object.prototype.hasOwnProperty.call(u||{},"finalResponse")||Object.prototype.hasOwnProperty.call(u||{},"finalResponsePreview"))return _.trimEnd();return _.length>0?_.trimEnd():qj(f)}function sG(f,u){if(Object.prototype.hasOwnProperty.call(u||{},"judge"))return v_(u?.judge);return Ej(f)}function oG(f){return`feedback:${String(f||"latest")}`}function hX(f,u,_){let y=String(u?.feedbackPrompt||"").trimEnd(),l=String(u?.feedbackPromptPreview||y||"").trimEnd(),$=Number(u?.feedbackPromptChars||y.length||l.length||0),j=Number(u?.feedbackPromptLines||ry(y||l));if(y.length>0||l.length>0||$>0)return{text:y,preview:l,chars:$,lines:j,source:u?.feedbackPromptSource||"judge-feedback",forAttempt:u?.feedbackPromptForAttempt||Number(_||0)+1,truncated:Boolean(u?.feedbackPromptTruncated)};let J=sG(f,u),F=String(J?.continuePrompt||"").trimEnd();if(J?.decision==="retry"&&F.length>0)return{text:"",preview:F,chars:F.length,lines:ry(F),source:"judge-continue-prompt",forAttempt:Number(_||0)+1,truncated:!1};return null}function IX(f){let u=Xj(f);return Boolean(u.hasReferenceInjection||Number(u.referencePromptChars||0)>0||f?.referenceInjection||f?.referenceInjectionSummary)}function cX(f,u=null){if(u!==null&&u!==void 0){let y=(v_(f?._traceStepsByAttempt)||{})[String(u)];return Array.isArray(y)?y:[]}return Array.isArray(f?._traceSteps)?f._traceSteps:[]}function cl(f){return(Array.isArray(f?.summaryLines)?f.summaryLines:[]).map((u)=>String(u||""))}function D4(f){let u=String(f?.status||"").trim();if(u.length>0)return u;let _=cl(f).join(` +`);return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(_)?.[1]||""}function hG(f){return/^item\/(?:started|completed): file changes status=/u.test(String(f||"").trim())}function pX(f){let u=cl(f);for(let y=u.length-1;y>=0;y-=1){let l=/file changes status=([A-Za-z0-9_-]+)/u.exec(u[y]||"")?.[1];if(l)return l}let _=D4(f);if(_==="item/fileChange/outputDelta")return"updated";if(_==="item/started")return"started";if(_==="item/completed")return"completed";return _.replace(/^item\//u,"")||String(f?.status||"changed")}function kX(f){if(String(f?.kind||"")!=="edited")return!1;let u=String(f?.title||""),_=String(f?.status||""),y=cl(f).join(` +`);if(u==="Edited files")return!0;if(/^item\/fileChange\//u.test(_))return!0;if((_==="item/started"||_==="item/completed")&&/file changes status=/u.test(y))return!0;if(/^Success\. Updated the following files:/mu.test(y))return!0;if(/^diff --git /mu.test(y))return!0;return/^([AMDRCU?]{1,2})\s+\S+/mu.test(y)}function mX(f){if(f.length<=1)return f[0];let u=f.find(($)=>D4($)==="item/fileChange/outputDelta")||f.find(($)=>cl($).some((j)=>!hG(j)))||f.at(-1)||f[0],_=f.flatMap(($)=>Array.isArray($?.rawSeqs)?$.rawSeqs:[$?.seq]).filter(($)=>$!==void 0),y=f.flatMap(cl).filter(($)=>$.trim().length>0&&!hG($)),l=f[f.length-1]||u;return{...u,at:u?.at||l?.at,title:String(u?.title||"Edited files"),status:pX(l),summaryLines:y.length>0?y:cl(u),rawSeqs:_}}function iX(f){let u=Array.isArray(f)?f:[],_=[],y=[],l=()=>{if(y.length>0)_.push(mX(y));y=[]};for(let $ of u){if(kX($)){if(D4($)==="item/started"&&y.length>0)l();if(y.push($),D4($)==="item/completed")l();continue}l(),_.push($)}return l(),_}function gX(f,u){if(u.length===0)return f;let _=u.reduce((y,l)=>{let $=String(l?.kind||"");if($==="explored")y.readCount+=1;else if($==="edited")y.editCount+=1;else if($==="ran")y.runCount+=1;return y},{readCount:0,editCount:0,runCount:0});return{...f,..._,toolCallCount:_.readCount+_.editCount+_.runCount,stepCount:u.length}}function aG(f,u=null){if(u!==null&&u!==void 0){let _=v_(f?._traceStepsLoadedByAttempt)||{};return Boolean(_[String(u)])}return Boolean(f?._traceStepsLoaded)}function Hj(f){return f?._traceStepDetails&&typeof f._traceStepDetails==="object"&&!Array.isArray(f._traceStepDetails)?f._traceStepDetails:{}}function nX(f,u){let _=Number(f?.index);return Number.isFinite(_)?_:u+1}function dG(f,u){return Boolean(f?.synthetic)||Number(u)<=0}function r4(f){let u=Number(f);return Number.isFinite(u)?String(u):void 0}function tX(f){let u=f?.timing&&typeof f.timing==="object"?f.timing:{},_=String(f?.status||"");if(["queued"].includes(_))return`等待 ${X4(u.queueWaitMs??u.totalElapsedMs)}`;if(["running","judging","retry_wait"].includes(_))return`耗时 ${X4(u.durationMs??u.totalElapsedMs)}`;return`耗时 ${X4(u.durationMs??u.totalElapsedMs)}`}function w4(f){return String(f?.queueId||"default")}function sX(f){return{system:"SYS",user:"YOU",assistant:"GPT",reasoning:"THINK",command:"CMD",diff:"DIFF",tool:"TOOL",error:"ERR"}[f]||f.toUpperCase()}function IG(f){return["running","judging","retry_wait"].includes(String(f?.status||""))}function d1(f){return["succeeded","failed","canceled"].includes(String(f?.status||""))}function hl(f){if(!d1(f))return!1;if(f?.terminalUnread===!0)return!0;if(f?.terminalUnread===!1)return!1;return!f?.readAt}function S$(f){let u=Number(f||0);return Number.isFinite(u)?u:0}function oX(f){return S$(f.queued)+S$(f.retry_wait)}function aX(f){return S$(f.running)+S$(f.judging)}function cG(f){if(hl(f))return 0;return{running:1,judging:2,retry_wait:3,queued:4,succeeded:8,failed:8,canceled:8}[String(f?.status||"")]??9}function M$(f){if(!f)return!1;if(f?._traceSummaryLoaded===!0)return!1;return f?.summaryOnly===!0||f?._metaLoaded!==!0}function dX(f){return Boolean(f?._metaLoaded)||f?.summaryOnly===!1}function eX(f,u,_){let y=String(f?.[_]||""),l=String(u?.[_]||"");return y.length>l.length?y:l}function Vj(f,u,_){let y=Array.isArray(f?.[_])?f[_]:[],l=Array.isArray(u?.[_])?u[_]:[];if(l.length===0&&y.length>0)return y;return y.length>l.length?y:l}function fN(f,u){let _=u?.summaryOnly===!0&&dX(f),y={...f,...u};if(!_)return y;for(let l of["prompt","basePrompt","displayPrompt","finalResponse"])y[l]=eX(f,u,l);for(let l of["promptHistory","attempts","output","events"])y[l]=Vj(f,u,l);if(f?.referenceInjection?.items&&!u?.referenceInjection?.items)y.referenceInjection=f.referenceInjection;if(f?.referenceInjectionSummary&&!u?.referenceInjectionSummary)y.referenceInjectionSummary=f.referenceInjectionSummary;y.summaryOnly=f?.summaryOnly===!1?!1:u.summaryOnly,y._metaLoaded=f?._metaLoaded,y._detailLoaded=f?._detailLoaded,y._transcriptComplete=f?._transcriptComplete,y._transcriptPreview=Object.prototype.hasOwnProperty.call(u,"_transcriptPreview")?u._transcriptPreview:f?._transcriptPreview;for(let l of["_traceSummary","_traceSummaryLoaded","_traceSteps","_traceStepsLoaded","_traceStepsByAttempt","_traceStepsLoadedByAttempt","_traceStepDetails","_promptDetails"])if(!Object.prototype.hasOwnProperty.call(u,l)&&Object.prototype.hasOwnProperty.call(f||{},l))y[l]=f[l];return y}function uN(f){let u=f?.selected,_=u?.task&&typeof u.task==="object"?u.task:null;if(_!==null){let l=Boolean(u?.preview);return{..._,transcript:Array.isArray(u?.transcript)?u.transcript:[],_detailLoaded:Array.isArray(u?.transcript)&&u.transcript.length>0,_transcriptComplete:Boolean(!l&&!u?.hasMore&&d1(_)),_transcriptPreview:l,_summaryLoaded:!0}}let y=Z1(f)[0];return y?{...y,_summaryLoaded:!0}:null}function Uj(f,u){let _=new Map;for(let y of[...Array.isArray(f)?f:[],...Array.isArray(u)?u:[]]){let l=`${Number(y?.seq??0)}:${String(y?.kind||"message")}`,$=_.get(l);if(!$){_.set(l,y);continue}let j={...$,...y};for(let[J,F]of[["bodyPreview","bodyOmittedLines"],["commandPreview","commandOmittedLines"]]){let A=String($?.[J]||""),U=String(y?.[J]||"");if(A.length>U.length)j[J]=$[J],j[F]=$[F]}_.set(l,j)}return Array.from(_.values()).sort((y,l)=>Number(y?.seq??0)-Number(l?.seq??0))}function O4(f){return(Array.isArray(f)?f:[]).reduce((u,_)=>Math.max(u,Number(_?.seq??0)),0)}function pG(f,u=8){let _=Array.from(new Set((Array.isArray(f)?f:[]).map((l)=>Number(l?.seq??0)).filter((l)=>Number.isFinite(l)&&l>0))).sort((l,$)=>l-$);if(_.length===0)return 0;let y=_[Math.max(0,_.length-u)]??0;return Math.max(0,y-0.001)}function Wj(f,u){let _=Number(f[u]??0);return Number.isFinite(_)?String(_):"0"}function _N(f,u){let _=Array.isArray(f?.codexModels)?f.codexModels:[],y=["gpt-5.5","gpt-5.4-mini","gpt-5.4"];return Array.from(new Set([..._,...y,u].map((l)=>String(l||"").trim()).filter(Boolean)))}function yN({task:f,selected:u,onSelect:_,onCopy:y,onReference:l,onMarkRead:$,copied:j,markingRead:J}){let F=f?.lastJudge||{},A=String(f?.id||""),U=hl(f);return T("article",{role:"button",tabIndex:0,className:`codex-task-card ${u?"selected":""} ${U?"unread-terminal":""}`,onClick:_,onKeyDown:(G)=>{if(G.key==="Enter"||G.key===" ")G.preventDefault(),_()},"data-unread-terminal":U?"true":"false","data-testid":`codex-task-${f?.id||"unknown"}`},U?T("span",{className:"codex-unread-badge",title:"待读","aria-label":"待读","data-testid":`codex-unread-task-${A||"unknown"}`}):null,T("div",{className:"codex-task-card-head"},T("div",{className:"codex-task-status-line"},T(x_,{status:f?.status},f?.status||"unknown")),T("span",{className:"mono-text"},`${f?.currentAttempt||0}/${f?.maxAttempts||0}`)),T("div",{className:"codex-task-id-row"},T("code",{title:A},A||"unknown"),T("div",{className:"codex-task-id-actions"},T("button",{type:"button",className:"codex-copy-id-btn",onClick:(G)=>{G.stopPropagation(),l(A)},"data-testid":`codex-reference-task-${A||"unknown"}`},"引用"),T("button",{type:"button",className:"codex-copy-id-btn",onClick:(G)=>{G.stopPropagation(),y(A)},"data-testid":`codex-copy-task-id-${A||"unknown"}`},j?"已复制":"复制ID"),U?T("button",{type:"button",className:"codex-copy-id-btn codex-mark-read-btn",disabled:Boolean(J),onClick:(G)=>{G.stopPropagation(),$(A)},"data-testid":`codex-mark-task-read-${A||"unknown"}`},J?"标记中":"标为已读"):null)),T("strong",null,iG(tG(f),120)||"空任务"),T("div",{className:"codex-task-meta"},T("span",null,`queue=${w4(f)}`),T("span",null,f?.model||"--"),T("span",null,tX(f))),T("div",{className:"codex-task-meta"},T("span",null,zf(f?.updatedAt))),F?.decision?T("div",{className:"codex-judge-line"},`judge=${F.decision} ${Math.round(Number(F.confidence||0)*100)}%`):null)}function Gj({title:f,tasks:u,selectedId:_,onSelect:y,onCopy:l,onReference:$,onMarkRead:j,copiedTaskId:J,markingReadTaskId:F,emptyText:A}){let U=Array.isArray(u)?u:[];return T("section",{className:"codex-task-section"},T("div",{className:"codex-task-section-head"},T("span",null,f),T("code",null,String(U.length))),U.length===0?T("p",{className:"codex-task-section-empty"},A):T("div",{className:"codex-task-section-list"},U.map((G)=>T(yN,{key:G.id,task:G,selected:_===G.id,onSelect:()=>y(G.id),onCopy:l,onReference:$,onMarkRead:j,copied:J===G.id,markingRead:F===G.id}))))}function lN({task:f,queueRows:u,busy:_,onMove:y}){let l=String(f?.id||""),$=w4(f),[j,J]=u0($);P$(()=>{J($)},[l,$]);let F=!l||_||["running","judging","retry_wait"].includes(String(f?.status||""));return T("div",{className:"codex-task-move-control","data-testid":"codex-task-queue-move-control"},T("label",null,"任务 queue",T("select",{value:j,disabled:!l||_,onChange:(A)=>J(String(A.target.value||$)),"data-testid":"codex-task-queue-move-select"},u.map((A)=>T("option",{key:String(A?.id||""),value:String(A?.id||"")},Kj(A))))),T("button",{type:"button",className:"ghost-btn",disabled:F||j===$,onClick:()=>y(j),title:F?"运行中 / judging / retry_wait 的任务不能移动;请先打断或等当前 turn 结束":"移动已创建任务到另一个 queue","data-testid":"codex-task-queue-move-button"},"移动"))}function kG(f,u=4){let _=(Array.isArray(f)?f:[]).map((l)=>String(l||"").trim()).filter(Boolean);if(_.length===0)return"--";let y=_.slice(0,u).join(" / ");return _.length>u?`${y} +${_.length-u}`:y}function $N({task:f,loading:u,onLoadPromptPart:_,testId:y="codex-initial-prompt-full",textTestId:l="codex-initial-prompt-full-text",baseTextTestId:$="codex-initial-prompt-base"}){let j=Xj(f),J=B4(f),F=CX(f).trimEnd(),A=String(J.full?.text||""),U=IX(f),G=Number(j.promptChars||f?.promptChars||A.length),W=Number(j.basePromptLines||ry(F)),K=Number(j.promptLines||ry(A));return T("section",{className:"codex-progressive-card codex-progressive-prompt","data-testid":"codex-progressive-prompt"},T("div",{className:"codex-progressive-card-head"},T("span",{className:"codex-output-channel"},"Prompt"),T("strong",null,"Submitted prompt / 原始用户 prompt"),T("code",null,`${W||ry(F)} lines / ${F.length} chars`)),T("pre",{className:"codex-prompt-full","data-testid":$},F||"空 prompt"),U?T("details",{className:"codex-reference-injection codex-progressive-full-prompt","data-testid":y,onToggle:(E)=>{if(E.currentTarget?.open&&!A)_?.("full")}},T("summary",null,T("span",null,"引用注入已折叠,点击按需拉取最终进入 opencode 的完整 prompt"),T("code",null,A?`${K||ry(A)} lines / ${A.length} chars`:`${Number.isFinite(G)&&G>0?G:"--"} chars`)),T("pre",{className:"codex-prompt-full codex-prompt-final-full","data-testid":l},A||(u?"正在按需拉取完整 prompt...":"展开后将只请求 full prompt,不拉取完整 transcript。"))):null)}function eG({task:f,attempt:u,attemptIndex:_,loading:y,onLoadSteps:l,onLoadStep:$,testId:j="codex-execution-summary"}){let J=iX(cX(f,_)),F=gX(xX(f,u),J),A=Hj(f),U=aG(f,_),G=Number(F.toolCallCount||0),W=Array.isArray(F.editedFiles)?F.editedFiles:[],K=Array.isArray(F.commands)?F.commands:[],H=dG(u,_)?` · ${String(u?.label||"recovered thread execution")}`:_?` #${_}`:"",O=vX(f,u,_,F),z=`最近更新: ${UX(O)}`;return T("details",{className:"codex-progressive-card codex-execution-summary","data-testid":j,"data-attempt-index":r4(_),onToggle:(q)=>{if(q.currentTarget?.open&&!U)l?.(_)}},T("summary",null,T("div",{className:"codex-progressive-card-head"},T("span",{className:"codex-output-channel"},"Summary"),T("strong",null,`执行过程摘要${H}`),T("code",{title:O?`最近更新: ${zf(O)}`:z},`${X4(F.durationMs??F.totalElapsedMs)} / ${G} tools / ${z}`)),T("div",{className:"codex-execution-digest"},T("span",null,`read ${Number(F.readCount||0)}`),T("span",null,`edit ${Number(F.editCount||0)}`),T("span",null,`run ${Number(F.runCount||0)}`),T("span",null,`${Number(F.stepCount||J.length||0)} steps`))),T("div",{className:"codex-execution-digest expanded"},T("span",null,`修改文件:${kG(W,6)}`),T("span",null,`执行命令:${kG(K,4)}`)),J.length===0?T("div",{className:"codex-output-empty"},y?"正在按需拉取步骤 summary...":"展开后将只请求执行步骤 summary,不拉取单步骤全量。"):T("div",{className:"codex-trace-step-list"},J.map((q)=>{let Z=String(q?.seq??""),V=A[Z],L=Array.isArray(q?.summaryLines)?q.summaryLines.slice(0,4):[];return T("details",{key:Z||`${q?.title}-${q?.at}`,className:`codex-trace-step ${String(q?.kind||"message")}`,"data-testid":`codex-trace-step-${Z||"unknown"}`,onToggle:(r)=>{if(r.currentTarget?.open&&!V)$?.(q?.seq)}},T("summary",null,T("span",{className:"codex-output-channel"},jN(q?.kind)),T("strong",null,String(q?.title||"Trace step")),q?.status?T("code",null,String(q.status)):null,T("time",null,zf(q?.at))),T("div",{className:"codex-trace-step-summary"},L.length>0?L.map((r,N)=>T("pre",{key:`${Z}-${N}`},String(r||""))):T("span",null,"无 summary")),V?.line?T(E4,{items:[V.line],autoScroll:!1,loading:!1,hasDetail:!0,emptyText:"无步骤详情",testId:`codex-trace-step-detail-${Z||"unknown"}`,className:"codex-transcript codex-step-detail-transcript",collapseTools:!1}):T("div",{className:"codex-output-empty"},y?"正在按需拉取这个步骤的全量数据...":"展开后将只请求这个单步骤的全量数据。"))})))}function jN(f){let u=String(f||"");if(u==="ran")return"Ran";if(u==="explored")return"Explored";if(u==="edited")return"Edited";if(u==="error")return"Error";if(u==="system")return"System";return"Message"}function fz({task:f,attempt:u,attemptIndex:_,testId:y="codex-final-response"}){let l=bX(f,u),$=Number(u?.finalResponseChars||l.length),j=_?` #${_}`:"";return T("section",{className:"codex-progressive-card codex-final-response","data-testid":y,"data-attempt-index":r4(_)},T("div",{className:"codex-progressive-card-head"},T("span",{className:"codex-output-channel"},"Final"),T("strong",null,`最终 response${j}`),T("code",null,`${Number.isFinite($)?$:l.length} chars`)),T("pre",{className:"codex-transcript-body"},l||"暂无最终 response"))}function uz({task:f,attempt:u,attemptIndex:_,testId:y="codex-progressive-judge"}){let l=sG(f,u),$=_?` #${_}`:"";return T("section",{className:"codex-progressive-card codex-progressive-judge","data-testid":y,"data-attempt-index":r4(_)},T("div",{className:"codex-progressive-card-head"},T("span",{className:"codex-output-channel"},"Judge"),T("strong",null,`完成判定${$}`),l?.decision?T("code",null,`${l.decision} ${Math.round(Number(l.confidence||0)*100)}%`):null),l?T("div",{className:"codex-judge-card","data-testid":`${y}-card`},T(x_,{status:l.decision},l.decision),T("strong",null,`${Math.round(Number(l.confidence||0)*100)}% confidence`),T("p",{"data-testid":`${y}-reason`},l.reason||"--"),l.continuePrompt?T("pre",{"data-testid":`${y}-continue-prompt`},String(l.continuePrompt||"")):null):T("div",{className:"codex-output-empty"},"尚未判定"))}function JN({task:f,attempt:u,attemptIndex:_,loading:y,onLoadPromptPart:l,testId:$="codex-judge-feedback-prompt"}){let j=hX(f,u,_);if(j===null)return null;let J=oG(_),A=B4(f)[J],U=String(A?.text||"").trimEnd(),G=String(j.preview||j.text||"").trimEnd(),W=U||String(j.text||"").trimEnd(),K=Number(A?.chars||j.chars||W.length||G.length),E=Number(A?.lines||j.lines||ry(W||G)),H=A?.forAttempt||j.forAttempt||Number(_||0)+1;return T("details",{className:"codex-progressive-card codex-judge-feedback-prompt","data-testid":$,"data-attempt-index":r4(_),onToggle:(O)=>{if(O.currentTarget?.open&&!U)l?.("feedback",_)}},T("summary",null,T("div",{className:"codex-progressive-card-head"},T("span",{className:"codex-output-channel"},"Prompt"),T("strong",null,`judge feedback prompt #${_} -> #${H}`),T("code",null,`${E||"--"} lines / ${Number.isFinite(K)?K:G.length} chars`)),T("p",{className:"codex-feedback-preview","data-testid":`${$}-preview`},G||"展开后按需拉取 judge feedback prompt。")),T("pre",{className:"codex-prompt-full codex-feedback-full","data-testid":`${$}-text`},W||(y?"正在按需拉取 judge feedback prompt...":"展开后将只请求这一次 judge feedback prompt。")))}function FN({task:f,attempt:u,position:_,loading:y,onLoadPromptPart:l,onLoadSteps:$,onLoadStep:j}){let J=nX(u,_),F=_===0,A=dG(u,J),U=A?String(u?.label||"Recovered thread execution"):`Attempt ${J}`;return T("section",{className:"codex-attempt-cycle","data-testid":`codex-attempt-cycle-${J}`},T("div",{className:"codex-attempt-cycle-head"},T("span",{className:"codex-output-channel"},U),T("strong",null,String(u?.mode||(J<=1?"initial":"retry"))),u?.terminalStatus?T(x_,{status:u.terminalStatus},u.terminalStatus):null,T("code",null,`${zf(u?.startedAt)} -> ${zf(u?.finishedAt)}`)),T(eG,{task:f,attempt:u,attemptIndex:J,loading:y,onLoadSteps:$,onLoadStep:j,testId:F?"codex-execution-summary":`codex-execution-summary-attempt-${J}`}),A?null:T(fz,{task:f,attempt:u,attemptIndex:J,testId:F?"codex-final-response":`codex-final-response-attempt-${J}`}),A?null:T(uz,{task:f,attempt:u,attemptIndex:J,testId:F?"codex-progressive-judge":`codex-progressive-judge-attempt-${J}`}),A?null:T(JN,{task:f,attempt:u,attemptIndex:J,loading:y,onLoadPromptPart:l,testId:F?"codex-judge-feedback-prompt":`codex-judge-feedback-prompt-attempt-${J}`}))}function QN({task:f,loading:u,onLoadPromptPart:_,onLoadSteps:y,onLoadStep:l}){if(!f)return T(Il,{title:"未选择任务",text:"从左侧队列选择任务,或提交新 Codex 任务。"});let $=RX(f);return T("div",{className:"codex-transcript codex-progressive-trace","data-testid":"codex-output"},u&&!b_(f)?T("div",{className:"codex-output-empty"},"正在加载 Trace Summary..."):null,T($N,{task:f,loading:u,onLoadPromptPart:_}),$.length>0?$.map((j,J)=>T(FN,{key:`${j?.index||J+1}-${j?.startedAt||J}`,task:f,attempt:j,position:J,loading:u,onLoadPromptPart:_,onLoadSteps:y,onLoadStep:l})):[T(eG,{key:"execution",task:f,loading:u,onLoadSteps:y,onLoadStep:l}),T(fz,{key:"final",task:f}),T(uz,{key:"judge",task:f})])}function AN({task:f}){let u=TX(f);if(!f||u.length===0)return T(Il,{title:"暂无原始消息",text:"原始 Codex app-server 消息会保留在任务 JSON 中。"});return T("details",{className:"codex-raw-output"},T("summary",null,`原始 messages (${u.length})`),T("div",null,u.map((_)=>T("article",{key:`${_.seq}-${_.channel}`,className:`codex-output-line ${_.channel||"system"}`},T("div",{className:"codex-output-meta"},T("span",{className:"codex-output-channel"},sX(String(_.channel||"system"))),T("span",null,zf(_.at)),_.method?T("code",null,_.method):null),T("pre",null,String(_.text||""))))))}function UN({task:f}){let u=nG(f).slice().reverse();if(u.length===0)return T(Il,{title:"尚无 attempt",text:"任务开始运行后,这里会记录 Codex 终态、传输中断和 stderr tail。"});return T("div",{className:"table-wrap codex-attempt-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("tbody",null,u.map((_)=>T("tr",{key:`${_.index}-${_.startedAt}`},T("td",null,_.index),T("td",null,_.mode),T("td",null,T(x_,{status:_.terminalStatus||"unknown"},_.terminalStatus||"unknown")),T("td",null,_.transportClosedBeforeTerminal?T(x_,{status:"failed"},"closed-before-terminal"):T(x_,{status:"succeeded"},"normal")),T("td",null,`code=${_.appServerExitCode??"--"} signal=${_.appServerSignal??"--"}`),T("td",null,zf(_.finishedAt)))))))}function _z({microservices:f,onRaw:u,apiBaseUrl:_="/api",initialTasksData:y=null,standalone:l=!1}){let $=f.find((g)=>g.id==="codex-queue")||null,j=uN(y),J=String(j?.id||""),F=new Map;if(j!==null&&J.length>0)F.set(J,{task:j,maxSeq:O4(Array.isArray(j.transcript)?j.transcript:[]),complete:Boolean(j._transcriptComplete),completeUpdatedAt:j._transcriptComplete?String(j.updatedAt||""):""});let A=typeof performance>"u"?0:performance.now(),U=Zu(J),G=Zu(0),W=Zu(0),K=Zu(!1),E=Zu(!1),H=Zu(null),O=Zu(new Map),z=Zu(new Map),q=Zu(new Map),Z=Zu(new Map),V=Zu(new Set),L=Zu(!1),r=Zu(Boolean(y)),N=Zu(F),D=Zu(y),[x,c]=u0(null),[v,C]=u0(y),[S,B]=u0(J),[P,M]=u0(j),[w,Y]=u0(!1),[R,k]=u0(""),[p,n]=u0(""),[_f,s]=u0("default"),[ff,Kf]=u0(R_),[Gf,jf]=u0("gpt-5.5"),[Wf,Of]=u0("/root/unidesk"),[Zf,h]=u0(99),[i,I]=u0(1),[lf,$f]=u0(!1),[Af,Yf]=u0(!1),[xf,of]=u0(""),[F0,y0]=u0(!0),[T0,Qu]=u0(()=>typeof window>"u"?!0:window.matchMedia(qX).matches),[X0,v0]=u0(!1),[iu,K0]=u0(""),[Au,uf]=u0(""),[vf,o0]=u0(""),[Bf,b0]=u0(""),[i0,a0]=u0(!1),[nf,d0]=u0(y?{phase:"complete",taskId:J,queueMs:0,detailMs:0,totalMs:A,chunks:j?1:0,transcriptRows:Array.isArray(j?.transcript)?j.transcript.length:0,partial:Boolean(y?.selected?.hasMore||M$(j)),completedAt:new Date}:null),[Hu,oy]=u0(y?new Date:null),[J_,ay]=u0(!1),t=Z1(v),Hf=t.filter(hl),Df=t.filter((g)=>!d1(g)),If=t.filter((g)=>d1(g)&&!hl(g)),Rf=v?.queue||x?.body?.queue||x?.queue||{},Q0=r$(v),af=xG(Rf,_f),h0=Y4(af,ff),e0=Number((Yu(ff)?Rf?.total:h0?.total)??Q0.total??t.length),S6=Q0.hasMore===!0&&String(Q0.nextBeforeId||"").length>0,dy=N4(Rf),ey=Yu(ff)?dy:[String(Y4(af,ff)?.activeTaskId||"")].filter(Boolean),$y=vG(Rf,af,ff,t),F_=Yu(ff)?Aj(Rf):Aj(h0||{}),C6=Aj(Rf),W2=oX(C6),G2=Math.max(aX(C6),dy.length),Q_=S$((Yu(ff)?Rf?.unreadTerminal:h0?.unreadTerminal)??Hf.length),jy=Yu(ff)?"All queues":ff,V3=$?GX($):{},R6=$?KX($):{},O3=$?zX($):{},X3=PG(()=>rX(R),[R]),j1=PG(()=>{let g=bG(i);return X3.flatMap((d)=>Array.from({length:g},()=>MX(d,p)))},[X3,i,p]),Jy=j1.length,x6=Jy>1&&!lf,z2=Af||X0||Jy===0||x6,N3=_N(Rf,Gf),L3=P?.id&&P?.activeTurnId&&String(P?.status)==="running",K2=P?.id&&!["succeeded","failed","canceled"].includes(String(P?.status||"")),Z2=P?.id&&["succeeded","failed","canceled"].includes(String(P?.status||""));function I1(g){let d=typeof g==="function"?g(D.current):g;return D.current=d,C(d),d}function v6(g,d,Qf=null,Ef=null){let Tf=new Set(g.map((Nf)=>String(Nf||"")).filter(Boolean));if(Tf.size===0&&Ef===null&&Qf===null)return;I1((Nf)=>{if(!Nf)return Nf;let rf=Z1(Nf).map((df)=>{let cf=String(df?.id||"");if(!Tf.has(cf))return df;let tf=Ef&&String(Ef?.id||"")===cf?Ef:{};return{...df,...tf,readAt:d,terminalUnread:!1}});return{...Nf,queue:Qf||Nf.queue,tasks:Tf.size>0?H4([rf],$y):rf}});for(let Nf of Tf){let rf=N.current.get(Nf);if(rf?.task){let df=Ef&&String(Ef?.id||"")===Nf?Ef:{},cf={...rf.task,...df,readAt:d,terminalUnread:!1};if(N.current.set(Nf,{...rf,task:cf}),U.current===Nf)M(cf)}}}P$(()=>{$f(!1)},[R,i,p]);function N1(g,d,Qf){let Ef=N.current.get(g)||{},Tf=Ef.task||{},Nf=Array.isArray(Tf.transcript)?Tf.transcript:[],rf=fN(Tf,d),df=Object.prototype.hasOwnProperty.call(d,"transcript")?Uj(Nf,Array.isArray(d.transcript)?d.transcript:[]):Nf,cf={...Tf,...rf,transcript:df,output:Array.isArray(rf.output)?Vj(Tf,rf,"output"):Array.isArray(Tf.output)?Tf.output:[],events:Array.isArray(rf.events)?Vj(Tf,rf,"events"):Array.isArray(Tf.events)?Tf.events:[]},tf=String(cf?.updatedAt||""),ef=Boolean(d._transcriptComplete)&&d1(cf),l0=Boolean(Ef.complete)&&d1(cf)&&String(Ef.completeUpdatedAt||"")===tf,fu=ef||l0,J1={...Ef,task:cf,maxSeq:O4(df),complete:fu,completeUpdatedAt:fu?tf:""};if(N.current.set(g,J1),Qf===W.current&&U.current===g)M(cf);return J1}async function fl(g,d=!1,Qf,Ef){if(!$||!g)return;let Nf=N.current.get(g)?.task,rf=String(Nf?._traceSummaryUpdatedAt||""),df=String(Nf?.updatedAt||"");if(!d&&Nf?._traceSummaryLoaded===!0&&rf===df)return;let cf=g,tf=O.current.get(cf);if(tf)return tf;let ef=W.current,l0=performance.now();if(U.current===g)Y(!0);let fu=(async()=>{try{let J1=await NX(_,g);if(ef!==W.current||U.current!==g)return;let N0=J1?.summary||{};N1(g,{id:g,status:N0.status,updatedAt:N0.updatedAt,startedAt:N0.startedAt,finishedAt:N0.finishedAt,currentAttempt:N0.currentAttempt,maxAttempts:N0.maxAttempts,finalResponse:N0.finalResponse,lastJudge:N0.lastJudge,lastError:N0.lastError,attempts:Array.isArray(N0.attempts)?N0.attempts:[],timing:N0.timing,_traceSummary:N0,_traceSummaryLoaded:!0,_traceSummaryUpdatedAt:String(N0.updatedAt||""),_detailLoaded:!0},ef),d0({phase:"complete",taskId:g,queueMs:Ef??0,detailMs:performance.now()-l0,totalMs:Qf===void 0?performance.now()-l0:performance.now()-Qf,chunks:1,transcriptRows:Number(N0?.execution?.stepCount||0),partial:!1,completedAt:new Date})}finally{if(O.current.delete(cf),ef===W.current&&U.current===g)Y(!1)}})();O.current.set(cf,fu),await fu}async function b6(g,d=null){let Qf=U.current;if(!$||!Qf||!g)return;let Ef=N.current.get(Qf)?.task,Tf=B4(Ef),Nf=g==="feedback"||g==="judge-feedback"?oG(d):g;if(Tf[Nf]?.text)return;let rf=`${Qf}:${Nf}`,df=z.current.get(rf);if(df)return df;let cf=W.current;if(U.current===Qf)Y(!0);let tf=(async()=>{try{let ef=await LX(_,Qf,g,d);if(cf!==W.current||U.current!==Qf)return;let l0=N.current.get(Qf)?.task,fu=B4(l0);N1(Qf,{...g==="full"?{prompt:String(ef?.text||""),promptChars:Number(ef?.chars||0)}:{},_promptDetails:{...fu,[Nf]:ef}},cf)}finally{if(z.current.delete(rf),cf===W.current&&U.current===Qf)Y(!1)}})();z.current.set(rf,tf),await tf}async function q2(g=null){let d=U.current;if(!$||!d)return;let Qf=N.current.get(d)?.task,Ef=g===null||g===void 0||String(g).length===0?"":String(g);if(aG(Qf,Ef||null))return;let Tf=`${d}:${Ef||"all"}`,Nf=q.current.get(Tf);if(Nf)return Nf;let rf=W.current;if(U.current===d)Y(!0);let df=(async()=>{try{let cf=await YX(_,d,0,500,Ef||null);if(rf!==W.current||U.current!==d)return;let tf=Array.isArray(cf?.steps)?cf.steps:[];if(Ef){let ef=N.current.get(d)?.task,l0=v_(ef?._traceStepsByAttempt)||{},fu=v_(ef?._traceStepsLoadedByAttempt)||{};N1(d,{_traceStepsByAttempt:{...l0,[Ef]:tf},_traceStepsLoadedByAttempt:{...fu,[Ef]:!0}},rf)}else N1(d,{_traceSteps:tf,_traceStepsLoaded:!0,_traceStepsHasMore:Boolean(cf?.hasMore),_traceStepsNextAfterSeq:cf?.nextAfterSeq},rf)}finally{if(q.current.delete(Tf),rf===W.current&&U.current===d)Y(!1)}})();q.current.set(Tf,df),await df}async function E2(g){let d=U.current,Qf=String(g??"");if(!$||!d||Qf.length===0)return;let Ef=N.current.get(d)?.task;if(Hj(Ef)[Qf]?.line)return;let Nf=`${d}:${Qf}`,rf=Z.current.get(Nf);if(rf)return rf;let df=W.current;if(U.current===d)Y(!0);let cf=(async()=>{try{let tf=await BX(_,d,g);if(df!==W.current||U.current!==d)return;let ef=N.current.get(d)?.task,l0=Hj(ef);N1(d,{_traceStepDetails:{...l0,[Qf]:tf}},df)}finally{if(Z.current.delete(Nf),df===W.current&&U.current===d)Y(!1)}})();Z.current.set(Nf,cf),await cf}async function EQ(g,d,Qf){if(!$||!g)return;let Ef=performance.now(),Tf=W.current,Nf=N.current.get(g);if(Nf?.task){if(M(Nf.task),Y(M$(Nf.task)||!Nf.complete),!M$(Nf.task)&&Nf.complete&&d1(Nf.task)&&String(Nf.completeUpdatedAt||"")===String(Nf.task?.updatedAt||"")){d0({phase:"complete",taskId:g,queueMs:Qf??0,detailMs:0,totalMs:d===void 0?0:performance.now()-d,chunks:0,transcriptRows:Array.isArray(Nf.task.transcript)?Nf.task.transcript.length:0,completedAt:new Date});return}}else Y(!0);let rf=H.current;if(rf?.taskId===g&&rf.token===Tf)return rf.promise;let df=(async()=>{try{let cf=await M0(P0(_,`/api/tasks/${encodeURIComponent(g)}?meta=1`));if(Tf!==W.current||U.current!==g)return;let tf=N.current.get(g),ef=Array.isArray(tf?.task?.transcript)?tf.task.transcript:[],l0=cf?.task||{},fu=Boolean(tf?.complete)&&String(tf?.completeUpdatedAt||"")===String(l0?.updatedAt||"");N1(g,{...l0,summaryOnly:!1,_metaLoaded:!0,transcript:ef,_detailLoaded:ef.length>0,_transcriptComplete:fu},Tf);let J1=M$(tf?.task)||Boolean(tf?.task?._transcriptPreview),N0=J1?0:ef.length>0?pG(ef):0,A_=!J1&&tf?.complete&&d1(l0)&&String(tf?.completeUpdatedAt||"")===String(l0?.updatedAt||"")?O4(ef):N0,_l=!0,p6=0,k6=ef.length;while(_l){let nu=await M0(P0(_,`/api/tasks/${encodeURIComponent(g)}/transcript?afterSeq=${encodeURIComponent(String(A_))}&limit=${FX}&fullText=1`));if(Tf!==W.current||U.current!==g)return;let L1=N.current.get(g),Fy=Array.isArray(L1?.task?.transcript)?L1.task.transcript:[],Qy=Uj(Fy,Array.isArray(nu?.transcript)?nu.transcript:[]);p6+=1,k6=Qy.length;let I0=Boolean(!nu?.hasMore);if(N1(g,{status:nu?.status||l0.status,updatedAt:nu?.updatedAt||l0.updatedAt,transcript:Qy,_detailLoaded:I0||Qy.length>0,_transcriptComplete:I0,_transcriptPreview:J1&&!I0},Tf),_l=Boolean(nu?.hasMore),A_=Number(nu?.nextAfterSeq??O4(Qy)),!_l)break;await new Promise((LQ)=>window.setTimeout(LQ,0))}d0({phase:"complete",taskId:g,queueMs:Qf??0,detailMs:performance.now()-Ef,totalMs:d===void 0?performance.now()-Ef:performance.now()-d,chunks:p6,transcriptRows:k6,completedAt:new Date})}finally{if(H.current?.taskId===g&&H.current?.token===Tf)H.current=null;if(Tf===W.current&&U.current===g)Y(!1)}})();H.current={taskId:g,token:Tf,promise:df},await df}async function gu(g=U.current,d=!0,Qf=ff){if(!$)return;if(!d&&L.current)return;let Ef=performance.now();if(d)L.current=!0;if(d)d0({phase:"loading",taskId:String(g||U.current||""),startedAt:new Date});let Tf=G.current+1;G.current=Tf;let Nf=String(g||U.current||""),rf=Nf?N.current.get(Nf):null,df=Array.isArray(rf?.task?.transcript)?rf.task.transcript:[],cf=pG(df),tf=x||{},ef=null;try{ef=await OX(_,Nf,cf,Qf)}catch{ef=await VX(_,tf,Qf)}if(Tf!==G.current){if(d)L.current=!1;return}let l0=performance.now()-Ef;c(tf);let fu=ef?.queue||{},J1=String(fu?.activeTaskId||N4(fu)[0]||""),N0=ef;I1((Uu)=>{let w3=Z1(ef),Ay=Z1(Uu),yl=Ay.length>0?H4([Ay,w3],J1):H4([w3],J1),Y2=r$(ef),i6=r$(Uu),tE=Ay.length>w3.length&&(i6.hasMore===!1||String(i6.nextBeforeId||"").length>0),sE={...Y2,...tE?{hasMore:i6.hasMore,nextBeforeId:i6.nextBeforeId}:{},returned:yl.length};return N0={...ef,tasks:yl,pagination:sE},N0});let A_=Z1(N0),_l=xG(fu,_f),p6=vG(fu,_l,Qf,A_),k6=HX(_l,Qf,A_),nu=Nf||U.current,L1=N0?.selected||null,Fy=L1?.task||null,Qy=Array.isArray(L1?.transcript)?L1.transcript:null,I0=nu&&(A_.some((Uu)=>Uu.id===nu)||String(Fy?.id||"")===nu)?nu:p6||k6||A_[0]?.id||"";if(U.current!==I0)W.current+=1;U.current=I0,B(I0);let m6=A_.find((Uu)=>Uu.id===I0);if(m6){let Uu=N.current.get(I0);if(Uu?.task)N.current.set(I0,{...Uu,task:{...m6,...Uu.task,status:m6.status,updatedAt:m6.updatedAt}})}if(Fy?.id===I0&&Qy!==null){let Uu=N.current.get(I0),w3=Array.isArray(Uu?.task?.transcript)?Uu.task.transcript:[],Ay=Uj(w3,Qy),yl=Boolean(L1?.preview);if(N1(I0,{...Fy,_summaryLoaded:!0,transcript:Ay,_detailLoaded:!L1?.hasMore||Ay.length>0,_transcriptComplete:!yl&&!L1?.hasMore&&d1(Fy),_transcriptPreview:yl},W.current),Y(!1),d)d0({phase:"complete",taskId:I0,queueMs:l0,detailMs:Math.max(0,performance.now()-Ef-l0),totalMs:performance.now()-Ef,chunks:1,transcriptRows:Ay.length,partial:Boolean(yl||L1?.hasMore||M$(Fy)),completedAt:new Date});if(oy(new Date),d)L.current=!1;fl(I0,!1,d?Ef:void 0,d?l0:void 0).catch((Y2)=>K0(C_(Y2,"加载 Codex Trace Summary 失败")));return}if(d)d0({phase:"session",taskId:I0,queueMs:l0,totalMs:l0,startedAt:new Date(Date.now()-l0)});if(I0)fl(I0,!0,d?Ef:void 0,d?l0:void 0).catch((Uu)=>K0(C_(Uu,"加载 Codex Trace Summary 失败")));else if(W.current+=1,M(null),Y(!1),d)d0({phase:"complete",taskId:"",queueMs:l0,detailMs:0,totalMs:performance.now()-Ef,chunks:0,transcriptRows:0,completedAt:new Date});if(oy(new Date),d)L.current=!1}async function h6(){if(!$||J_||E.current)return;let g=String(r$(v).nextBeforeId||"");if(!g)return;E.current=!0,ay(!0),K0("");try{let d=await XX(_,ff,g),Qf=Z1(d),Ef=d?.queue||Rf||{},Tf=String(Ef?.activeTaskId||N4(Ef)[0]||$y||"");I1((Nf)=>{let rf=H4([Z1(Nf),Qf],Tf),df=r$(d);return{...Nf||{},queue:Ef,tasks:rf,pagination:{...df,returned:rf.length}}})}catch(d){K0(C_(d,"加载更早 Codex tasks 失败"))}finally{E.current=!1,ay(!1)}}function H2(g){let d=g.currentTarget;if(!d||J_||!S6)return;if(d.scrollHeight-d.scrollTop-d.clientHeight<120)h6()}async function Mu(g,d){v0(!0),K0("");try{await g()}catch(Qf){K0(C_(Qf,d))}finally{v0(!1)}}async function Y3(g){if(!g)return;try{let d=!1;try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(g),d=!0}catch{d=!1}if(!d){let Qf=document.createElement("textarea");Qf.value=g,Qf.style.position="fixed",Qf.style.opacity="0",document.body.appendChild(Qf),Qf.select(),d=document.execCommand("copy"),document.body.removeChild(Qf)}if(!d)throw Error("browser clipboard rejected the copy request");o0(g),uf(`已复制任务 ID:${g}`),window.setTimeout(()=>o0((Qf)=>Qf===g?"":Qf),1600)}catch(d){K0(`复制任务 ID 失败:${C_(d)}`)}}function ul(g){if(!g)return;n(g),uf(`已引用任务 ID:${g};提交时后端会读取并注入该任务上下文`)}async function B3(g){if(!$||!g)return;b0(g),await Mu(async()=>{let d=await DX(_,g),Qf=d?.task||{id:g,readAt:new Date().toISOString(),terminalUnread:!1},Ef=String(Qf?.readAt||new Date().toISOString());v6([g],Ef,d?.queue||null,Qf),uf(`已将任务 ${g} 标为已读`)},"标记 Codex task 已读失败"),b0((d)=>d===g?"":d)}async function I6(){if(!$||i0)return;a0(!0),await Mu(async()=>{let g=await wX(_),d=String(g?.readAt||new Date().toISOString()),Qf=Z1(D.current).filter(hl).map((rf)=>String(rf?.id||"")).filter(Boolean),Ef=Array.from(N.current.entries()).filter(([,rf])=>hl(rf?.task)).map(([rf])=>rf),Tf=Array.from(new Set([...Qf,...Ef]));v6(Tf,d,g?.queue||null);let Nf=Number(g?.count||Tf.length);uf(`已将 ${Nf} 个已结束未读任务标为已读`)},"全部标为已读失败"),a0(!1)}function V2(g){let d=g||R_;if(Kf(d),!Yu(d))s(d);if(I1(null),!(Yu(d)?U.current:""))U.current="",W.current+=1,B(""),M(null),Y(!0)}async function O2(){let g=typeof window>"u"?"":window.prompt("输入新的 Codex queue ID(字母/数字/._-,最长 64)","new-lane"),d=String(g||"").trim();if(!d)return;await Mu(async()=>{let Qf=await M0(P0(_,"/api/queues"),{method:"POST",body:{queueId:d}}),Ef=String(Qf?.queue?.id||d);s(Ef),Kf(Ef),I1(null),U.current="",W.current+=1,B(""),M(null),uf(`已创建并切换到 queue:${Ef}`),await gu("",!0,Ef)},"创建 Codex queue 失败")}async function D3(g){if(g.preventDefault(),K.current){uf("任务正在提交中,请等待当前请求完成,已阻止重复提交。");return}if(j1.length>1&&!lf){K0(`检测到将创建 ${j1.length} 个任务;请先勾选“确认批量入队”,避免误传多个任务。`);return}K.current=!0,Yf(!0),uf("正在提交 Codex Queue 任务,请等待后端确认,输入已临时锁定。"),await Mu(async()=>{if(j1.length===0)throw Error("prompt 不能为空");let d=L4(p),Qf=_f.trim()||"default",Ef=[...j1],Tf=(tf)=>({prompt:tf,queueId:Qf,model:Gf,cwd:Wf,maxAttempts:Number(Zf),...d.length>0?{referenceTaskIds:d}:{}}),Nf=Ef.length===1?Tf(Ef[0]):{tasks:Ef.map(Tf)},rf=await M0(P0(_,Ef.length===1?"/api/tasks":"/api/tasks/batch"),{method:"POST",body:Nf}),df=rf?.tasks?.[0]?.id||"",cf=Array.isArray(rf?.tasks)?rf.tasks.map((tf)=>String(tf?.id||"")).filter(Boolean):[];if(uf(`已创建 ${cf.length||Ef.length} 个任务${cf.length>0?`:${cf.join(" / ")}`:""}`),k(""),n(""),$f(!1),U.current=df,ff!==Qf)I1(null);Kf(Qf),s(Qf),await gu(df,!0,Qf)},"Codex 任务入队失败"),K.current=!1,Yf(!1)}async function X2(g){if(g.preventDefault(),!P?.id)return;await Mu(async()=>{await M0(P0(_,`/api/tasks/${encodeURIComponent(P.id)}/steer`),{method:"POST",body:{prompt:xf}}),of(""),await gu(P.id)},"追加 prompt 失败")}async function N2(){if(!P?.id)return;await Mu(async()=>{await M0(P0(_,`/api/tasks/${encodeURIComponent(P.id)}/interrupt`),{method:"POST",body:{}}),await gu(P.id)},"打断 Codex session 失败")}async function c6(){if(!P?.id)return;await Mu(async()=>{await M0(P0(_,`/api/tasks/${encodeURIComponent(P.id)}/retry`),{method:"POST",body:{}}),await gu(P.id)},"重新入队失败")}async function cE(g){let d=String(P?.id||""),Qf=String(g||"").trim();if(!d||!Qf)return;let Ef=w4(P);if(Qf===Ef){uf(`任务 ${d} 已在 queue=${Qf}`);return}await Mu(async()=>{let Nf=(await M0(P0(_,`/api/tasks/${encodeURIComponent(d)}/move`),{method:"POST",body:{queueId:Qf}}))?.task||{...P,queueId:Qf};if(N.current.set(d,{...N.current.get(d)||{},task:Nf}),U.current=d,M(Nf),B(d),s(Qf),!Yu(ff))I1(null),Kf(Qf);uf(`已将任务 ${d} 从 ${Ef} 移动到 ${Qf}`),await gu(d,!0,Yu(ff)?R_:Qf)},"移动任务 queue 失败")}async function pE(){let g=U.current;if(!g)return;let d=performance.now();await Mu(async()=>{d0({phase:"session",taskId:g,queueMs:0,totalMs:0,partial:!0,startedAt:new Date}),await fl(g,!0,d,0)},"刷新 Trace Summary 失败")}function kE(g){U.current=g,W.current+=1,B(g);let d=N.current.get(g);if(d?.task)M(d.task),Y(!1);else{Y(!0);let Qf=t.find((Ef)=>Ef.id===g);if(Qf)M(Qf);else M(null)}gu(g).catch((Qf)=>K0(C_(Qf,"切换 Codex session 失败")))}function L2(g){if(kE(g),EX())Qu(!1)}P$(()=>{if(r.current){r.current=!1;return}Mu(()=>gu(U.current),"Codex Queue 加载失败")},[$?.id,ff]),P$(()=>{if(!$)return;let g=()=>{if(!SG())return;gu(U.current,!1).catch((Ef)=>K0(C_(Ef,"Codex Queue 轮询失败")))},d=window.setInterval(()=>{g()},1500),Qf=()=>{if(SG())g()};return document.addEventListener("visibilitychange",Qf),()=>{window.clearInterval(d),document.removeEventListener("visibilitychange",Qf)}},[$?.id,ff]),P$(()=>{if(!$||!P||w)return;let g=String(P.id||"");if(!g)return;let d=String(P.updatedAt||""),Qf=String(P._traceSummaryUpdatedAt||"");if(P._traceSummaryLoaded===!0&&Qf===d)return;let Ef=`${g}:${d||"unknown"}`;if(V.current.has(Ef))return;V.current.add(Ef),fl(g,!0).catch((Tf)=>K0(C_(Tf,"自动加载 Trace Summary 失败")))},[$?.id,P?.id,P?.updatedAt,P?._traceSummaryUpdatedAt,P?._traceSummaryLoaded,w]);let mE=t.length===0?T(Il,{title:"队列为空",text:"提交一个任务后,Codex 会串行执行并保存输出。"}):[Hf.length>0?T(Gj,{key:"unread",title:"已结束未读",tasks:Hf,selectedId:S,emptyText:"暂无已结束未读任务。",onSelect:L2,onCopy:Y3,onReference:ul,onMarkRead:B3,copiedTaskId:vf,markingReadTaskId:Bf}):null,T(Gj,{key:"active",title:"运行 / 排队",tasks:Df,selectedId:S,emptyText:"当前没有运行或排队任务。",onSelect:L2,onCopy:Y3,onReference:ul,onMarkRead:B3,copiedTaskId:vf,markingReadTaskId:Bf}),T(Gj,{key:"history",title:"历史 session",tasks:If,selectedId:S,emptyText:"最近没有完成、失败或取消的 session。",onSelect:L2,onCopy:Y3,onReference:ul,onMarkRead:B3,copiedTaskId:vf,markingReadTaskId:Bf}),T("div",{key:"pagination",className:"codex-task-pagination","data-testid":"codex-task-pagination"},T("span",null,`已加载 ${t.length} / ${Number.isFinite(e0)?e0:t.length}`),S6?T("button",{type:"button",className:"ghost-btn",disabled:J_,onClick:()=>void h6(),"data-testid":"codex-load-more-tasks-button"},J_?"加载中":"加载更早任务"):T("code",null,"已到队列末尾"))],HQ=(g,d=!1)=>T("label",{className:`codex-queue-switcher ${d?"compact":""}`},T("span",null,d?"Queue":"查看 queue"),T("select",{value:ff,onChange:(Qf)=>V2(String(Qf.target.value||R_)),"data-testid":g},T("option",{value:R_},`All queues · ${Number.isFinite(e0)?e0:t.length} tasks · ${dy.length} running`),af.map((Qf)=>T("option",{key:String(Qf?.id||""),value:String(Qf?.id||"")},Kj(Qf))))),iE=T("div",{className:"codex-trace-status","data-testid":"codex-trace-status-summary"},T("span",{className:"codex-trace-status-chip queued"},T("b",null,"排队"),String(W2)),T("span",{className:"codex-trace-status-chip running"},T("b",null,"运行"),String(G2)),T("span",{className:`codex-trace-status-chip unread ${Q_>0?"warn":""}`},T("b",null,"结束未读"),String(Q_))),gE=T(bl,{title:P?`Trace ${String(P.id).slice(0,22)}`:"Trace 输出",eyebrow:P?`${P.status} / view=${jy} / task queue=${w4(P)} / ${P.model} / agent loop trace`:`Agent loop trace / view=${jy}`,summary:iE,actions:T("div",{className:"panel-actions"},HQ("codex-queue-filter-select"),T("button",{type:"button",className:"ghost-btn codex-mark-all-read-btn",disabled:Q_===0||X0||i0,onClick:()=>void I6(),"data-testid":"codex-mark-all-read-button"},i0?"标记中":`全部标已读${Q_>0?` (${Q_})`:""}`),P?T("button",{type:"button",className:"ghost-btn",disabled:w||X0,onClick:()=>void pE(),"data-testid":"codex-load-full-trace-button"},w?"加载中":b_(P)?"刷新 Summary":"加载 Summary"):null,T("button",{type:"button",className:"codex-session-title-toggle",onClick:()=>Qu((g)=>!g),"data-testid":"codex-queue-sidebar-toggle"},T0?"收起队列":"展开队列"),T("label",{className:"inline-check"},T("input",{type:"checkbox",checked:F0,onChange:(g)=>y0(Boolean(g.target.checked))}),"自动滚动"),T("button",{type:"button",className:"ghost-btn",disabled:!K2||X0,onClick:()=>void N2(),"data-testid":"codex-interrupt-button"},"打断"),T("button",{type:"button",className:"ghost-btn",disabled:!Z2||X0,onClick:()=>void c6()},"重试"),P?T(CG,{title:"Codex Task",data:P,onOpen:u,testId:"raw-codex-task"}):null),className:"codex-output-panel"},T("div",{className:`codex-session-shell ${T0?"":"queue-collapsed"}`},T0?T("aside",{className:"codex-session-sidebar","data-testid":"codex-session-sidebar"},T("div",{className:"codex-session-sidebar-head"},T("div",null,T("span",null,Yu(ff)?"All queues":"Queue lane"),T("strong",null,`${jy} · ${t.length}/${Number.isFinite(e0)?e0:t.length} sessions · 未读 ${Q_}`)),T("button",{type:"button",className:"ghost-btn",onClick:()=>Qu(!1)},"收起")),HQ("codex-queue-filter-sidebar",!0),T("div",{className:"codex-task-list codex-task-list-session",onScroll:H2,"data-testid":"codex-task-list-scroll"},mE)):null,T("div",{className:"codex-session-main"},T("div",{className:"codex-output-stack"},T(QN,{task:P,loading:w,onLoadPromptPart:b6,onLoadSteps:q2,onLoadStep:E2}),T(AN,{task:P})))));if(!$)return T(Il,{title:"Codex Queue 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=codex-queue"});let VQ=Number(nf?.totalMs),OQ=Number(nf?.queueMs),XQ=Number(nf?.detailMs),NQ=Number(nf?.transcriptRows),nE=nf?.phase==="complete"?"complete":String(nf?.phase||"idle");return T("div",{className:`codex-queue-page ${l?"codex-standalone-page":""}`,"data-testid":"codex-queue-page","data-load-state":nE,"data-load-total-ms":Number.isFinite(VQ)?String(Math.round(VQ*10)/10):"","data-load-queue-ms":Number.isFinite(OQ)?String(Math.round(OQ*10)/10):"","data-load-detail-ms":Number.isFinite(XQ)?String(Math.round(XQ*10)/10):"","data-load-transcript-rows":Number.isFinite(NQ)?String(NQ):"","data-load-task-id":String(nf?.taskId||S||""),"data-load-partial":nf?.partial?"true":"false"},T(H0,{error:iu,wide:!0}),Au?T("div",{className:"form-success wide","data-testid":"codex-create-success"},Au):null,T("div",{className:"codex-session-stage codex-session-stage-top"},gE),T("div",{className:"codex-queue-layout"},T("div",{className:"codex-left-rail"},T(bl,{title:"提交任务",eyebrow:Af?"Submitting...":j1.length>1?`${j1.length} tasks`:"Single or Batch",className:"codex-compose-panel"},T("form",{className:`codex-task-form ${Af?"is-submitting":""}`,onSubmit:D3,"data-testid":"codex-queue-task-form","aria-busy":Af?"true":"false"},T("label",null,"Prompt / 多任务用单独一行 --- 分隔",T("textarea",{value:R,rows:8,disabled:Af,onChange:(g)=>k(g.target.value),placeholder:"写入 Codex 任务;多个任务之间用 --- 分隔。"})),T("label",{className:"codex-reference-field"},"引用任务 ID(可选)",T("input",{value:p,disabled:Af,onChange:(g)=>n(g.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-reference-task-id"}),L4(p).length>0?T("code",null,`后端将解析并注入:${L4(p).join(" / ")}`):null),T("div",{className:"codex-form-grid"},T("label",{className:"codex-submit-queue-field"},"Queue",T("div",{className:"codex-submit-queue-row"},T("select",{value:_f,disabled:Af,onChange:(g)=>s(String(g.target.value||"default")),"data-testid":"codex-queue-id-select"},af.map((g)=>T("option",{key:String(g?.id||""),value:String(g?.id||"")},Kj(g)))),T("button",{type:"button",className:"ghost-btn codex-create-queue-btn",onClick:()=>void O2(),disabled:X0||Af,"data-testid":"codex-create-queue-button"},"创建 queue"))),T("label",null,"模型",T("select",{value:Gf,disabled:Af,onChange:(g)=>jf(g.target.value),"data-testid":"codex-model-select"},N3.map((g)=>T("option",{key:g,value:g},g)))),T("label",null,"工作目录",T("input",{value:Wf,disabled:Af,onChange:(g)=>Of(g.target.value),placeholder:Rf?.defaultWorkdir||"/root/unidesk"})),T("label",null,"最大尝试",T("input",{type:"number",min:1,max:99,value:Zf,disabled:Af,onChange:(g)=>h(Number(g.target.value)),"data-testid":"codex-max-attempts-input"})),T("label",null,"入队份数",T("input",{type:"number",min:1,max:50,value:i,disabled:Af,onChange:(g)=>I(Number(g.target.value)),"data-testid":"codex-repeat-count-input"}))),Jy>1?T("label",{className:`codex-batch-confirm ${lf?"confirmed":""}`,"data-testid":"codex-batch-confirm-row"},T("input",{type:"checkbox",checked:lf,disabled:Af,onChange:(g)=>$f(Boolean(g.target.checked)),"data-testid":"codex-batch-confirm-checkbox"}),T("span",null,`确认批量入队 ${Jy} 个任务(prompt 分段 ${X3.length} × 入队份数 ${bG(i)})`)):null,Af?T("div",{className:"codex-submit-wait","data-testid":"codex-submit-wait"},"正在提交到后端,已锁定输入以防重复提交..."):null,T("div",{className:"codex-form-actions"},T("button",{type:"button",className:"ghost-btn",disabled:X0||Af||R.length===0&&p.length===0,onClick:()=>{k(""),n(""),$f(!1),uf("已清空任务输入栏")},"data-testid":"codex-clear-input-button"},"清空输入"),T("button",{type:"submit",className:"primary-btn",disabled:z2,"data-testid":"codex-enqueue-button"},Af?"提交中,请等待...":x6?`请确认批量入队 ${Jy} 个任务`:j1.length>1?`批量入队 ${j1.length} 个任务`:"入队并运行"))))),T("div",{className:"codex-main-stage"},T("div",{className:"codex-detail-grid"},T(bl,{title:"运行控制",eyebrow:L3?"Active turn steer":"Steer when running"},T("div",{className:"codex-run-control-stack"},T(lN,{task:P,queueRows:af,busy:X0,onMove:cE}),T("form",{className:"codex-steer-form",onSubmit:X2},T("label",null,"追加 prompt",T("textarea",{value:xf,rows:4,onChange:(g)=>of(g.target.value),placeholder:"给正在运行的 Codex session 推入新的指令或纠偏。",disabled:!L3})),T("button",{type:"submit",className:"primary-btn",disabled:!L3||X0||xf.trim().length===0,"data-testid":"codex-steer-button"},"推入运行中 session")))),T(bl,{title:"完成判定",eyebrow:P?.lastJudge?P.lastJudge.source:"judge"},P?.lastJudge?T("div",{className:"codex-judge-card","data-testid":"codex-task-judge-card"},T(x_,{status:P.lastJudge.decision},P.lastJudge.decision),T("strong",null,`${Math.round(Number(P.lastJudge.confidence||0)*100)}% confidence`),T("p",{"data-testid":"codex-task-judge-reason"},P.lastJudge.reason||"--"),P.lastJudge.continuePrompt?T("code",{"data-testid":"codex-task-judge-continue-prompt"},iG(P.lastJudge.continuePrompt,220)):null):T(Il,{title:"尚未判定",text:"Codex turn 结束后会由 MiniMax M2.7 或 fallback judge 判定 complete/retry/fail;retry 会在已有 thread 追加继续执行 prompt。"}))),T(bl,{title:"Attempts",eyebrow:"terminal vs interruption"},T(UN,{task:P})))),T(bl,{title:"运行概要",eyebrow:"用户服务",actions:T("div",{className:"panel-actions"},T("button",{type:"button",className:"ghost-btn",onClick:()=>void Mu(()=>gu(S),"刷新失败"),disabled:X0,"data-testid":"codex-refresh-button"},X0?"同步中":"刷新"),T(CG,{title:"Codex Queue 用户服务",data:$,onOpen:u,testId:"raw-codex-queue-service"}))},T("div",{className:"codex-queue-hero"},T("div",null,T("div",{className:"node-version-line"},T(x_,{status:V3.providerStatus==="online"?"online":"warn"},V3.providerStatus||"unknown"),T("span",null,$.providerId),T("span",null,O3.public?"公网暴露":"仅 UniDesk frontend 代理访问"),T("span",null,Rf?.judgeConfigured?`MiniMax ${Rf?.minimaxModel||"M2.7"}`:"Fallback judge")),T("p",{className:"muted paragraph"},$.description)),T("div",{className:"microservice-ref-card"},T("span",null,"Queue view"),T("strong",null,jy),T("code",null,`${t.length}/${Number.isFinite(e0)?e0:t.length} loaded / ${dy.length} active lanes`),T("code",null,`models: ${N3.join(" / ")}`)),T("div",{className:"microservice-ref-card"},T("span",null,"Backend"),T("strong",null,`${O3.nodeBindHost||"--"}:${O3.nodePort||"--"}`),T("code",null,R6.containerName||"codex-queue-backend")))),T("div",{className:"codex-queue-metrics"},T(Ty,{label:"Queues",value:String(Rf?.queueCount??af.length??1),hint:`${Number(ey.length||0)} active lanes`,tone:ey.length>1?"warn":""}),T(Ty,{label:"排队",value:Wj(F_,"queued"),hint:"waiting turns"}),T(Ty,{label:"运行",value:Wj(F_,"running"),hint:ey.length>1?`${ey.length} parallel`:$y?`active ${String($y).slice(0,16)}`:"idle",tone:$y?"warn":"ok"}),T(Ty,{label:"成功",value:Wj(F_,"succeeded"),hint:"completed tasks",tone:"ok"}),T(Ty,{label:"异常/取消",value:String(Number(F_.failed||0)+Number(F_.canceled||0)),hint:"terminal non-success",tone:Number(F_.failed||0)>0?"fail":""}),T(Ty,{label:"加载耗时",value:Qj(nf?.totalMs),hint:nf?.phase==="complete"?`queue ${Qj(nf?.queueMs)} / session ${Qj(nf?.detailMs)} / ${nf?.chunks??0} chunks${nf?.partial?" / preview":""}`:`${nf?.phase||"idle"}...`,tone:Number(nf?.totalMs||0)>1000?"warn":"ok"}),T(Ty,{label:"最近刷新",value:Hu?L0(Hu):"--",hint:"1.5s polling"})))}var C4=Sf(c0(),1);var Jf=C4.default.createElement,{useEffect:WN}=C4.default,GN=C4.default.useState;function M4({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return Jf("span",{className:`status-badge ${_}`},u||f||"unknown")}function h_({label:f,value:u,hint:_,tone:y}){return Jf("article",{className:`metric-card ${y||""}`},Jf("div",{className:"metric-label"},f),Jf("div",{className:"metric-value"},u),Jf("div",{className:"metric-hint"},_))}function P4({title:f,eyebrow:u,actions:_,children:y,className:l}){return Jf("section",{className:`panel ${l||""}`},Jf("div",{className:"panel-head"},Jf("div",null,u?Jf("p",{className:"panel-eyebrow"},u):null,Jf("h2",null,f)),_?Jf("div",{className:"panel-actions"},_):null),Jf("div",{className:"panel-body"},y))}function S4({title:f,data:u,onOpen:_,testId:y}){return Jf("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function Nj({title:f,text:u}){return Jf("div",{className:"empty-state"},Jf("strong",null,f),Jf("span",null,u))}function zN(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function KN(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function ZN(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function My(f,u){let _=f&&typeof f==="object"?f[u]:void 0;return Number.isFinite(Number(_))?String(_):"--"}function qN(f){return(Array.isArray(f?.jobs)?f.jobs:[]).slice(0,40)}function EN(f){return(Array.isArray(f?.drafts)?f.drafts:[]).slice(0,12)}function yz({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((E)=>E.id==="findjob")||null,[l,$]=GN({loading:!1,error:"",health:null,summary:null,jobs:null,drafts:null,refreshedAt:null});async function j(){if(!y)return;$((E)=>({...E,loading:!0,error:""}));try{let[E,H,O,z]=await Promise.all([wf(`${_}/microservices/findjob/health`),wf(`${_}/microservices/findjob/proxy/api/summary`),wf(`${_}/microservices/findjob/proxy/api/jobs?__unideskArrayLimit=jobs:40`),wf(`${_}/microservices/findjob/proxy/api/drafts`)]);$({loading:!1,error:"",health:E,summary:H,jobs:O,drafts:z,refreshedAt:new Date})}catch(E){$((H)=>({...H,loading:!1,error:Pf(E,"FindJob 加载失败")}))}}if(WN(()=>{j()},[y?.id,y?.runtime?.providerStatus]),!y)return Jf(Nj,{title:"FindJob 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=findjob"});let J=zN(y),F=ZN(y),A=KN(y),U=l.summary||{},G=qN(l.jobs),W=EN(l.drafts),K=l.jobs?._unidesk?.arrayLimits?.jobs;return Jf("div",{className:"findjob-page","data-testid":"findjob-page"},Jf(P4,{title:"FindJob 工作台",eyebrow:"D601 用户服务",actions:Jf("div",{className:"panel-actions"},Jf("button",{type:"button",className:"ghost-btn",onClick:j,disabled:l.loading,"data-testid":"findjob-refresh-button"},l.loading?"刷新中":"刷新"),Jf(S4,{title:"FindJob 用户服务",data:y,onOpen:u,testId:"raw-findjob-service"}))},Jf("div",{className:"findjob-hero"},Jf("div",null,Jf("div",{className:"node-version-line"},Jf(M4,{status:J.providerStatus==="online"?"online":"warn"},J.providerStatus||"unknown"),Jf("span",null,y.providerId),Jf("span",null,A.public?"公网暴露":"仅 UniDesk frontend 代理访问")),Jf("p",{className:"muted paragraph"},y.description)),Jf("div",{className:"microservice-ref-card"},Jf("span",null,"Repo"),Jf("strong",null,F.url||"--"),Jf("code",null,F.commitId||"--")),Jf("div",{className:"microservice-ref-card"},Jf("span",null,"D601 Docker"),Jf("strong",null,`${A.nodeBindHost||"--"}:${A.nodePort||"--"}`),Jf("code",null,`${F.composeFile||"--"} / ${F.composeService||"--"}`))),Jf(H0,{error:l.error,wide:!0})),Jf("div",{className:"findjob-grid"},Jf(P4,{title:"岗位指标",eyebrow:l.refreshedAt?`Updated ${L0(l.refreshedAt)}`:"Summary"},Jf("div",{className:"metric-grid"},Jf(h_,{label:"岗位总量",value:My(U,"totalJobs"),hint:"tracked jobs",tone:"ok"}),Jf(h_,{label:"原始岗位",value:My(U,"rawJobs"),hint:"raw queue"}),Jf(h_,{label:"已验证",value:My(U,"verifiedJobs"),hint:"verified set"}),Jf(h_,{label:"优先处理",value:My(U,"prioritizedJobs"),hint:"prioritized"}),Jf(h_,{label:"过期",value:My(U,"staleJobs"),hint:"stale jobs",tone:"warn"}),Jf(h_,{label:"无效",value:My(U,"invalidJobs"),hint:"invalid jobs",tone:"warn"}),Jf(h_,{label:"上海",value:My(U,"shanghaiJobs"),hint:"city filter"}),Jf(h_,{label:"Health",value:l.health?.ok?"OK":"--",hint:"D601 /api/health"})),Jf("div",{className:"panel-actions inline-actions"},Jf(S4,{title:"FindJob Summary",data:U,onOpen:u,testId:"raw-findjob-summary"}))),Jf(P4,{title:"近期岗位",eyebrow:K?`${K.returnedLength}/${K.originalLength} Preview`:`${G.length} Preview`},G.length===0?Jf(Nj,{title:"暂无岗位预览",text:"等待 D601 findjob backend 返回 /api/jobs"}):Jf("div",{className:"table-wrap findjob-job-table"},Jf("table",null,Jf("thead",null,Jf("tr",null,Jf("th",null,"优先级"),Jf("th",null,"状态"),Jf("th",null,"单位"),Jf("th",null,"职位"),Jf("th",null,"城市"),Jf("th",null,"阶段"),Jf("th",null,"截止"),Jf("th",null,"证据"))),Jf("tbody",null,G.map((E)=>Jf("tr",{key:E.id},Jf("td",null,Jf(M4,{status:String(E.priority||"").toLowerCase()||"unknown"},E.priority||"--")),Jf("td",null,Jf(M4,{status:String(E.status||"").toLowerCase()||"unknown"},E.status||"--")),Jf("td",null,E.organization_name||"--",Jf("code",null,E.id||"--")),Jf("td",null,E.display_title||E.title||"--"),Jf("td",null,E.display_city||E.city||"--"),Jf("td",null,E.workflow_stage||"--"),Jf("td",null,E.deadline||"--"),Jf("td",null,E.evidence_url?Jf("a",{href:E.evidence_url,target:"_blank",rel:"noreferrer"},"打开"):Jf("span",{className:"muted"},"无"))))))),Jf("div",{className:"panel-actions inline-actions"},Jf(S4,{title:"FindJob Jobs Preview",data:l.jobs,onOpen:u,testId:"raw-findjob-jobs"}))),Jf(P4,{title:"草稿与报告",eyebrow:`${W.length} Drafts`},W.length===0?Jf(Nj,{title:"暂无草稿",text:"D601 findjob backend 未返回 drafts"}):Jf("div",{className:"draft-list"},W.map((E)=>Jf("article",{key:E.id,className:"draft-card"},Jf("div",{className:"node-card-head"},Jf("strong",null,E.id),Jf(M4,{status:E.status},E.status||"--")),Jf("div",{className:"docker-meta compact"},Jf("span",null,E.workflow_stage||"--"),Jf("span",null,`jobs ${E.counts?.jobs??0}`),Jf("span",null,`reports ${E.counts?.reports??0}`)),Jf("span",null,E.latestReportPath||"暂无报告"),Jf("code",null,zf(E.updated_at||E.updatedAt))))),Jf("div",{className:"panel-actions inline-actions"},Jf(S4,{title:"FindJob Drafts",data:l.drafts,onOpen:u,testId:"raw-findjob-drafts"})))))}var v$=Sf(c0(),1);var b=v$.default.createElement,{useEffect:HN}=v$.default,Lj=v$.default.useState;function C$(f){let u=Number(f);return Number.isFinite(u)?`${Math.max(0,Math.min(100,u)).toFixed(1)}%`:"--"}function Bj(f){if(f===null||f===void 0||f==="")return"--";let u=Number(f);if(!Number.isFinite(u))return"--";if(u<60)return`${Math.max(0,Math.round(u))}s`;if(u<3600)return`${Math.floor(u/60)}m ${Math.round(u%60)}s`;return`${Math.floor(u/3600)}h ${Math.floor(u%3600/60)}m`}function Dj(f,u=2){let _=Number(f);if(!Number.isFinite(_))return f===!1?"false":f===!0?"true":"--";let y=Math.abs(_);if(Number.isInteger(_)||y>=1000)return _.toLocaleString("zh-CN",{maximumFractionDigits:0});if(y>=1)return _.toLocaleString("zh-CN",{maximumFractionDigits:u});return _.toLocaleString("zh-CN",{maximumFractionDigits:Math.max(u,6)})}function x$(f){if(f===null||f===void 0||f==="")return"--";if(typeof f==="boolean")return f?"true":"false";if(typeof f==="number")return Dj(f,4);if(Array.isArray(f))return f.map((u)=>x$(u)).join(" x ");if(typeof f==="object")return"已上报";return String(f)}function R4(f){let u=Number(f);if(!Number.isFinite(u)||u<=0)return"--";let _=u>=100?0:u>=10?1:2;return`${u.toLocaleString("zh-CN",{maximumFractionDigits:_})} epoch/h`}function x4(f){return f.replace(/[^a-zA-Z0-9_-]/g,"-")}function Bu(f){return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function R$({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return b("span",{className:`status-badge ${_}`},u||f||"unknown")}function I_({label:f,value:u,hint:_,tone:y}){return b("article",{className:`metric-card ${y||""}`},b("div",{className:"metric-label"},f),b("div",{className:"metric-value"},u),b("div",{className:"metric-hint"},_))}function Yj({title:f,eyebrow:u,actions:_,children:y,className:l}){return b("section",{className:`panel ${l||""}`},b("div",{className:"panel-head"},b("div",null,u?b("p",{className:"panel-eyebrow"},u):null,b("h2",null,f)),_?b("div",{className:"panel-actions"},_):null),b("div",{className:"panel-body"},y))}function pl({title:f,data:u,onOpen:_,testId:y}){return b("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:(l)=>{l?.stopPropagation?.(),_(f,u)}},"查看原始JSON")}function e1({title:f,text:u}){return b("div",{className:"empty-state"},b("strong",null,f),b("span",null,u))}function VN(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function ON(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function XN(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function NN(f){return f?.counts&&typeof f.counts==="object"&&!Array.isArray(f.counts)?f.counts:{}}function LN(f){return Array.isArray(f?.jobs)?f.jobs.slice(0,240):[]}function YN(f){return Array.isArray(f?.projects)?f.projects.slice(0,1000):[]}function v4(f){return Array.isArray(f?.projects)?f.projects:[]}function BN(f,u){if(Array.isArray(u?.gpu))return u.gpu;if(Array.isArray(f?.gpu))return f.gpu;return[]}function hu(f,u){return`${f}/microservices/met-nonlinear/proxy${u}`}function lz(f){return f.startedAt&&f.finishedAt?Bj((Date.parse(f.finishedAt)-Date.parse(f.startedAt))/1000):"--"}function DN(f){let u=f.progress||{};if(u.etaSeconds!==null&&u.etaSeconds!==void 0&&u.etaSeconds!==""){let j=Number(u.etaSeconds);if(Number.isFinite(j))return Math.max(0,j)}let _=Number(u.currentEpoch),y=Number(u.epochTarget??f.epochTarget),l=Date.parse(f.startedAt||"");if(!Number.isFinite(_)||_<=0||!Number.isFinite(y)||y<=_||!Number.isFinite(l))return null;let $=Math.max(0,(Date.now()-l)/1000);if($<=0)return null;return Math.max(0,$/_*(y-_))}function $z(f){let u=f.progress||{},_=Number(u.epochPerHour);if(Number.isFinite(_)&&_>0)return _;let y=Date.parse(f.startedAt||""),l=["succeeded","failed","canceled"].includes(f.status)?Date.parse(f.finishedAt||""):Date.now();if(!Number.isFinite(y)||!Number.isFinite(l)||l<=y)return null;let $=Number(u.currentEpoch??f.epochTarget);if(!Number.isFinite($)||$<=0)return null;return $/((l-y)/3600000)}function jz(f){if(f==="staged")return"待启动";if(f==="queued")return"排队中";if(f==="running")return"训练中";if(f==="succeeded")return"已完成";if(f==="failed")return"失败";if(f==="canceled")return"已取消";return f||"unknown"}function Jz(f,u,_){return{name:f,path:u,depth:_,count:0,children:[],project:null}}function wN(f){let u=Jz("","",-1);for(let y of f){let $=String(y?.projectPath||"").replace(/\\/g,"/").split("/").filter(Boolean);if($.length===0)continue;let j=u,J=[];for(let[F,A]of $.entries()){J.push(A);let U=J.join("/"),G=j.children.find((W)=>W.path===U);if(!G)G=Jz(A,U,F),j.children.push(G);if(F===$.length-1)G.project=y;j=G}}let _=(y)=>{let l=y.children.reduce(($,j)=>$+_(j),0);return y.count=(y.project?1:0)+l,y.children.sort(($,j)=>{if(Boolean($.project)!==Boolean(j.project))return $.project?1:-1;return $.name.localeCompare(j.name,"zh-CN",{numeric:!0,sensitivity:"base"})}),y.count};return _(u),u}function TN(f){let u=Bu(f.data);return Bu(u.project).projectPath?Bu(u.project):u}function rN(f){return Bu(Bu(f.data).job)}function Fz({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((h)=>h.id==="met-nonlinear")||null,[l,$]=Lj({loading:!1,actionBusy:!1,error:"",health:null,summary:null,queue:null,projects:null,history:null,images:null,refreshedAt:null}),[j,J]=Lj({loading:!1,error:"",kind:"",key:"",title:"",data:null}),[F,A]=Lj(()=>({activeTab:"projects",selectedProjects:{},expandedProjectDirs:{},sourceProject:"",forkCount:1,forkEpochs:200,forkPrefix:`ui_fork_${Date.now()}`,maxConcurrency:3,targetGpuName:"2080 Ti",actionMessage:""}));function U(h){A((i)=>({...i,...h}))}async function G(h=F.activeTab){if(!y)return;$((i)=>({...i,loading:!0,error:""}));try{let i=[["health",wf(`${_}/microservices/met-nonlinear/health`)],["summary",wf(hu(_,"/api/summary"))]];if(h==="projects")i.push(["projectsRoot",wf(hu(_,"/api/projects?root=projects&limit=500"))]),i.push(["exProjectsRoot",wf(hu(_,"/api/projects?root=ex_projects&limit=500"))]);if(h==="current"||h==="completed"||h==="failed")i.push(["queue",wf(hu(_,"/api/queue"))]);if(h==="completed"||h==="failed")i.push(["history",wf(hu(_,"/api/history"))]);if(h==="gpu")i.push(["images",wf(hu(_,"/api/images"))]);let I=Object.fromEntries(await Promise.all(i.map(async([$f,Af])=>[$f,await Af]))),lf={loading:!1,actionBusy:!1,error:"",health:I.health,summary:I.summary,refreshedAt:new Date};if(I.projectsRoot||I.exProjectsRoot){let{projectsRoot:$f,exProjectsRoot:Af}=I;lf.projects={ok:$f?.ok!==!1&&Af?.ok!==!1,roots:[{root:"projects",count:v4($f).length},{root:"ex_projects",count:v4(Af).length}],projects:[...v4($f),...v4(Af)]}}if(I.queue)lf.queue=I.queue;if(I.history)lf.history=I.history;if(I.images)lf.images=I.images;$(($f)=>({...$f,...lf}))}catch(i){$((I)=>({...I,loading:!1,actionBusy:!1,error:Pf(i,"MET Nonlinear 加载失败")}))}}async function W(h,i){$((I)=>({...I,actionBusy:!0,error:""})),U({actionMessage:`${h}...`});try{let I=await i();U({actionMessage:I||`${h}完成`}),await G()}catch(I){$((lf)=>({...lf,actionBusy:!1,error:Pf(I,`${h}失败`)}))}}async function K(){await W("保存并发设置",async()=>{await wf(hu(_,"/api/queue/settings"),{method:"PUT",body:JSON.stringify({maxConcurrency:Number(F.maxConcurrency),targetGpuName:F.targetGpuName})})})}function E(){return Object.entries(F.selectedProjects).filter(([,h])=>h).map(([h])=>h)}async function H(){let h=E();if(h.length===0)throw Error("请先选择至少一个 project");await W("加入待启动队列",async()=>{await wf(hu(_,"/api/queue"),{method:"POST",body:JSON.stringify({projectPaths:h,maxConcurrency:Number(F.maxConcurrency),targetGpuName:F.targetGpuName,start:!1})}),U({activeTab:"current",selectedProjects:{}})})}async function O(){let h=F.sourceProject||S[0]?.projectPath;if(!h)throw Error("请先选择源 project");await W("Fork Project",async()=>{let i=await wf(hu(_,"/api/projects/fork"),{method:"POST",body:JSON.stringify({sourceProject:h,count:Number(F.forkCount),epochs:Number(F.forkEpochs),prefix:F.forkPrefix})}),I=Array.isArray(i.projectPaths)?i.projectPaths:[],lf=I.reduce(($f,Af)=>{return $f[Af]=!0,$f},{...F.selectedProjects});return U({selectedProjects:lf}),`已 fork ${I.length} 个 project,并已自动勾选;请确认后点击加入待启动队列。`})}async function z(){await W("启动队列",async()=>{await wf(hu(_,"/api/queue/start"),{method:"POST",body:JSON.stringify({maxConcurrency:Number(F.maxConcurrency),targetGpuName:F.targetGpuName})}),U({activeTab:"current"})})}async function q(h){await W("取消任务",async()=>{await wf(hu(_,`/api/jobs/${encodeURIComponent(h.id)}/cancel`),{method:"POST",body:JSON.stringify({})})})}async function Z(h){let i=String(h?.projectPath||"");if(!i)return;J({loading:!0,error:"",kind:"project",key:i,title:i,data:null});try{let I=await wf(hu(_,`/api/projects/config?path=${encodeURIComponent(i)}`));J({loading:!1,error:"",kind:"project",key:i,title:i,data:I})}catch(I){J({loading:!1,error:Pf(I,"Project 详情加载失败"),kind:"project",key:i,title:i,data:null})}}async function V(h){let i=String(h?.id||"");if(!i)return;J({loading:!0,error:"",kind:"job",key:i,title:h.projectPath||i,data:null});try{let I=await wf(hu(_,`/api/jobs/${encodeURIComponent(i)}`));J({loading:!1,error:"",kind:"job",key:i,title:I?.job?.projectPath||h.projectPath||i,data:I})}catch(I){J({loading:!1,error:Pf(I,"Job 详情加载失败"),kind:"job",key:i,title:h.projectPath||i,data:null})}}if(HN(()=>{G(F.activeTab)},[y?.id,y?.runtime?.providerStatus,F.activeTab]),!y)return b(e1,{title:"MET Nonlinear 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=met-nonlinear"});let L=VN(y),r=XN(y),N=ON(y),D=NN(l.queue?.queue||l.summary?.queue),x=BN(l.health,l.queue),c=l.health?.targetGpu||l.summary?.targetGpu||x.find((h)=>String(h.name||"").includes("2080")),v=l.images?.mlImage||l.health?.image||{},C=LN(l.queue),S=YN(l.projects),B=wN(S),P=F.sourceProject||S[0]?.projectPath||"",M=C.filter((h)=>["staged","queued","running"].includes(h.status)),w=C.filter((h)=>h.status==="succeeded"),Y=C.filter((h)=>["failed","canceled"].includes(h.status)),R=Array.isArray(l.history?.jobs)?l.history.jobs.slice(0,120):[],k=[{id:"projects",label:"项目库",count:S.length},{id:"current",label:"当前队列",count:M.length||Number(D.staged||0)+Number(D.queued||0)+Number(D.running||0)},{id:"completed",label:"已完成",count:w.length||Number(D.succeeded||0)},{id:"failed",label:"失败诊断",count:Y.length||Number(D.failed||0)+Number(D.canceled||0)},{id:"gpu",label:"GPU/镜像",count:x.length}];function p(h,i){if(h.length===0)return b(e1,{title:i==="current"?"当前队列为空":"暂无记录",text:i==="current"?"从项目库选择或 fork project 后先加入待启动队列,再启动队列。":"终态任务会显示耗时、exit code 和失败诊断。"});return b("div",{className:"table-wrap met-job-table"},b("table",null,b("thead",null,b("tr",null,b("th",null,"状态"),b("th",null,"Project"),b("th",null,"Epoch"),b("th",null,"速度"),b("th",null,"ETA/耗时"),b("th",null,"GPU"),b("th",null,"Exit"),b("th",null,"更新时间"),b("th",null,"操作"))),b("tbody",null,h.map((I)=>{let lf=I.progress||{},$f=["staged","queued","running"].includes(I.status),Af=j.kind==="job"&&j.key===I.id;return b("tr",{key:I.id,className:`met-click-row ${Af?"active":""}`,onClick:()=>V(I),"data-testid":`met-job-row-${x4(I.id)}`},b("td",null,b(R$,{status:I.status},jz(I.status))),b("td",null,b("button",{type:"button",className:"met-inline-link",onClick:(Yf)=>{Yf.stopPropagation(),V(I)}},I.projectPath),b("code",null,I.id)),b("td",null,b("span",null,`${lf.currentEpoch??"--"} / ${lf.epochTarget??I.epochTarget??"--"}`),b("div",{className:"met-progress"},b("span",{style:{width:C$(lf.progressPercent)}}))),b("td",null,b("strong",null,R4($z(I)))),b("td",null,I.status==="succeeded"||I.status==="failed"||I.status==="canceled"?lz(I):I.status==="running"?`ETA ${Bj(DN(I))}`:"--"),b("td",null,I.gpuName||"--"),b("td",null,I.exitCode??"--"),b("td",null,zf(I.updatedAt)),b("td",null,$f?b("button",{type:"button",className:"ghost-btn mini",onClick:(Yf)=>{Yf.stopPropagation(),q(I)},disabled:l.actionBusy},"取消"):null,b(pl,{title:`MET Job ${I.id}`,data:I,onOpen:u,testId:`raw-met-job-${I.id}`})))}))))}function n(){return b("div",{className:"met-queue-summary","data-testid":"met-current-summary"},b(R$,{status:"staged"},`待启动 ${D.staged??0}`),b(R$,{status:"queued"},`排队中 ${D.queued??0}`),b(R$,{status:"running"},`训练中 ${D.running??0}`),b("span",null,`最大并发 ${l.summary?.queue?.maxConcurrency??l.queue?.queue?.maxConcurrency??F.maxConcurrency}`),b("span",null,`目标 GPU ${l.summary?.queue?.targetGpuName??l.queue?.queue?.targetGpuName??F.targetGpuName}`))}function _f(h,i){let I=F.expandedProjectDirs[h];return I===void 0?i<2:Boolean(I)}function s(h,i){let I=_f(h,i);U({expandedProjectDirs:{...F.expandedProjectDirs,[h]:!I}})}function ff(h){let i=8+Math.max(0,h.depth)*16;if(Boolean(h.project)){let $f=h.project,Af=Boolean(F.selectedProjects[$f.projectPath]),Yf=j.kind==="project"&&j.key===$f.projectPath;return b("div",{key:h.path,className:`met-tree-row project ${Af?"selected":""} ${Yf?"active":""}`,style:{paddingLeft:i},onClick:()=>Z($f),"data-testid":`met-project-node-${x4($f.projectPath)}`},b("div",{className:"met-tree-name"},b("input",{type:"checkbox",checked:Af,onClick:(xf)=>xf.stopPropagation(),onChange:(xf)=>U({selectedProjects:{...F.selectedProjects,[$f.projectPath]:xf.target.checked}}),"data-testid":`met-project-checkbox-${x4($f.projectPath)}`}),b("button",{type:"button",className:"met-inline-link project-path",onClick:(xf)=>{xf.stopPropagation(),Z($f)}},h.name)),b("span",null,$f.useModel||"--"),b("span",null,$f.epochTrain??"--"),b("span",null,C$($f.progress?.progressPercent)),b("span",null,R4($f.progress?.epochPerHour)))}let lf=_f(h.path,h.depth);return b(v$.default.Fragment,{key:h.path},b("div",{className:"met-tree-row folder",style:{paddingLeft:i},"data-testid":`met-project-folder-${x4(h.path)}`},b("button",{type:"button",className:"met-tree-toggle",onClick:()=>s(h.path,h.depth),"aria-label":lf?`折叠 ${h.path}`:`展开 ${h.path}`},lf?"-":"+"),b("strong",null,h.name),b("span",{className:"met-tree-count"},`${h.count} projects`)),lf?h.children.map(($f)=>ff($f)):null)}function Kf(h){return b("div",{className:"met-detail-kv"},h.map((i)=>b("div",{key:i.label,className:"met-detail-kv-item"},b("span",null,i.label),b("strong",null,x$(i.value)),i.hint?b("small",null,i.hint):null)))}function Gf(h,i){return b("div",{className:"met-detail-section"},b("h3",null,h),Kf(i))}function jf(h){if(!Array.isArray(h)||h.length===0)return b(e1,{title:"模型层未上报",text:"等待 data/model_info.json 或 compute_analysis.json 生成。"});return b("div",{className:"table-wrap met-layer-table"},b("table",null,b("thead",null,b("tr",null,b("th",null,"Layer"),b("th",null,"Type"),b("th",null,"Params"),b("th",null,"Trainable"),b("th",null,"Compute"))),b("tbody",null,h.slice(0,18).map((i,I)=>b("tr",{key:`${i.name||"layer"}-${I}`},b("td",null,i.name||`#${I+1}`),b("td",null,i.type||"--"),b("td",null,Dj(i.num_params)),b("td",null,i.trainable===void 0?"--":String(Boolean(i.trainable))),b("td",null,Dj(i.compute?.total??i.estimated_cost?.weighted_units?.total)))))))}function Wf(h){let i=Array.isArray(h)?h:[];if(i.length===0)return b(e1,{title:"data/ 暂无文件",text:"训练或评估完成后会生成 training_state、metrics、model_info 等文件。"});return b("div",{className:"met-file-chip-grid"},i.slice(0,48).map((I)=>b("span",{key:I},I)),i.length>48?b("span",null,`+${i.length-48}`):null)}function Of(h){let i=String(h||"").replace(/\x1b\[[0-9;]*[A-Za-z]/g,"").split(/\r?\n/).map((I)=>I.trim()).filter(Boolean).slice(-12);if(i.length===0)return b(e1,{title:"暂无日志尾部",text:"该任务未上报 logTail 或日志已轮转。"});return b("div",{className:"met-log-lines"},i.map((I,lf)=>b("div",{key:`${lf}-${I.slice(0,16)}`},I)))}function Zf(){if(j.loading)return b("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},b(e1,{title:"详情加载中",text:j.title||"正在读取 D601 data/ 和 config.json"}));if(j.error)return b("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},b(H0,{error:j.error,wide:!0}));if(!j.data)return b("section",{className:"met-detail-panel muted","data-testid":"met-detail-panel"},b(e1,{title:"选择一个项目或任务查看详情",text:"项目库、当前队列、已完成和失败诊断中的行都可以点击;默认只展示结构化字段,原始 JSON 需显式点击按钮。"}));let h=TN(j),i=rN(j),I=Bu(h.config),lf=Bu(h.progress||i.progress),$f=Bu(h.data),Af=Bu(h.metrics||$f.metrics||lf.trainingInfo?.evaluation_metrics),Yf=Bu($f.trainingInfo||lf.trainingInfo),xf=Bu($f.trainingState),of=Bu(h.model||$f.model),F0=Array.isArray(of.modelSummary)&&of.modelSummary.length>0?of.modelSummary:of.computeLayers,y0=Bu(Yf.evaluation_metrics),T0=j.kind==="job"?"训练任务详情":"Project 详情";return b("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},b("div",{className:"panel-head compact"},b("div",null,b("p",{className:"panel-eyebrow"},j.kind==="job"?"Job + Project Detail":"Project Library Detail"),b("h2",null,T0),b("code",null,h.projectPath||i.projectPath||j.title)),b("div",{className:"panel-actions"},b(pl,{title:`MET ${T0}`,data:j.data,onOpen:u,testId:"raw-met-detail"}))),j.kind==="job"?Gf("任务状态",[{label:"Job ID",value:i.id},{label:"状态",value:jz(i.status)},{label:"GPU",value:i.gpuName},{label:"Exit Code",value:i.exitCode},{label:"耗时",value:lz(i)},{label:"训练速度",value:R4($z({...i,progress:lf}))}]):null,Gf("config.json",[{label:"use_model",value:I.use_model},{label:"epoch_train",value:I.epoch_train},{label:"step_per_epoch",value:I.step_per_epoch},{label:"learning_rate",value:I.learning_rate},{label:"using_gpu",value:I.using_gpu},{label:"use_points",value:I.use_points},{label:"sample_rate",value:I.sample_rate},{label:"time_clipped_s",value:I.time_clipped_s},{label:"H_UNITS",value:I.H_UNITS},{label:"INNER_KAN_UNITS",value:I.INNER_KAN_UNITS},{label:"INNER_KAN_LAYERS",value:I.INNER_KAN_LAYERS},{label:"GRID_SIZE",value:I.GRID_SIZE},{label:"SPLINE_ORDER",value:I.SPLINE_ORDER},{label:"USE_FAST_MODEL",value:I.USE_FAST_MODEL},{label:"IIR_TRAINABLE",value:I.IIR_TRAINABLE}]),Gf("data/ 训练状态",[{label:"Epoch",value:`${lf.currentEpoch??xf.current_epoch??xf.completed_epoch??"--"} / ${lf.epochTarget??I.epoch_train??"--"}`},{label:"Progress",value:C$(lf.progressPercent)},{label:"Last Loss",value:lf.lastLoss??xf.loss},{label:"Last Val Loss",value:lf.lastValLoss??xf.val_loss},{label:"Min Loss",value:Yf.min_loss??xf.min_loss},{label:"Min Val Loss",value:Yf.min_val_loss??xf.min_val_loss},{label:"Log Lines",value:lf.logLineCount},{label:"ETA",value:Bj(lf.etaSeconds??xf.remaining_time)},{label:"训练速度",value:R4(lf.epochPerHour??xf.smoothed_speed)},{label:"Training Alive",value:xf.training_alive}]),Gf("模型参数",[{label:"Model Type",value:of.modelType??I.use_model},{label:"Total Params",value:of.totalParams,hint:of.totalParams===null||of.totalParams===void 0?"未上报":"data/model_info.json"},{label:"Trainable",value:of.trainableParams},{label:"Non-trainable",value:of.nonTrainableParams},{label:"Compute Cost",value:of.computeCost},{label:"Estimate Status",value:of.estimateStatus},{label:"Unsupported Layers",value:of.unsupportedLayerCount}]),Gf("指标",[{label:"train_loss",value:Af.train_loss??y0.train_loss},{label:"val_loss",value:Af.val_loss??y0.val_loss},{label:"train_mae",value:Af.train_mae??y0.train_mae},{label:"val_mae",value:Af.val_mae??y0.val_mae},{label:"train_afmae",value:Af.train_afmae??y0.train_afmae},{label:"val_afmae",value:Af.val_afmae??y0.val_afmae},{label:"freq_drift_hz",value:Af.freq_drift_hz},{label:"sens_drift_percent",value:Af.sens_drift_percent},{label:"linearity_percent",value:Af.linearity_percent},{label:"weights_source",value:Af.weights_source??y0.weights_source},{label:"lr min/mean/max",value:`${x$(Yf.learning_rate_min)} / ${x$(Yf.learning_rate_mean)} / ${x$(Yf.learning_rate_max)}`}]),b("div",{className:"met-detail-section"},b("h3",null,"模型层"),jf(F0)),b("div",{className:"met-detail-section"},b("h3",null,"data/ 文件"),Wf($f.files)),j.kind==="job"?b("div",{className:"met-detail-section"},b("h3",null,"日志尾部"),Of(Bu(j.data).logTail)):null)}return b("div",{className:"met-page","data-testid":"met-nonlinear-page"},b(Yj,{title:"MET Nonlinear 训练编排",eyebrow:"D601 GPU 用户服务",actions:b("div",{className:"panel-actions"},b("button",{type:"button",className:"ghost-btn",onClick:G,disabled:l.loading,"data-testid":"met-refresh-button"},l.loading?"刷新中":"刷新"),b(pl,{title:"MET Nonlinear 用户服务",data:y,onOpen:u,testId:"raw-met-service"}))},b("div",{className:"findjob-hero"},b("div",null,b("div",{className:"node-version-line"},b(R$,{status:L.providerStatus==="online"?"online":"warn"},L.providerStatus||"unknown"),b("span",null,y.providerId),b("span",null,N.public?"公网暴露":"仅 UniDesk frontend 代理访问")),b("p",{className:"muted paragraph"},y.description)),b("div",{className:"microservice-ref-card"},b("span",null,"Repo"),b("strong",null,r.url||"--"),b("code",null,r.commitId||"--")),b("div",{className:"microservice-ref-card"},b("span",null,"D601 Docker"),b("strong",null,`${N.nodeBindHost||"--"}:${N.nodePort||"--"}`),b("code",null,`${r.composeFile||"--"} / ${r.containerName||"--"}`))),b(H0,{error:l.error,wide:!0}),F.actionMessage?b("div",{className:"met-action-log","data-testid":"met-action-message"},F.actionMessage):null),b("div",{className:"met-grid"},b(Yj,{title:"核心状态",eyebrow:l.refreshedAt?`Updated ${L0(l.refreshedAt)}`:"Queue + GPU"},b("div",{className:"metric-grid"},b(I_,{label:"Staged",value:D.staged??0,hint:"加入队列未开始",tone:Number(D.staged||0)>0?"warn":""}),b(I_,{label:"Queued",value:D.queued??0,hint:"排队等待调度",tone:Number(D.queued||0)>0?"warn":""}),b(I_,{label:"Running",value:D.running??0,hint:`max ${l.summary?.queue?.maxConcurrency??l.queue?.queue?.maxConcurrency??"--"}`,tone:Number(D.running||0)>0?"ok":""}),b(I_,{label:"Succeeded",value:D.succeeded??0,hint:"已完成"}),b(I_,{label:"Failed",value:D.failed??0,hint:"需要诊断",tone:Number(D.failed||0)>0?"warn":""}),b(I_,{label:"2080Ti Free",value:c?C$(Number(c.freeRatio)*100):"--",hint:c?`${c.memoryFreeMiB}/${c.memoryTotalMiB} MiB`:"等待 GPU 上报"}),b(I_,{label:"ML Image",value:v.present?"READY":"MISSING",hint:v.image||"met-nonlinear-ml:tf26",tone:v.present?"ok":"warn"}),b(I_,{label:"Health",value:l.health?.ok?"OK":"--",hint:"D601 /health"}))),b(Yj,{title:"队列控制",eyebrow:"Downloader-like staging"},b("div",{className:"met-control-strip"},b("label",null,"最大并发",b("input",{type:"number",min:1,max:16,value:F.maxConcurrency,"data-testid":"met-max-concurrency-input",onChange:(h)=>U({maxConcurrency:h.target.value})})),b("label",null,"目标 GPU",b("input",{value:F.targetGpuName,"data-testid":"met-target-gpu-input",onChange:(h)=>U({targetGpuName:h.target.value})})),b("button",{type:"button",className:"ghost-btn",onClick:K,disabled:l.actionBusy,"data-testid":"met-save-settings-button"},"保存设置"),b("button",{type:"button",className:"primary-btn",onClick:z,disabled:l.actionBusy||Number(D.staged||0)===0,"data-testid":"met-start-queue-button"},"启动队列")),b("p",{className:"muted paragraph"},"Project 先进入待启动队列,不会立即训练;点击启动队列后才切换为排队中,并由 D601 scheduler 按最大并发和 2080Ti 显存策略调度。")),b("section",{className:"panel met-workspace"},b("div",{className:"met-tabs",role:"tablist"},k.map((h)=>b("button",{key:h.id,type:"button",className:F.activeTab===h.id?"active":"",onClick:()=>U({activeTab:h.id}),"data-testid":`met-tab-${h.id}`},`${h.label} ${h.count}`))),b("div",{className:"panel-body"},F.activeTab==="projects"?b("div",{className:"met-form-grid","data-testid":"met-projects-pane"},b("div",{className:"met-fork-card"},b("h3",null,"Fork Project"),b("label",null,"源 Project",b("select",{value:P,"data-testid":"met-source-project-select",onChange:(h)=>U({sourceProject:h.target.value})},S.map((h)=>b("option",{key:h.projectPath,value:h.projectPath},`${h.projectPath} · ${h.useModel||"model?"}`)))),b("label",null,"Fork 数量",b("input",{type:"number",min:1,max:100,value:F.forkCount,"data-testid":"met-fork-count-input",onChange:(h)=>U({forkCount:h.target.value})})),b("label",null,"训练轮数",b("input",{type:"number",min:1,max:1e5,value:F.forkEpochs,"data-testid":"met-fork-epochs-input",onChange:(h)=>U({forkEpochs:h.target.value})})),b("label",null,"目标前缀",b("input",{value:F.forkPrefix,"data-testid":"met-fork-prefix-input",onChange:(h)=>U({forkPrefix:h.target.value})})),b("button",{type:"button",className:"primary-btn",onClick:O,disabled:l.actionBusy||!P,"data-testid":"met-fork-button"},"Fork Project"),b("p",{className:"muted paragraph"},"Fork 只创建新 Project 并自动勾选,不会直接训练;需要在右侧确认后加入待启动队列。")),b("div",{className:"met-project-list"},b("div",{className:"panel-head compact"},b("div",null,b("p",{className:"panel-eyebrow"},`Existing Projects · ${(l.projects?.roots||[]).map((h)=>`${h.root} ${h.count}`).join(" / ")}`),b("h2",null,"选择已有 Project")),b("button",{type:"button",className:"ghost-btn",onClick:H,disabled:l.actionBusy||E().length===0,"data-testid":"met-stage-selected-button"},`加入待启动队列 (${E().length})`)),S.length===0?b(e1,{title:"暂无 project",text:"等待 D601 返回 /api/projects"}):b("div",{className:"met-project-table","data-testid":"met-project-tree"},b("div",{className:"met-tree-header"},b("span",null,"文件树 Project"),b("span",null,"Model"),b("span",null,"Epochs"),b("span",null,"Progress"),b("span",null,"速度")),B.children.map((h)=>ff(h)))),Zf()):null,F.activeTab==="current"?b("div",{"data-testid":"met-current-pane"},n(),p(M,"current"),Zf(),b("div",{className:"panel-actions inline-actions"},b(pl,{title:"MET Queue",data:l.queue,onOpen:u,testId:"raw-met-queue"}))):null,F.activeTab==="completed"?b("div",{"data-testid":"met-completed-pane"},p(w.length>0?w:R.filter((h)=>h.status==="succeeded"),"completed"),Zf()):null,F.activeTab==="failed"?b("div",{"data-testid":"met-failed-pane"},p(Y.length>0?Y:R.filter((h)=>["failed","canceled"].includes(h.status)),"failed"),Zf(),b("div",{className:"panel-actions inline-actions"},b(pl,{title:"MET History",data:l.history,onOpen:u,testId:"raw-met-history"}))):null,F.activeTab==="gpu"?b("div",{className:"met-gpu-pane","data-testid":"met-gpu-pane"},x.length===0?b(e1,{title:"暂无 GPU 上报",text:"等待 D601 met-nonlinear-ts 或 ML image 提供 nvidia-smi 数据"}):b("div",{className:"table-wrap"},b("table",null,b("thead",null,b("tr",null,b("th",null,"Index"),b("th",null,"Name"),b("th",null,"Free"),b("th",null,"Policy"))),b("tbody",null,x.map((h)=>b("tr",{key:h.index},b("td",null,h.index),b("td",null,h.name),b("td",null,`${h.memoryFreeMiB} / ${h.memoryTotalMiB} MiB`,b("div",{className:"met-progress"},b("span",{style:{width:C$(Number(h.freeRatio)*100)}}))),b("td",null,String(h.name||"").includes("2080")?"target 2080Ti, <20% 限制并发":"non-target")))))),b("div",{className:"panel-actions inline-actions"},b(pl,{title:"MET Images",data:l.images,onOpen:u,testId:"raw-met-images"}))):null))))}var h4=[{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:"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:"codex-queue",label:"Codex Queue"},{id:"project-manager",label:"Project Manager"}]},{id:"config",label:"系统配置",code:"CFG",tabs:[{id:"topology",label:"连接拓扑"},{id:"auth",label:"认证策略"},{id:"security",label:"安全边界"}]}],kl=Object.fromEntries(h4.map((f)=>[f.id,f.tabs[0]?.id??""]));function MN(f){let u=String(f||"").trim();if(!u)return"";try{return decodeURIComponent(u)}catch{return u}}function b4(f){let u=String(f||"/"),[_]=u.split(/[?#]/u,1);if(_==="/")return"/";let l=`/${_.split("/").map(MN).filter(Boolean).join("/")}`;return l.endsWith("/")?l:`${l}/`}function PN(f){let u=2166136261;for(let _ of f)u^=_.charCodeAt(0),u=Math.imul(u,16777619);return Math.abs(u>>>0).toString(36)}function wj(f){return String(f||"").normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"")}function Qz(f){return String(f||"").trim().toLowerCase().replace(/[\s/\\?#%]+/gu,"-").replace(/-+/gu,"-").replace(/^-+|-+$/gu,"")}function Az(f){let u=wj(f.routeSegment||"")||Qz(f.routeSegment||"");if(u)return u;let _=wj(f.id||"");if(_)return _;let y=wj(f.label||"")||Qz(f.label||"");if(y)return y;return`route-${PN(JSON.stringify(f))}`}function Tj(f,u){return`${f}:${u}`}function Uz(f){let u=f.map((F)=>{let A=Az(F);return{...F,routeSegment:A,tabs:F.tabs.map((U)=>({...U,routeSegment:Az(U)}))}}),_={},y={},l={},$=u.map((F)=>{let A=F.tabs[0]?.id??"";l[F.id]=A;let U=F.tabs.map((K)=>{let E=`/${F.routeSegment}/${K.routeSegment}/`,H=[E],O={moduleId:F.id,tabId:K.id};for(let z of H)_[b4(z)]=O;return y[Tj(F.id,K.id)]=E,{...K,canonicalPath:E,aliases:H}}),G=`/${F.routeSegment}/`,W={moduleId:F.id,tabId:A};return _[b4(G)]=W,{...F,routeSegment:F.routeSegment,canonicalPath:G,tabs:U}}),j=$[0],J={moduleId:j?.id||"",tabId:j?.tabs[0]?.id||""};return _["/"]=J,{modules:$,moduleById:Object.fromEntries($.map((F)=>[F.id,F])),defaultActiveTabs:l,routeMap:_,canonicalPathByTarget:y,fallbackTarget:J}}function rj(f,u){return f.routeMap[b4(u)]||f.fallbackTarget}function b$(f,u,_){return f.canonicalPathByTarget[Tj(u,_)]||f.canonicalPathByTarget[Tj(f.fallbackTarget.moduleId,f.fallbackTarget.tabId)]||"/"}function Wz(f,u){let _=f.routeMap[b4(u)];if(!_)return null;return b$(f,_.moduleId,_.tabId)}var fy=Sf(c0(),1);var o=Sf(Zz(),1),a=Sf(c0(),1);function B0(f){if(typeof f==="string"||typeof f==="number")return""+f;let u="";if(Array.isArray(f)){for(let _=0,y;_{}};function Ez(){for(var f=0,u=arguments.length,_={},y;f=0)y=_.slice(l+1),_=_.slice(0,l);if(_&&!u.hasOwnProperty(_))throw Error("unknown type: "+_);return{type:_,name:y}})}c4.prototype=Ez.prototype={constructor:c4,on:function(f,u){var _=this._,y=IN(f+"",_),l,$=-1,j=y.length;if(arguments.length<2){while(++$0)for(var _=Array(l),y=0,l,$;y=0&&(u=f.slice(0,_))!=="xmlns")f=f.slice(_+1);return Mj.hasOwnProperty(u)?{space:Mj[u],local:f}:f}function Pj(f){let u;while(u=f.sourceEvent)f=u;return f}function ju(f,u){if(f=Pj(f),u===void 0)u=f.currentTarget;if(u){var _=u.ownerSVGElement||u;if(_.createSVGPoint){var y=_.createSVGPoint();return y.x=f.clientX,y.y=f.clientY,y=y.matrixTransform(u.getScreenCTM().inverse()),[y.x,y.y]}if(u.getBoundingClientRect){var l=u.getBoundingClientRect();return[f.clientX-l.left-u.clientLeft,f.clientY-l.top-u.clientTop]}}return[f.pageX,f.pageY]}function pN(){}function c_(f){return f==null?pN:function(){return this.querySelector(f)}}function Sj(f){if(typeof f!=="function")f=c_(f);for(var u=this._groups,_=u.length,y=Array(_),l=0;l<_;++l)for(var $=u[l],j=$.length,J=y[l]=Array(j),F,A,U=0;U=Z)Z=q+1;while(!(L=O[Z])&&++Z=0;)if(j=y[l]){if($&&j.compareDocumentPosition($)^4)$.parentNode.insertBefore(j,$);$=j}return this}function gj(f){if(!f)f=uL;function u(G,W){return G&&W?f(G.__data__,W.__data__):!G-!W}for(var _=this._groups,y=_.length,l=Array(y),$=0;$u?1:f>=u?0:NaN}function nj(){var f=arguments[0];return arguments[0]=this,f.apply(null,arguments),this}function tj(){return Array.from(this)}function sj(){for(var f=this._groups,u=0,_=f.length;u<_;++u)for(var y=f[u],l=0,$=y.length;l<$;++l){var j=y[l];if(j)return j}return null}function oj(){let f=0;for(let u of this)++f;return f}function aj(){return!this.node()}function dj(f){for(var u=this._groups,_=0,y=u.length;_1?this.each((u==null?FL:typeof u==="function"?AL:QL)(f,u,_==null?"":_)):p_(this.node(),f)}function p_(f,u){return f.style.getPropertyValue(u)||c$(f).getComputedStyle(f,null).getPropertyValue(u)}function UL(f){return function(){delete this[f]}}function WL(f,u){return function(){this[f]=u}}function GL(f,u){return function(){var _=u.apply(this,arguments);if(_==null)delete this[f];else this[f]=_}}function uJ(f,u){return arguments.length>1?this.each((u==null?UL:typeof u==="function"?GL:WL)(f,u)):this.node()[f]}function Hz(f){return f.trim().split(/^|\s+/)}function _J(f){return f.classList||new Vz(f)}function Vz(f){this._node=f,this._names=Hz(f.getAttribute("class")||"")}Vz.prototype={add:function(f){var u=this._names.indexOf(f);if(u<0)this._names.push(f),this._node.setAttribute("class",this._names.join(" "))},remove:function(f){var u=this._names.indexOf(f);if(u>=0)this._names.splice(u,1),this._node.setAttribute("class",this._names.join(" "))},contains:function(f){return this._names.indexOf(f)>=0}};function Oz(f,u){var _=_J(f),y=-1,l=u.length;while(++y=0)_=u.slice(y+1),u=u.slice(0,y);return{type:u,name:_}})}function SL(f){return function(){var u=this.__on;if(!u)return;for(var _=0,y=-1,l=u.length,$;_()=>f;function i$(f,{sourceEvent:u,subject:_,target:y,identifier:l,active:$,x:j,y:J,dx:F,dy:A,dispatch:U}){Object.defineProperties(this,{type:{value:f,enumerable:!0,configurable:!0},sourceEvent:{value:u,enumerable:!0,configurable:!0},subject:{value:_,enumerable:!0,configurable:!0},target:{value:y,enumerable:!0,configurable:!0},identifier:{value:l,enumerable:!0,configurable:!0},active:{value:$,enumerable:!0,configurable:!0},x:{value:j,enumerable:!0,configurable:!0},y:{value:J,enumerable:!0,configurable:!0},dx:{value:F,enumerable:!0,configurable:!0},dy:{value:A,enumerable:!0,configurable:!0},_:{value:U}})}i$.prototype.on=function(){var f=this._.on.apply(this._,arguments);return f===this._?this:f};function iL(f){return!f.ctrlKey&&!f.button}function gL(){return this.parentNode}function nL(f,u){return u==null?{x:f.x,y:f.y}:u}function tL(){return navigator.maxTouchPoints||"ontouchstart"in this}function g$(){var f=iL,u=gL,_=nL,y=tL,l={},$=Py("start","drag","end"),j=0,J,F,A,U,G=0;function W(V){V.on("mousedown.drag",K).filter(y).on("touchstart.drag",O).on("touchmove.drag",z,Yz).on("touchend.drag touchcancel.drag",q).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function K(V,L){if(U||!f.call(this,V,L))return;var r=Z(this,u.call(this,V,L),V,L,"mouse");if(!r)return;R0(V.view).on("mousemove.drag",E,Sy).on("mouseup.drag",H,Sy),gl(V.view),m4(V),A=!1,J=V.clientX,F=V.clientY,r("start",V)}function E(V){if(u_(V),!A){var L=V.clientX-J,r=V.clientY-F;A=L*L+r*r>G}l.mouse("drag",V)}function H(V){R0(V.view).on("mousemove.drag mouseup.drag",null),k$(V.view,A),u_(V),l.mouse("end",V)}function O(V,L){if(!f.call(this,V,L))return;var r=V.changedTouches,N=u.call(this,V,L),D=r.length,x,c;for(x=0;x>8&15|u>>4&240,u>>4&15|u&240,(u&15)<<4|u&15,1):_===8?i4(u>>24&255,u>>16&255,u>>8&255,(u&255)/255):_===4?i4(u>>12&15|u>>8&240,u>>8&15|u>>4&240,u>>4&15|u&240,((u&15)<<4|u&15)/255):null):(u=oL.exec(f))?new Du(u[1],u[2],u[3],1):(u=aL.exec(f))?new Du(u[1]*255/100,u[2]*255/100,u[3]*255/100,1):(u=dL.exec(f))?i4(u[1],u[2],u[3],u[4]):(u=eL.exec(f))?i4(u[1]*255/100,u[2]*255/100,u[3]*255/100,u[4]):(u=fY.exec(f))?Pz(u[1],u[2]/100,u[3]/100,1):(u=uY.exec(f))?Pz(u[1],u[2]/100,u[3]/100,u[4]):Bz.hasOwnProperty(f)?Tz(Bz[f]):f==="transparent"?new Du(NaN,NaN,NaN,0):null}function Tz(f){return new Du(f>>16&255,f>>8&255,f&255,1)}function i4(f,u,_,y){if(y<=0)f=u=_=NaN;return new Du(f,u,_,y)}function lY(f){if(!(f instanceof o$))f=E1(f);if(!f)return new Du;return f=f.rgb(),new Du(f.r,f.g,f.b,f.opacity)}function tl(f,u,_,y){return arguments.length===1?lY(f):new Du(f,u,_,y==null?1:y)}function Du(f,u,_,y){this.r=+f,this.g=+u,this.b=+_,this.opacity=+y}n$(Du,tl,qJ(o$,{brighter(f){return f=f==null?n4:Math.pow(n4,f),new Du(this.r*f,this.g*f,this.b*f,this.opacity)},darker(f){return f=f==null?t$:Math.pow(t$,f),new Du(this.r*f,this.g*f,this.b*f,this.opacity)},rgb(){return this},clamp(){return new Du(Ry(this.r),Ry(this.g),Ry(this.b),t4(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:rz,formatHex:rz,formatHex8:$Y,formatRgb:Mz,toString:Mz}));function rz(){return`#${Cy(this.r)}${Cy(this.g)}${Cy(this.b)}`}function $Y(){return`#${Cy(this.r)}${Cy(this.g)}${Cy(this.b)}${Cy((isNaN(this.opacity)?1:this.opacity)*255)}`}function Mz(){let f=t4(this.opacity);return`${f===1?"rgb(":"rgba("}${Ry(this.r)}, ${Ry(this.g)}, ${Ry(this.b)}${f===1?")":`, ${f})`}`}function t4(f){return isNaN(f)?1:Math.max(0,Math.min(1,f))}function Ry(f){return Math.max(0,Math.min(255,Math.round(f)||0))}function Cy(f){return f=Ry(f),(f<16?"0":"")+f.toString(16)}function Pz(f,u,_,y){if(y<=0)f=u=_=NaN;else if(_<=0||_>=1)f=u=NaN;else if(u<=0)f=NaN;return new q1(f,u,_,y)}function Cz(f){if(f instanceof q1)return new q1(f.h,f.s,f.l,f.opacity);if(!(f instanceof o$))f=E1(f);if(!f)return new q1;if(f instanceof q1)return f;f=f.rgb();var u=f.r/255,_=f.g/255,y=f.b/255,l=Math.min(u,_,y),$=Math.max(u,_,y),j=NaN,J=$-l,F=($+l)/2;if(J){if(u===$)j=(_-y)/J+(_0&&F<1?0:j;return new q1(j,J,F,f.opacity)}function Rz(f,u,_,y){return arguments.length===1?Cz(f):new q1(f,u,_,y==null?1:y)}function q1(f,u,_,y){this.h=+f,this.s=+u,this.l=+_,this.opacity=+y}n$(q1,Rz,qJ(o$,{brighter(f){return f=f==null?n4:Math.pow(n4,f),new q1(this.h,this.s,this.l*f,this.opacity)},darker(f){return f=f==null?t$:Math.pow(t$,f),new q1(this.h,this.s,this.l*f,this.opacity)},rgb(){var f=this.h%360+(this.h<0)*360,u=isNaN(f)||isNaN(this.s)?0:this.s,_=this.l,y=_+(_<0.5?_:1-_)*u,l=2*_-y;return new Du(EJ(f>=240?f-240:f+120,l,y),EJ(f,l,y),EJ(f<120?f+240:f-120,l,y),this.opacity)},clamp(){return new q1(Sz(this.h),g4(this.s),g4(this.l),t4(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 f=t4(this.opacity);return`${f===1?"hsl(":"hsla("}${Sz(this.h)}, ${g4(this.s)*100}%, ${g4(this.l)*100}%${f===1?")":`, ${f})`}`}}));function Sz(f){return f=(f||0)%360,f<0?f+360:f}function g4(f){return Math.max(0,Math.min(1,f||0))}function EJ(f,u,_){return(f<60?u+(_-u)*f/60:f<180?_:f<240?u+(_-u)*(240-f)/60:u)*255}function HJ(f,u,_,y,l){var $=f*f,j=$*f;return((1-3*f+3*$-j)*u+(4-6*$+3*j)*_+(1+3*f+3*$-3*j)*y+j*l)/6}function VJ(f){var u=f.length-1;return function(_){var y=_<=0?_=0:_>=1?(_=1,u-1):Math.floor(_*u),l=f[y],$=f[y+1],j=y>0?f[y-1]:2*l-$,J=y()=>f;function JY(f,u){return function(_){return f+_*u}}function FY(f,u,_){return f=Math.pow(f,_),u=Math.pow(u,_)-f,_=1/_,function(y){return Math.pow(f+y*u,_)}}function xz(f){return(f=+f)===1?o4:function(u,_){return _-u?FY(u,_,f):a$(isNaN(u)?_:u)}}function o4(f,u){var _=u-f;return _?JY(f,_):a$(isNaN(f)?u:f)}var xy=function f(u){var _=xz(u);function y(l,$){var j=_((l=tl(l)).r,($=tl($)).r),J=_(l.g,$.g),F=_(l.b,$.b),A=o4(l.opacity,$.opacity);return function(U){return l.r=j(U),l.g=J(U),l.b=F(U),l.opacity=A(U),l+""}}return y.gamma=f,y}(1);function vz(f){return function(u){var _=u.length,y=Array(_),l=Array(_),$=Array(_),j,J;for(j=0;j<_;++j)J=tl(u[j]),y[j]=J.r||0,l[j]=J.g||0,$[j]=J.b||0;return y=f(y),l=f(l),$=f($),J.opacity=1,function(F){return J.r=y(F),J.g=l(F),J.b=$(F),J+""}}}var QY=vz(VJ),AY=vz(OJ);function XJ(f,u){if(!u)u=[];var _=f?Math.min(u.length,f.length):0,y=u.slice(),l;return function($){for(l=0;l<_;++l)y[l]=f[l]*(1-$)+u[l]*$;return y}}function bz(f){return ArrayBuffer.isView(f)&&!(f instanceof DataView)}function hz(f,u){var _=u?u.length:0,y=f?Math.min(_,f.length):0,l=Array(y),$=Array(_),j;for(j=0;j_)if($=u.slice(_,$),J[j])J[j]+=$;else J[++j]=$;if((y=y[0])===(l=l[0]))if(J[j])J[j]+=l;else J[++j]=l;else J[++j]=null,F.push({i:j,x:Ju(y,l)});_=YJ.lastIndex}if(_180)U+=360;else if(U-A>180)A+=360;W.push({i:G.push(l(G)+"rotate(",null,y)-2,x:Ju(A,U)})}else if(U)G.push(l(G)+"rotate("+U+y)}function J(A,U,G,W){if(A!==U)W.push({i:G.push(l(G)+"skewX(",null,y)-2,x:Ju(A,U)});else if(U)G.push(l(G)+"skewX("+U+y)}function F(A,U,G,W,K,E){if(A!==G||U!==W){var H=K.push(l(K)+"scale(",null,",",null,")");E.push({i:H-4,x:Ju(A,G)},{i:H-2,x:Ju(U,W)})}else if(G!==1||W!==1)K.push(l(K)+"scale("+G+","+W+")")}return function(A,U){var G=[],W=[];return A=f(A),U=f(U),$(A.translateX,A.translateY,U.translateX,U.translateY,G,W),j(A.rotate,U.rotate,G,W),J(A.skewX,U.skewX,G,W),F(A.scaleX,A.scaleY,U.scaleX,U.scaleY,G,W),A=U=null,function(K){var E=-1,H=W.length,O;while(++E=0)f._call.call(void 0,u);f=f._next}--ol}function tz(){by=(u5=u6.now())+_5,ol=e$=0;try{az()}finally{ol=0,rY(),by=0}}function TY(){var f=u6.now(),u=f-u5;if(u>sz)_5-=u,u5=f}function rY(){var f,u=f5,_,y=1/0;while(u)if(u._call){if(y>u._time)y=u._time;f=u,u=u._next}else _=u._next,u._next=null,u=f?f._next=_:f5=_;f6=f,TJ(y)}function TJ(f){if(ol)return;if(e$)e$=clearTimeout(e$);var u=f-by;if(u>24){if(f<1/0)e$=setTimeout(tz,f-u6.now()-_5);if(d$)d$=clearInterval(d$)}else{if(!d$)u5=u6.now(),d$=setInterval(TY,sz);ol=1,oz(tz)}}function l6(f,u,_){var y=new _6;return u=u==null?0:+u,y.restart((l)=>{y.stop(),f(l+u)},u,_),y}var PY=Py("start","end","cancel","interrupt"),SY=[],fK=0,dz=1,$5=2,l5=3,ez=4,j5=5,$6=6;function __(f,u,_,y,l,$){var j=f.__transition;if(!j)f.__transition={};else if(_ in j)return;CY(f,_,{name:u,index:y,group:l,on:PY,tween:SY,time:$.time,delay:$.delay,duration:$.duration,ease:$.ease,timer:null,state:fK})}function j6(f,u){var _=x0(f,u);if(_.state>fK)throw Error("too late; already scheduled");return _}function s0(f,u){var _=x0(f,u);if(_.state>l5)throw Error("too late; already running");return _}function x0(f,u){var _=f.__transition;if(!_||!(_=_[u]))throw Error("transition not found");return _}function CY(f,u,_){var y=f.__transition,l;y[u]=_,_.timer=y5($,0,_.time);function $(A){if(_.state=dz,_.timer.restart(j,_.delay,_.time),_.delay<=A)j(A-_.delay)}function j(A){var U,G,W,K;if(_.state!==dz)return F();for(U in y){if(K=y[U],K.name!==_.name)continue;if(K.state===l5)return l6(j);if(K.state===ez)K.state=$6,K.timer.stop(),K.on.call("interrupt",f,f.__data__,K.index,K.group),delete y[U];else if(+U$5&&y.state=0)u=u.slice(0,_);return!u||u==="start"})}function fB(f,u,_){var y,l,$=eY(u)?j6:s0;return function(){var j=$(this,f),J=j.on;if(J!==y)(l=(y=J).copy()).on(u,_);j.on=l}}function IJ(f,u){var _=this._id;return arguments.length<2?x0(this.node(),_).on.on(f):this.each(fB(_,f,u))}function uB(f){return function(){var u=this.parentNode;for(var _ in this.__transition)if(+_!==f)return;if(u)u.removeChild(this)}}function cJ(){return this.on("end.remove",uB(this._id))}function pJ(f){var u=this._name,_=this._id;if(typeof f!=="function")f=c_(f);for(var y=this._groups,l=y.length,$=Array(l),j=0;j()=>f;function dJ(f,{sourceEvent:u,target:_,transform:y,dispatch:l}){Object.defineProperties(this,{type:{value:f,enumerable:!0,configurable:!0},sourceEvent:{value:u,enumerable:!0,configurable:!0},target:{value:_,enumerable:!0,configurable:!0},transform:{value:y,enumerable:!0,configurable:!0},_:{value:l}})}function H1(f,u,_){this.k=f,this.x=u,this.y=_}H1.prototype={constructor:H1,scale:function(f){return f===1?this:new H1(this.k*f,this.x,this.y)},translate:function(f,u){return f===0&u===0?this:new H1(this.k,this.x+this.k*f,this.y+this.k*u)},apply:function(f){return[f[0]*this.k+this.x,f[1]*this.k+this.y]},applyX:function(f){return f*this.k+this.x},applyY:function(f){return f*this.k+this.y},invert:function(f){return[(f[0]-this.x)/this.k,(f[1]-this.y)/this.k]},invertX:function(f){return(f-this.x)/this.k},invertY:function(f){return(f-this.y)/this.k},rescaleX:function(f){return f.copy().domain(f.range().map(this.invertX,this).map(f.invert,f))},rescaleY:function(f){return f.copy().domain(f.range().map(this.invertY,this).map(f.invert,f))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var hy=new H1(1,0,0);Q6.prototype=H1.prototype;function Q6(f){while(!f.__zoom)if(!(f=f.parentNode))return hy;return f.__zoom}function q5(f){f.stopImmediatePropagation()}function Iy(f){f.preventDefault(),f.stopImmediatePropagation()}function qB(f){return(!f.ctrlKey||f.type==="wheel")&&!f.button}function EB(){var f=this;if(f instanceof SVGElement){if(f=f.ownerSVGElement||f,f.hasAttribute("viewBox"))return f=f.viewBox.baseVal,[[f.x,f.y],[f.x+f.width,f.y+f.height]];return[[0,0],[f.width.baseVal.value,f.height.baseVal.value]]}return[[0,0],[f.clientWidth,f.clientHeight]]}function yK(){return this.__zoom||hy}function HB(f){return-f.deltaY*(f.deltaMode===1?0.05:f.deltaMode?1:0.002)*(f.ctrlKey?10:1)}function VB(){return navigator.maxTouchPoints||"ontouchstart"in this}function OB(f,u,_){var y=f.invertX(u[0][0])-_[0][0],l=f.invertX(u[1][0])-_[1][0],$=f.invertY(u[0][1])-_[0][1],j=f.invertY(u[1][1])-_[1][1];return f.translate(l>y?(y+l)/2:Math.min(0,y)||Math.max(0,l),j>$?($+j)/2:Math.min(0,$)||Math.max(0,j))}function A6(){var f=qB,u=EB,_=OB,y=HB,l=VB,$=[0,1/0],j=[[-1/0,-1/0],[1/0,1/0]],J=250,F=vy,A=Py("start","zoom","end"),U,G,W,K=500,E=150,H=0,O=10;function z(B){B.property("__zoom",yK).on("wheel.zoom",D,{passive:!1}).on("mousedown.zoom",x).on("dblclick.zoom",c).filter(l).on("touchstart.zoom",v).on("touchmove.zoom",C).on("touchend.zoom touchcancel.zoom",S).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}z.transform=function(B,P,M,w){var Y=B.selection?B.selection():B;if(Y.property("__zoom",yK),B!==Y)L(B,P,M,w);else Y.interrupt().each(function(){r(this,arguments).event(w).start().zoom(null,typeof P==="function"?P.apply(this,arguments):P).end()})},z.scaleBy=function(B,P,M,w){z.scaleTo(B,function(){var Y=this.__zoom.k,R=typeof P==="function"?P.apply(this,arguments):P;return Y*R},M,w)},z.scaleTo=function(B,P,M,w){z.transform(B,function(){var Y=u.apply(this,arguments),R=this.__zoom,k=M==null?V(Y):typeof M==="function"?M.apply(this,arguments):M,p=R.invert(k),n=typeof P==="function"?P.apply(this,arguments):P;return _(Z(q(R,n),k,p),Y,j)},M,w)},z.translateBy=function(B,P,M,w){z.transform(B,function(){return _(this.__zoom.translate(typeof P==="function"?P.apply(this,arguments):P,typeof M==="function"?M.apply(this,arguments):M),u.apply(this,arguments),j)},null,w)},z.translateTo=function(B,P,M,w,Y){z.transform(B,function(){var R=u.apply(this,arguments),k=this.__zoom,p=w==null?V(R):typeof w==="function"?w.apply(this,arguments):w;return _(hy.translate(p[0],p[1]).scale(k.k).translate(typeof P==="function"?-P.apply(this,arguments):-P,typeof M==="function"?-M.apply(this,arguments):-M),R,j)},w,Y)};function q(B,P){return P=Math.max($[0],Math.min($[1],P)),P===B.k?B:new H1(P,B.x,B.y)}function Z(B,P,M){var w=P[0]-M[0]*B.k,Y=P[1]-M[1]*B.k;return w===B.x&&Y===B.y?B:new H1(B.k,w,Y)}function V(B){return[(+B[0][0]+ +B[1][0])/2,(+B[0][1]+ +B[1][1])/2]}function L(B,P,M,w){B.on("start.zoom",function(){r(this,arguments).event(w).start()}).on("interrupt.zoom end.zoom",function(){r(this,arguments).event(w).end()}).tween("zoom",function(){var Y=this,R=arguments,k=r(Y,R).event(w),p=u.apply(Y,R),n=M==null?V(p):typeof M==="function"?M.apply(Y,R):M,_f=Math.max(p[1][0]-p[0][0],p[1][1]-p[0][1]),s=Y.__zoom,ff=typeof P==="function"?P.apply(Y,R):P,Kf=F(s.invert(n).concat(_f/s.k),ff.invert(n).concat(_f/ff.k));return function(Gf){if(Gf===1)Gf=ff;else{var jf=Kf(Gf),Wf=_f/jf[2];Gf=new H1(Wf,n[0]-jf[0]*Wf,n[1]-jf[1]*Wf)}k.zoom(null,Gf)}})}function r(B,P,M){return!M&&B.__zooming||new N(B,P)}function N(B,P){this.that=B,this.args=P,this.active=0,this.sourceEvent=null,this.extent=u.apply(B,P),this.taps=0}N.prototype={event:function(B){if(B)this.sourceEvent=B;return this},start:function(){if(++this.active===1)this.that.__zooming=this,this.emit("start");return this},zoom:function(B,P){if(this.mouse&&B!=="mouse")this.mouse[1]=P.invert(this.mouse[0]);if(this.touch0&&B!=="touch")this.touch0[1]=P.invert(this.touch0[0]);if(this.touch1&&B!=="touch")this.touch1[1]=P.invert(this.touch1[0]);return this.that.__zoom=P,this.emit("zoom"),this},end:function(){if(--this.active===0)delete this.that.__zooming,this.emit("end");return this},emit:function(B){var P=R0(this.that).datum();A.call(B,this.that,new dJ(B,{sourceEvent:this.sourceEvent,target:z,type:B,transform:this.that.__zoom,dispatch:A}),P)}};function D(B,...P){if(!f.apply(this,arguments))return;var M=r(this,P).event(B),w=this.__zoom,Y=Math.max($[0],Math.min($[1],w.k*Math.pow(2,y.apply(this,arguments)))),R=ju(B);if(M.wheel){if(M.mouse[0][0]!==R[0]||M.mouse[0][1]!==R[1])M.mouse[1]=w.invert(M.mouse[0]=R);clearTimeout(M.wheel)}else if(w.k===Y)return;else M.mouse=[R,w.invert(R)],k_(this),M.start();Iy(B),M.wheel=setTimeout(k,E),M.zoom("mouse",_(Z(q(w,Y),M.mouse[0],M.mouse[1]),M.extent,j));function k(){M.wheel=null,M.end()}}function x(B,...P){if(W||!f.apply(this,arguments))return;var M=B.currentTarget,w=r(this,P,!0).event(B),Y=R0(B.view).on("mousemove.zoom",n,!0).on("mouseup.zoom",_f,!0),R=ju(B,M),k=B.clientX,p=B.clientY;gl(B.view),q5(B),w.mouse=[R,this.__zoom.invert(R)],k_(this),w.start();function n(s){if(Iy(s),!w.moved){var ff=s.clientX-k,Kf=s.clientY-p;w.moved=ff*ff+Kf*Kf>H}w.event(s).zoom("mouse",_(Z(w.that.__zoom,w.mouse[0]=ju(s,M),w.mouse[1]),w.extent,j))}function _f(s){Y.on("mousemove.zoom mouseup.zoom",null),k$(s.view,w.moved),Iy(s),w.event(s).end()}}function c(B,...P){if(!f.apply(this,arguments))return;var M=this.__zoom,w=ju(B.changedTouches?B.changedTouches[0]:B,this),Y=M.invert(w),R=M.k*(B.shiftKey?0.5:2),k=_(Z(q(M,R),w,Y),u.apply(this,P),j);if(Iy(B),J>0)R0(this).transition().duration(J).call(L,k,w,B);else R0(this).call(z.transform,k,w,B)}function v(B,...P){if(!f.apply(this,arguments))return;var M=B.touches,w=M.length,Y=r(this,P,B.changedTouches.length===w).event(B),R,k,p,n;q5(B);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:(f)=>`Node type "${f}" 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:(f)=>`The old edge with id=${f} does not exist.`,error009:(f)=>`Marker type "${f}" doesn't exist.`,error008:(f,{id:u,sourceHandle:_,targetHandle:y})=>`Couldn't create edge for ${f} handle id: "${f==="source"?_:y}", edge id: ${u}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:(f)=>`Edge type "${f}" not found. Using fallback type "default".`,error012:(f)=>`Node with id "${f}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(f="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${f}/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."},_3=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],yF=["Enter"," ","Escape"],lF={"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:f,x:u,y:_})=>`Moved selected node ${f}. New position, x: ${u}, y: ${_}`,"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"},g_;(function(f){f.Strict="strict",f.Loose="loose"})(g_||(g_={}));var l_;(function(f){f.Free="free",f.Vertical="vertical",f.Horizontal="horizontal"})(l_||(l_={}));var cy;(function(f){f.Partial="partial",f.Full="full"})(cy||(cy={}));var $F={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null},C1;(function(f){f.Bezier="default",f.Straight="straight",f.Step="step",f.SmoothStep="smoothstep",f.SimpleBezier="simplebezier"})(C1||(C1={}));var n_;(function(f){f.Arrow="arrow",f.ArrowClosed="arrowclosed"})(n_||(n_={}));var Uf;(function(f){f.Left="left",f.Top="top",f.Right="right",f.Bottom="bottom"})(Uf||(Uf={}));var lK={[Uf.Left]:Uf.Right,[Uf.Right]:Uf.Left,[Uf.Top]:Uf.Bottom,[Uf.Bottom]:Uf.Top};function jF(f){return f===null?null:f?"valid":"invalid"}var JF=(f)=>("id"in f)&&("source"in f)&&("target"in f),qK=(f)=>("id"in f)&&("position"in f)&&!("source"in f)&&!("target"in f),FF=(f)=>("id"in f)&&("internals"in f)&&!("source"in f)&&!("target"in f);var G6=(f,u=[0,0])=>{let{width:_,height:y}=R1(f),l=f.origin??u,$=_*l[0],j=y*l[1];return{x:f.position.x-$,y:f.position.y-j}},QF=(f,u={nodeOrigin:[0,0]})=>{if(f.length===0)return{x:0,y:0,width:0,height:0};let _=f.reduce((y,l)=>{let $=typeof l==="string",j=!u.nodeLookup&&!$?l:void 0;if(u.nodeLookup)j=$?u.nodeLookup.get(l):!FF(l)?u.nodeLookup.get(l.id):l;let J=j?V5(j,u.nodeOrigin):{x:0,y:0,x2:0,y2:0};return X5(y,J)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return N5(_)},y3=(f,u={})=>{let _={x:1/0,y:1/0,x2:-1/0,y2:-1/0},y=!1;return f.forEach((l)=>{if(u.filter===void 0||u.filter(l))_=X5(_,V5(l)),y=!0}),y?N5(_):{x:0,y:0,width:0,height:0}},O5=(f,u,[_,y,l]=[0,0,1],$=!1,j=!1)=>{let J={...j3(u,[_,y,l]),width:u.width/l,height:u.height/l},F=[];for(let A of f.values()){let{measured:U,selectable:G=!0,hidden:W=!1}=A;if(j&&!G||W)continue;let K=U.width??A.width??A.initialWidth??null,E=U.height??A.height??A.initialHeight??null,H=l3(J,ky(A)),O=(K??0)*(E??0),z=$&&H>0;if(!A.internals.handleBounds||z||H>=O||A.dragging)F.push(A)}return F},EK=(f,u)=>{let _=new Set;return f.forEach((y)=>{_.add(y.id)}),u.filter((y)=>_.has(y.source)||_.has(y.target))};function XB(f,u){let _=new Map,y=u?.nodes?new Set(u.nodes.map((l)=>l.id)):null;return f.forEach((l)=>{if(l.measured.width&&l.measured.height&&(u?.includeHiddenNodes||!l.hidden)&&(!y||y.has(l.id)))_.set(l.id,l)}),_}async function HK({nodes:f,width:u,height:_,panZoom:y,minZoom:l,maxZoom:$},j){if(f.size===0)return Promise.resolve(!0);let J=XB(f,j),F=y3(J),A=z6(F,u,_,j?.minZoom??l,j?.maxZoom??$,j?.padding??0.1);return await y.setViewport(A,{duration:j?.duration,ease:j?.ease,interpolate:j?.interpolate}),Promise.resolve(!0)}function AF({nodeId:f,nextPosition:u,nodeLookup:_,nodeOrigin:y=[0,0],nodeExtent:l,onError:$}){let j=_.get(f),J=j.parentId?_.get(j.parentId):void 0,{x:F,y:A}=J?J.internals.positionAbsolute:{x:0,y:0},U=j.origin??y,G=j.extent||l;if(j.extent==="parent"&&!j.expandParent)if(!J)$?.("005",Iu.error005());else{let K=J.measured.width,E=J.measured.height;if(K&&E)G=[[F,A],[F+K,A+E]]}else if(J&&u3(j.extent))G=[[j.extent[0][0]+F,j.extent[0][1]+A],[j.extent[1][0]+F,j.extent[1][1]+A]];let W=u3(G)?py(u,G,j.measured):u;if(j.measured.width===void 0||j.measured.height===void 0)$?.("015",Iu.error015());return{position:{x:W.x-F+(j.measured.width??0)*U[0],y:W.y-A+(j.measured.height??0)*U[1]},positionAbsolute:W}}async function VK({nodesToRemove:f=[],edgesToRemove:u=[],nodes:_,edges:y,onBeforeDelete:l}){let $=new Set(f.map((W)=>W.id)),j=[];for(let W of _){if(W.deletable===!1)continue;let K=$.has(W.id),E=!K&&W.parentId&&j.find((H)=>H.id===W.parentId);if(K||E)j.push(W)}let J=new Set(u.map((W)=>W.id)),F=y.filter((W)=>W.deletable!==!1),U=EK(j,F);for(let W of F)if(J.has(W.id)&&!U.find((E)=>E.id===W.id))U.push(W);if(!l)return{edges:U,nodes:j};let G=await l({nodes:j,edges:U});if(typeof G==="boolean")return G?{edges:U,nodes:j}:{edges:[],nodes:[]};return G}var f3=(f,u=0,_=1)=>Math.min(Math.max(f,u),_),py=(f={x:0,y:0},u,_)=>({x:f3(f.x,u[0][0],u[1][0]-(_?.width??0)),y:f3(f.y,u[0][1],u[1][1]-(_?.height??0))});function OK(f,u,_){let{width:y,height:l}=R1(_),{x:$,y:j}=_.internals.positionAbsolute;return py(f,[[$,j],[$+y,j+l]],u)}var $K=(f,u,_)=>{if(f_)return-f3(Math.abs(f-_),1,u)/u;return 0},XK=(f,u,_=15,y=40)=>{let l=$K(f.x,y,u.width-y)*_,$=$K(f.y,y,u.height-y)*_;return[l,$]},X5=(f,u)=>({x:Math.min(f.x,u.x),y:Math.min(f.y,u.y),x2:Math.max(f.x2,u.x2),y2:Math.max(f.y2,u.y2)}),_F=({x:f,y:u,width:_,height:y})=>({x:f,y:u,x2:f+_,y2:u+y}),N5=({x:f,y:u,x2:_,y2:y})=>({x:f,y:u,width:_-f,height:y-u}),ky=(f,u=[0,0])=>{let{x:_,y}=FF(f)?f.internals.positionAbsolute:G6(f,u);return{x:_,y,width:f.measured?.width??f.width??f.initialWidth??0,height:f.measured?.height??f.height??f.initialHeight??0}},V5=(f,u=[0,0])=>{let{x:_,y}=FF(f)?f.internals.positionAbsolute:G6(f,u);return{x:_,y,x2:_+(f.measured?.width??f.width??f.initialWidth??0),y2:y+(f.measured?.height??f.height??f.initialHeight??0)}},UF=(f,u)=>N5(X5(_F(f),_F(u))),l3=(f,u)=>{let _=Math.max(0,Math.min(f.x+f.width,u.x+u.width)-Math.max(f.x,u.x)),y=Math.max(0,Math.min(f.y+f.height,u.y+u.height)-Math.max(f.y,u.y));return Math.ceil(_*y)},WF=(f)=>u1(f.width)&&u1(f.height)&&u1(f.x)&&u1(f.y),u1=(f)=>!isNaN(f)&&isFinite(f),GF=(f,u)=>{},$3=(f,u=[1,1])=>{return{x:u[0]*Math.round(f.x/u[0]),y:u[1]*Math.round(f.y/u[1])}},j3=({x:f,y:u},[_,y,l],$=!1,j=[1,1])=>{let J={x:(f-_)/l,y:(u-y)/l};return $?$3(J,j):J},W6=({x:f,y:u},[_,y,l])=>{return{x:f*l+_,y:u*l+y}};function dl(f,u){if(typeof f==="number")return Math.floor((u-u/(1+f))*0.5);if(typeof f==="string"&&f.endsWith("px")){let _=parseFloat(f);if(!Number.isNaN(_))return Math.floor(_)}if(typeof f==="string"&&f.endsWith("%")){let _=parseFloat(f);if(!Number.isNaN(_))return Math.floor(u*_*0.01)}return console.error(`[React Flow] The padding value "${f}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function NB(f,u,_){if(typeof f==="string"||typeof f==="number"){let y=dl(f,_),l=dl(f,u);return{top:y,right:l,bottom:y,left:l,x:l*2,y:y*2}}if(typeof f==="object"){let y=dl(f.top??f.y??0,_),l=dl(f.bottom??f.y??0,_),$=dl(f.left??f.x??0,u),j=dl(f.right??f.x??0,u);return{top:y,right:j,bottom:l,left:$,x:$+j,y:y+l}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function LB(f,u,_,y,l,$){let{x:j,y:J}=W6(f,[u,_,y]),{x:F,y:A}=W6({x:f.x+f.width,y:f.y+f.height},[u,_,y]),U=l-F,G=$-A;return{left:Math.floor(j),top:Math.floor(J),right:Math.floor(U),bottom:Math.floor(G)}}var z6=(f,u,_,y,l,$)=>{let j=NB($,u,_),J=(u-j.x)/f.width,F=(_-j.y)/f.height,A=Math.min(J,F),U=f3(A,y,l),G=f.x+f.width/2,W=f.y+f.height/2,K=u/2-G*U,E=_/2-W*U,H=LB(f,K,E,U,u,_),O={left:Math.min(H.left-j.left,0),top:Math.min(H.top-j.top,0),right:Math.min(H.right-j.right,0),bottom:Math.min(H.bottom-j.bottom,0)};return{x:K-O.left+O.right,y:E-O.top+O.bottom,zoom:U}},J3=()=>typeof navigator<"u"&&navigator?.userAgent?.indexOf("Mac")>=0;function u3(f){return f!==void 0&&f!==null&&f!=="parent"}function R1(f){return{width:f.measured?.width??f.width??f.initialWidth??0,height:f.measured?.height??f.height??f.initialHeight??0}}function zF(f){return(f.measured?.width??f.width??f.initialWidth)!==void 0&&(f.measured?.height??f.height??f.initialHeight)!==void 0}function KF(f,u={width:0,height:0},_,y,l){let $={...f},j=y.get(_);if(j){let J=j.origin||l;$.x+=j.internals.positionAbsolute.x-(u.width??0)*J[0],$.y+=j.internals.positionAbsolute.y-(u.height??0)*J[1]}return $}function ZF(f,u){if(f.size!==u.size)return!1;for(let _ of f)if(!u.has(_))return!1;return!0}function NK(){let f,u;return{promise:new Promise((y,l)=>{f=y,u=l}),resolve:f,reject:u}}function LK(f){return{...lF,...f||{}}}function U6(f,{snapGrid:u=[0,0],snapToGrid:_=!1,transform:y,containerBounds:l}){let{x:$,y:j}=_1(f),J=j3({x:$-(l?.left??0),y:j-(l?.top??0)},y),{x:F,y:A}=_?$3(J,u):J;return{xSnapped:F,ySnapped:A,...J}}var L5=(f)=>({width:f.offsetWidth,height:f.offsetHeight}),qF=(f)=>f?.getRootNode?.()||window?.document,YB=["INPUT","SELECT","TEXTAREA"];function EF(f){let u=f.composedPath?.()?.[0]||f.target;if(u?.nodeType!==1)return!1;return YB.includes(u.nodeName)||u.hasAttribute("contenteditable")||!!u.closest(".nokey")}var HF=(f)=>("clientX"in f),_1=(f,u)=>{let _=HF(f),y=_?f.clientX:f.touches?.[0].clientX,l=_?f.clientY:f.touches?.[0].clientY;return{x:y-(u?.left??0),y:l-(u?.top??0)}},jK=(f,u,_,y,l)=>{let $=u.querySelectorAll(`.${f}`);if(!$||!$.length)return null;return Array.from($).map((j)=>{let J=j.getBoundingClientRect();return{id:j.getAttribute("data-handleid"),type:f,nodeId:l,position:j.getAttribute("data-handlepos"),x:(J.left-_.left)/y,y:(J.top-_.top)/y,...L5(j)}})};function Y5({sourceX:f,sourceY:u,targetX:_,targetY:y,sourceControlX:l,sourceControlY:$,targetControlX:j,targetControlY:J}){let F=f*0.125+l*0.375+j*0.375+_*0.125,A=u*0.125+$*0.375+J*0.375+y*0.125,U=Math.abs(F-f),G=Math.abs(A-u);return[F,A,U,G]}function E5(f,u){if(f>=0)return 0.5*f;return u*25*Math.sqrt(-f)}function JK({pos:f,x1:u,y1:_,x2:y,y2:l,c:$}){switch(f){case Uf.Left:return[u-E5(u-y,$),_];case Uf.Right:return[u+E5(y-u,$),_];case Uf.Top:return[u,_-E5(_-l,$)];case Uf.Bottom:return[u,_+E5(l-_,$)]}}function B5({sourceX:f,sourceY:u,sourcePosition:_=Uf.Bottom,targetX:y,targetY:l,targetPosition:$=Uf.Top,curvature:j=0.25}){let[J,F]=JK({pos:_,x1:f,y1:u,x2:y,y2:l,c:j}),[A,U]=JK({pos:$,x1:y,y1:l,x2:f,y2:u,c:j}),[G,W,K,E]=Y5({sourceX:f,sourceY:u,targetX:y,targetY:l,sourceControlX:J,sourceControlY:F,targetControlX:A,targetControlY:U});return[`M${f},${u} C${J},${F} ${A},${U} ${y},${l}`,G,W,K,E]}function VF({sourceX:f,sourceY:u,targetX:_,targetY:y}){let l=Math.abs(_-f)/2,$=_0}var BB=({source:f,sourceHandle:u,target:_,targetHandle:y})=>`xy-edge__${f}${u||""}-${_}${y||""}`,DB=(f,u)=>{return u.some((_)=>_.source===f.source&&_.target===f.target&&(_.sourceHandle===f.sourceHandle||!_.sourceHandle&&!f.sourceHandle)&&(_.targetHandle===f.targetHandle||!_.targetHandle&&!f.targetHandle))},OF=(f,u,_={})=>{if(!f.source||!f.target)return GF("006",Iu.error006()),u;let y=_.getEdgeId||BB,l;if(JF(f))l={...f};else l={...f,id:y(f)};if(DB(l,u))return u;if(l.sourceHandle===null)delete l.sourceHandle;if(l.targetHandle===null)delete l.targetHandle;return u.concat(l)};function D5({sourceX:f,sourceY:u,targetX:_,targetY:y}){let[l,$,j,J]=VF({sourceX:f,sourceY:u,targetX:_,targetY:y});return[`M ${f},${u}L ${_},${y}`,l,$,j,J]}var FK={[Uf.Left]:{x:-1,y:0},[Uf.Right]:{x:1,y:0},[Uf.Top]:{x:0,y:-1},[Uf.Bottom]:{x:0,y:1}},wB=({source:f,sourcePosition:u=Uf.Bottom,target:_})=>{if(u===Uf.Left||u===Uf.Right)return f.x<_.x?{x:1,y:0}:{x:-1,y:0};return f.y<_.y?{x:0,y:1}:{x:0,y:-1}},QK=(f,u)=>Math.sqrt(Math.pow(u.x-f.x,2)+Math.pow(u.y-f.y,2));function TB({source:f,sourcePosition:u=Uf.Bottom,target:_,targetPosition:y=Uf.Top,center:l,offset:$,stepPosition:j}){let J=FK[u],F=FK[y],A={x:f.x+J.x*$,y:f.y+J.y*$},U={x:_.x+F.x*$,y:_.y+F.y*$},G=wB({source:A,sourcePosition:u,target:U}),W=G.x!==0?"x":"y",K=G[W],E=[],H,O,z={x:0,y:0},q={x:0,y:0},[,,Z,V]=VF({sourceX:f.x,sourceY:f.y,targetX:_.x,targetY:_.y});if(J[W]*F[W]===-1){if(W==="x")H=l.x??A.x+(U.x-A.x)*j,O=l.y??(A.y+U.y)/2;else H=l.x??(A.x+U.x)/2,O=l.y??A.y+(U.y-A.y)*j;let D=[{x:H,y:A.y},{x:H,y:U.y}],x=[{x:A.x,y:O},{x:U.x,y:O}];if(J[W]===K)E=W==="x"?D:x;else E=W==="x"?x:D}else{let D=[{x:A.x,y:U.y}],x=[{x:U.x,y:A.y}];if(W==="x")E=J.x===K?x:D;else E=J.y===K?D:x;if(u===y){let B=Math.abs(f[W]-_[W]);if(B<=$){let P=Math.min($-1,$-B);if(J[W]===K)z[W]=(A[W]>f[W]?-1:1)*P;else q[W]=(U[W]>_[W]?-1:1)*P}}if(u!==y){let B=W==="x"?"y":"x",P=J[W]===F[B],M=A[B]>U[B],w=A[B]=S)H=(c.x+v.x)/2,O=E[0].y;else H=E[0].x,O=(c.y+v.y)/2}let L={x:A.x+z.x,y:A.y+z.y},r={x:U.x+q.x,y:U.y+q.y};return[[f,...L.x!==E[0].x||L.y!==E[0].y?[L]:[],...E,...r.x!==E[E.length-1].x||r.y!==E[E.length-1].y?[r]:[],_],H,O,Z,V]}function rB(f,u,_,y){let l=Math.min(QK(f,u)/2,QK(u,_)/2,y),{x:$,y:j}=u;if(f.x===$&&$===_.x||f.y===j&&j===_.y)return`L${$} ${j}`;if(f.y===j){let A=f.x<_.x?-1:1,U=f.y<_.y?1:-1;return`L ${$+l*A},${j}Q ${$},${j} ${$},${j+l*U}`}let J=f.x<_.x?1:-1,F=f.y<_.y?-1:1;return`L ${$},${j+l*F}Q ${$},${j} ${$+l*J},${j}`}function K6({sourceX:f,sourceY:u,sourcePosition:_=Uf.Bottom,targetX:y,targetY:l,targetPosition:$=Uf.Top,borderRadius:j=5,centerX:J,centerY:F,offset:A=20,stepPosition:U=0.5}){let[G,W,K,E,H]=TB({source:{x:f,y:u},sourcePosition:_,target:{x:y,y:l},targetPosition:$,center:{x:J,y:F},offset:A,stepPosition:U}),O=`M${G[0].x} ${G[0].y}`;for(let z=1;z_.id===u))||null}function w5(f,u){if(!f)return"";if(typeof f==="string")return f;return`${u?`${u}__`:""}${Object.keys(f).sort().map((y)=>`${y}=${f[y]}`).join("&")}`}function wK(f,{id:u,defaultColor:_,defaultMarkerStart:y,defaultMarkerEnd:l}){let $=new Set;return f.reduce((j,J)=>{return[J.markerStart||y,J.markerEnd||l].forEach((F)=>{if(F&&typeof F==="object"){let A=w5(F,u);if(!$.has(A))j.push({id:A,color:F.color||_,...F}),$.add(A)}}),j},[]).sort((j,J)=>j.id.localeCompare(J.id))}var TK=1000,MB=10,XF={nodeOrigin:[0,0],nodeExtent:_3,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},PB={...XF,checkEquality:!0};function NF(f,u){let _={...f};for(let y in u)if(u[y]!==void 0)_[y]=u[y];return _}function rK(f,u,_){let y=NF(XF,_);for(let l of f.values())if(l.parentId)YF(l,f,u,y);else{let $=G6(l,y.nodeOrigin),j=u3(l.extent)?l.extent:y.nodeExtent,J=py($,j,R1(l));l.internals.positionAbsolute=J}}function SB(f,u){if(!f.handles)return!f.measured?void 0:u?.internals.handleBounds;let _=[],y=[];for(let l of f.handles){let $={id:l.id,width:l.width??1,height:l.height??1,nodeId:f.id,x:l.x,y:l.y,position:l.position,type:l.type};if(l.type==="source")_.push($);else if(l.type==="target")y.push($)}return{source:_,target:y}}function LF(f){return f==="manual"}function T5(f,u,_,y={}){let l=NF(PB,y),$={i:0},j=new Map(u),J=l?.elevateNodesOnSelect&&!LF(l.zIndexMode)?TK:0,F=f.length>0,A=!1;u.clear(),_.clear();for(let U of f){let G=j.get(U.id);if(l.checkEquality&&U===G?.internals.userNode)u.set(U.id,G);else{let W=G6(U,l.nodeOrigin),K=u3(U.extent)?U.extent:l.nodeExtent,E=py(W,K,R1(U));G={...l.defaults,...U,measured:{width:U.measured?.width,height:U.measured?.height},internals:{positionAbsolute:E,handleBounds:SB(U,G),z:MK(U,J,l.zIndexMode),userNode:U}},u.set(U.id,G)}if((G.measured===void 0||G.measured.width===void 0||G.measured.height===void 0)&&!G.hidden)F=!1;if(U.parentId)YF(G,u,_,y,$);A||=U.selected??!1}return{nodesInitialized:F,hasSelectedNodes:A}}function CB(f,u){if(!f.parentId)return;let _=u.get(f.parentId);if(_)_.set(f.id,f);else u.set(f.parentId,new Map([[f.id,f]]))}function YF(f,u,_,y,l){let{elevateNodesOnSelect:$,nodeOrigin:j,nodeExtent:J,zIndexMode:F}=NF(XF,y),A=f.parentId,U=u.get(A);if(!U){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(CB(f,_),l&&!U.parentId&&U.internals.rootParentIndex===void 0&&F==="auto")U.internals.rootParentIndex=++l.i,U.internals.z=U.internals.z+l.i*MB;if(l&&U.internals.rootParentIndex!==void 0)l.i=U.internals.rootParentIndex;let G=$&&!LF(F)?TK:0,{x:W,y:K,z:E}=RB(f,U,j,J,G,F),{positionAbsolute:H}=f.internals,O=W!==H.x||K!==H.y;if(O||E!==f.internals.z)u.set(f.id,{...f,internals:{...f.internals,positionAbsolute:O?{x:W,y:K}:H,z:E}})}function MK(f,u,_){let y=u1(f.zIndex)?f.zIndex:0;if(LF(_))return y;return y+(f.selected?u:0)}function RB(f,u,_,y,l,$){let{x:j,y:J}=u.internals.positionAbsolute,F=R1(f),A=G6(f,_),U=u3(f.extent)?py(A,f.extent,F):A,G=py({x:j+U.x,y:J+U.y},y,F);if(f.extent==="parent")G=OK(G,F,u);let W=MK(f,l,$),K=u.internals.z??0;return{x:G.x,y:G.y,z:K>=W?K+1:W}}function r5(f,u,_,y=[0,0]){let l=[],$=new Map;for(let j of f){let J=u.get(j.parentId);if(!J)continue;let F=$.get(j.parentId)?.expandedRect??ky(J),A=UF(F,j.rect);$.set(j.parentId,{expandedRect:A,parent:J})}if($.size>0)$.forEach(({expandedRect:j,parent:J},F)=>{let A=J.internals.positionAbsolute,U=R1(J),G=J.origin??y,W=j.x0||K>0||O||z)l.push({id:F,type:"position",position:{x:J.position.x-W+O,y:J.position.y-K+z}}),_.get(F)?.forEach((q)=>{if(!f.some((Z)=>Z.id===q.id))l.push({id:q.id,type:"position",position:{x:q.position.x+W,y:q.position.y+K}})});if(U.width0){let K=r5(W,u,_,l);A.push(...K)}return{changes:A,updatedInternals:F}}async function SK({delta:f,panZoom:u,transform:_,translateExtent:y,width:l,height:$}){if(!u||!f.x&&!f.y)return Promise.resolve(!1);let j=await u.setViewportConstrained({x:_[0]+f.x,y:_[1]+f.y,zoom:_[2]},[[0,0],[l,$]],y),J=!!j&&(j.x!==_[0]||j.y!==_[1]||j.k!==_[2]);return Promise.resolve(J)}function GK(f,u,_,y,l,$){let j=l,J=y.get(j)||new Map;y.set(j,J.set(_,u)),j=`${l}-${f}`;let F=y.get(j)||new Map;if(y.set(j,F.set(_,u)),$){j=`${l}-${f}-${$}`;let A=y.get(j)||new Map;y.set(j,A.set(_,u))}}function BF(f,u,_){f.clear(),u.clear();for(let y of _){let{source:l,target:$,sourceHandle:j=null,targetHandle:J=null}=y,F={edgeId:y.id,source:l,target:$,sourceHandle:j,targetHandle:J},A=`${l}-${j}--${$}-${J}`,U=`${$}-${J}--${l}-${j}`;GK("source",F,U,f,l,j),GK("target",F,A,f,$,J),u.set(y.id,y)}}function CK(f,u){if(!f.parentId)return!1;let _=u.get(f.parentId);if(!_)return!1;if(_.selected)return!0;return CK(_,u)}function zK(f,u,_){let y=f;do{if(y?.matches?.(u))return!0;if(y===_)return!1;y=y?.parentElement}while(y);return!1}function xB(f,u,_,y){let l=new Map;for(let[$,j]of f)if((j.selected||j.id===y)&&(!j.parentId||!CK(j,f))&&(j.draggable||u&&typeof j.draggable>"u")){let J=f.get($);if(J)l.set($,{id:$,position:J.position||{x:0,y:0},distance:{x:_.x-J.internals.positionAbsolute.x,y:_.y-J.internals.positionAbsolute.y},extent:J.extent,parentId:J.parentId,origin:J.origin,expandParent:J.expandParent,internals:{positionAbsolute:J.internals.positionAbsolute||{x:0,y:0}},measured:{width:J.measured.width??0,height:J.measured.height??0}})}return l}function eJ({nodeId:f,dragItems:u,nodeLookup:_,dragging:y=!0}){let l=[];for(let[j,J]of u){let F=_.get(j)?.internals.userNode;if(F)l.push({...F,position:J.position,dragging:y})}if(!f)return[l[0],l];let $=_.get(f)?.internals.userNode;return[!$?l[0]:{...$,position:u.get(f)?.position||$.position,dragging:y},l]}function vB({dragItems:f,snapGrid:u,x:_,y}){let l=f.values().next().value;if(!l)return null;let $={x:_-l.distance.x,y:y-l.distance.y},j=$3($,u);return{x:j.x-$.x,y:j.y-$.y}}function RK({onNodeMouseDown:f,getStoreItems:u,onDragStart:_,onDrag:y,onDragStop:l}){let $={x:null,y:null},j=0,J=new Map,F=!1,A={x:0,y:0},U=null,G=!1,W=null,K=!1,E=!1,H=null;function O({noDragClassName:q,handleSelector:Z,domNode:V,isSelectable:L,nodeId:r,nodeClickDistance:N=0}){W=R0(V);function D({x:C,y:S}){let{nodeLookup:B,nodeExtent:P,snapGrid:M,snapToGrid:w,nodeOrigin:Y,onNodeDrag:R,onSelectionDrag:k,onError:p,updateNodePositions:n}=u();$={x:C,y:S};let _f=!1,s=J.size>1,ff=s&&P?_F(y3(J)):null,Kf=s&&w?vB({dragItems:J,snapGrid:M,x:C,y:S}):null;for(let[Gf,jf]of J){if(!B.has(Gf))continue;let Wf={x:C-jf.distance.x,y:S-jf.distance.y};if(w)Wf=Kf?{x:Math.round(Wf.x+Kf.x),y:Math.round(Wf.y+Kf.y)}:$3(Wf,M);let Of=null;if(s&&P&&!jf.extent&&ff){let{positionAbsolute:i}=jf.internals,I=i.x-ff.x+P[0][0],lf=i.x+jf.measured.width-ff.x2+P[1][0],$f=i.y-ff.y+P[0][1],Af=i.y+jf.measured.height-ff.y2+P[1][1];Of=[[I,$f],[lf,Af]]}let{position:Zf,positionAbsolute:h}=AF({nodeId:Gf,nextPosition:Wf,nodeLookup:B,nodeExtent:Of?Of:P,nodeOrigin:Y,onError:p});_f=_f||jf.position.x!==Zf.x||jf.position.y!==Zf.y,jf.position=Zf,jf.internals.positionAbsolute=h}if(E=E||_f,!_f)return;if(n(J,!0),H&&(y||R||!r&&k)){let[Gf,jf]=eJ({nodeId:r,dragItems:J,nodeLookup:B});if(y?.(H,J,Gf,jf),R?.(H,Gf,jf),!r)k?.(H,jf)}}async function x(){if(!U)return;let{transform:C,panBy:S,autoPanSpeed:B,autoPanOnNodeDrag:P}=u();if(!P){F=!1,cancelAnimationFrame(j);return}let[M,w]=XK(A,U,B);if(M!==0||w!==0){if($.x=($.x??0)-M/C[2],$.y=($.y??0)-w/C[2],await S({x:M,y:w}))D($)}j=requestAnimationFrame(x)}function c(C){let{nodeLookup:S,multiSelectionActive:B,nodesDraggable:P,transform:M,snapGrid:w,snapToGrid:Y,selectNodesOnDrag:R,onNodeDragStart:k,onSelectionDragStart:p,unselectNodesAndEdges:n}=u();if(G=!0,(!R||!L)&&!B&&r){if(!S.get(r)?.selected)n()}if(L&&R&&r)f?.(r);let _f=U6(C.sourceEvent,{transform:M,snapGrid:w,snapToGrid:Y,containerBounds:U});if($=_f,J=xB(S,P,_f,r),J.size>0&&(_||k||!r&&p)){let[s,ff]=eJ({nodeId:r,dragItems:J,nodeLookup:S});if(_?.(C.sourceEvent,J,s,ff),k?.(C.sourceEvent,s,ff),!r)p?.(C.sourceEvent,ff)}}let v=g$().clickDistance(N).on("start",(C)=>{let{domNode:S,nodeDragThreshold:B,transform:P,snapGrid:M,snapToGrid:w}=u();if(U=S?.getBoundingClientRect()||null,K=!1,E=!1,H=C.sourceEvent,B===0)c(C);$=U6(C.sourceEvent,{transform:P,snapGrid:M,snapToGrid:w,containerBounds:U}),A=_1(C.sourceEvent,U)}).on("drag",(C)=>{let{autoPanOnNodeDrag:S,transform:B,snapGrid:P,snapToGrid:M,nodeDragThreshold:w,nodeLookup:Y}=u(),R=U6(C.sourceEvent,{transform:B,snapGrid:P,snapToGrid:M,containerBounds:U});if(H=C.sourceEvent,C.sourceEvent.type==="touchmove"&&C.sourceEvent.touches.length>1||r&&!Y.has(r))K=!0;if(K)return;if(!F&&S&&G)F=!0,x();if(!G){let k=_1(C.sourceEvent,U),p=k.x-A.x,n=k.y-A.y;if(Math.sqrt(p*p+n*n)>w)c(C)}if(($.x!==R.xSnapped||$.y!==R.ySnapped)&&J&&G)A=_1(C.sourceEvent,U),D(R)}).on("end",(C)=>{if(!G||K)return;if(F=!1,G=!1,cancelAnimationFrame(j),J.size>0){let{nodeLookup:S,updateNodePositions:B,onNodeDragStop:P,onSelectionDragStop:M}=u();if(E)B(J,!1),E=!1;if(l||P||!r&&M){let[w,Y]=eJ({nodeId:r,dragItems:J,nodeLookup:S,dragging:!1});if(l?.(C.sourceEvent,J,w,Y),P?.(C.sourceEvent,w,Y),!r)M?.(C.sourceEvent,Y)}}}).filter((C)=>{let S=C.target;return!C.button&&(!q||!zK(S,`.${q}`,V))&&(!Z||zK(S,Z,V))});W.call(v)}function z(){W?.on(".drag",null)}return{update:O,destroy:z}}function bB(f,u,_){let y=[],l={x:f.x-_,y:f.y-_,width:_*2,height:_*2};for(let $ of u.values())if(l3(l,ky($))>0)y.push($);return y}var hB=250;function IB(f,u,_,y){let l=[],$=1/0,j=bB(f,_,u+hB);for(let J of j){let F=[...J.internals.handleBounds?.source??[],...J.internals.handleBounds?.target??[]];for(let A of F){if(y.nodeId===A.nodeId&&y.type===A.type&&y.id===A.id)continue;let{x:U,y:G}=t_(J,A,A.position,!0),W=Math.sqrt(Math.pow(U-f.x,2)+Math.pow(G-f.y,2));if(W>u)continue;if(W<$)l=[{...A,x:U,y:G}],$=W;else if(W===$)l.push({...A,x:U,y:G})}}if(!l.length)return null;if(l.length>1){let J=y.type==="source"?"target":"source";return l.find((F)=>F.type===J)??l[0]}return l[0]}function xK(f,u,_,y,l,$=!1){let j=y.get(f);if(!j)return null;let J=l==="strict"?j.internals.handleBounds?.[u]:[...j.internals.handleBounds?.source??[],...j.internals.handleBounds?.target??[]],F=(_?J?.find((A)=>A.id===_):J?.[0])??null;return F&&$?{...F,...t_(j,F,F.position,!0)}:F}function vK(f,u){if(f)return f;else if(u?.classList.contains("target"))return"target";else if(u?.classList.contains("source"))return"source";return null}function cB(f,u){let _=null;if(u)_=!0;else if(f&&!u)_=!1;return _}var bK=()=>!0;function pB(f,{connectionMode:u,connectionRadius:_,handleId:y,nodeId:l,edgeUpdaterType:$,isTarget:j,domNode:J,nodeLookup:F,lib:A,autoPanOnConnect:U,flowId:G,panBy:W,cancelConnection:K,onConnectStart:E,onConnect:H,onConnectEnd:O,isValidConnection:z=bK,onReconnectEnd:q,updateConnection:Z,getTransform:V,getFromHandle:L,autoPanSpeed:r,dragThreshold:N=1,handleDomNode:D}){let x=qF(f.target),c=0,v,{x:C,y:S}=_1(f),B=vK($,D),P=J?.getBoundingClientRect(),M=!1;if(!P||!B)return;let w=xK(l,B,y,F,u);if(!w)return;let Y=_1(f,P),R=!1,k=null,p=!1,n=null;function _f(){if(!U||!P)return;let[Zf,h]=XK(Y,P,r);W({x:Zf,y:h}),c=requestAnimationFrame(_f)}let s={...w,nodeId:l,type:B,position:w.position},ff=F.get(l),Gf={inProgress:!0,isValid:null,from:t_(ff,s,Uf.Left,!0),fromHandle:s,fromPosition:s.position,fromNode:ff,to:Y,toHandle:null,toPosition:lK[s.position],toNode:null,pointer:Y};function jf(){M=!0,Z(Gf),E?.(f,{nodeId:l,handleId:y,handleType:B})}if(N===0)jf();function Wf(Zf){if(!M){let{x:Af,y:Yf}=_1(Zf),xf=Af-C,of=Yf-S;if(!(xf*xf+of*of>N*N))return;jf()}if(!L()||!s){Of(Zf);return}let h=V();if(Y=_1(Zf,P),v=IB(j3(Y,h,!1,[1,1]),_,F,s),!R)_f(),R=!0;let i=hK(Zf,{handle:v,connectionMode:u,fromNodeId:l,fromHandleId:y,fromType:j?"target":"source",isValidConnection:z,doc:x,lib:A,flowId:G,nodeLookup:F});n=i.handleDomNode,k=i.connection,p=cB(!!v,i.isValid);let I=F.get(l),lf=I?t_(I,s,Uf.Left,!0):Gf.from,$f={...Gf,from:lf,isValid:p,to:i.toHandle&&p?W6({x:i.toHandle.x,y:i.toHandle.y},h):Y,toHandle:i.toHandle,toPosition:p&&i.toHandle?i.toHandle.position:lK[s.position],toNode:i.toHandle?F.get(i.toHandle.nodeId):null,pointer:Y};Z($f),Gf=$f}function Of(Zf){if("touches"in Zf&&Zf.touches.length>0)return;if(M){if((v||n)&&k&&p)H?.(k);let{inProgress:h,...i}=Gf,I={...i,toPosition:Gf.toHandle?Gf.toPosition:null};if(O?.(Zf,I),$)q?.(Zf,I)}K(),cancelAnimationFrame(c),R=!1,p=!1,k=null,n=null,x.removeEventListener("mousemove",Wf),x.removeEventListener("mouseup",Of),x.removeEventListener("touchmove",Wf),x.removeEventListener("touchend",Of)}x.addEventListener("mousemove",Wf),x.addEventListener("mouseup",Of),x.addEventListener("touchmove",Wf),x.addEventListener("touchend",Of)}function hK(f,{handle:u,connectionMode:_,fromNodeId:y,fromHandleId:l,fromType:$,doc:j,lib:J,flowId:F,isValidConnection:A=bK,nodeLookup:U}){let G=$==="target",W=u?j.querySelector(`.${J}-flow__handle[data-id="${F}-${u?.nodeId}-${u?.id}-${u?.type}"]`):null,{x:K,y:E}=_1(f),H=j.elementFromPoint(K,E),O=H?.classList.contains(`${J}-flow__handle`)?H:W,z={handleDomNode:O,isValid:!1,connection:null,toHandle:null};if(O){let q=vK(void 0,O),Z=O.getAttribute("data-nodeid"),V=O.getAttribute("data-handleid"),L=O.classList.contains("connectable"),r=O.classList.contains("connectableend");if(!Z||!q)return z;let N={source:G?Z:y,sourceHandle:G?V:l,target:G?y:Z,targetHandle:G?l:V};z.connection=N;let x=L&&r&&(_===g_.Strict?G&&q==="source"||!G&&q==="target":Z!==y||V!==l);z.isValid=x&&A(N),z.toHandle=xK(Z,q,V,U,_,!0)}return z}var M5={onPointerDown:pB,isValid:hK};function IK({domNode:f,panZoom:u,getTransform:_,getViewScale:y}){let l=R0(f);function $({translateExtent:J,width:F,height:A,zoomStep:U=1,pannable:G=!0,zoomable:W=!0,inversePan:K=!1}){let E=(Z)=>{if(Z.sourceEvent.type!=="wheel"||!u)return;let V=_(),L=Z.sourceEvent.ctrlKey&&J3()?10:1,r=-Z.sourceEvent.deltaY*(Z.sourceEvent.deltaMode===1?0.05:Z.sourceEvent.deltaMode?1:0.002)*U,N=V[2]*Math.pow(2,r*L);u.scaleTo(N)},H=[0,0],O=(Z)=>{if(Z.sourceEvent.type==="mousedown"||Z.sourceEvent.type==="touchstart")H=[Z.sourceEvent.clientX??Z.sourceEvent.touches[0].clientX,Z.sourceEvent.clientY??Z.sourceEvent.touches[0].clientY]},z=(Z)=>{let V=_();if(Z.sourceEvent.type!=="mousemove"&&Z.sourceEvent.type!=="touchmove"||!u)return;let L=[Z.sourceEvent.clientX??Z.sourceEvent.touches[0].clientX,Z.sourceEvent.clientY??Z.sourceEvent.touches[0].clientY],r=[L[0]-H[0],L[1]-H[1]];H=L;let N=y()*Math.max(V[2],Math.log(V[2]))*(K?-1:1),D={x:V[0]-r[0]*N,y:V[1]-r[1]*N},x=[[0,0],[F,A]];u.setViewportConstrained({x:D.x,y:D.y,zoom:V[2]},x,J)},q=A6().on("start",O).on("zoom",G?z:null).on("zoom.wheel",W?E:null);l.call(q,{})}function j(){l.on("zoom",null)}return{update:$,destroy:j,pointer:ju}}var P5=(f)=>({x:f.x,y:f.y,zoom:f.k}),fF=({x:f,y:u,zoom:_})=>hy.translate(f,u).scale(_),el=(f,u)=>f.target.closest(`.${u}`),cK=(f,u)=>u===2&&Array.isArray(f)&&f.includes(2),kB=(f)=>((f*=2)<=1?f*f*f:(f-=2)*f*f+2)/2,uF=(f,u=0,_=kB,y=()=>{})=>{let l=typeof u==="number"&&u>0;if(!l)y();return l?f.transition().duration(u).ease(_).on("end",y):f},pK=(f)=>{let u=f.ctrlKey&&J3()?10:1;return-f.deltaY*(f.deltaMode===1?0.05:f.deltaMode?1:0.002)*u};function mB({zoomPanValues:f,noWheelClassName:u,d3Selection:_,d3Zoom:y,panOnScrollMode:l,panOnScrollSpeed:$,zoomOnPinch:j,onPanZoomStart:J,onPanZoom:F,onPanZoomEnd:A}){return(U)=>{if(el(U,u)){if(U.ctrlKey)U.preventDefault();return!1}U.preventDefault(),U.stopImmediatePropagation();let G=_.property("__zoom").k||1;if(U.ctrlKey&&j){let O=ju(U),z=pK(U),q=G*Math.pow(2,z);y.scaleTo(_,q,O,U);return}let W=U.deltaMode===1?20:1,K=l===l_.Vertical?0:U.deltaX*W,E=l===l_.Horizontal?0:U.deltaY*W;if(!J3()&&U.shiftKey&&l!==l_.Vertical)K=U.deltaY*W,E=0;y.translateBy(_,-(K/G)*$,-(E/G)*$,{internal:!0});let H=P5(_.property("__zoom"));if(clearTimeout(f.panScrollTimeout),!f.isPanScrolling)f.isPanScrolling=!0,J?.(U,H);else F?.(U,H),f.panScrollTimeout=setTimeout(()=>{A?.(U,H),f.isPanScrolling=!1},150)}}function iB({noWheelClassName:f,preventScrolling:u,d3ZoomHandler:_}){return function(y,l){let $=y.type==="wheel",j=!u&&$&&!y.ctrlKey,J=el(y,f);if(y.ctrlKey&&$&&J)y.preventDefault();if(j||J)return null;y.preventDefault(),_.call(this,y,l)}}function gB({zoomPanValues:f,onDraggingChange:u,onPanZoomStart:_}){return(y)=>{if(y.sourceEvent?.internal)return;let l=P5(y.transform);if(f.mouseButton=y.sourceEvent?.button||0,f.isZoomingOrPanning=!0,f.prevViewport=l,y.sourceEvent?.type==="mousedown")u(!0);if(_)_?.(y.sourceEvent,l)}}function nB({zoomPanValues:f,panOnDrag:u,onPaneContextMenu:_,onTransformChange:y,onPanZoom:l}){return($)=>{if(f.usedRightMouseButton=!!(_&&cK(u,f.mouseButton??0)),!$.sourceEvent?.sync)y([$.transform.x,$.transform.y,$.transform.k]);if(l&&!$.sourceEvent?.internal)l?.($.sourceEvent,P5($.transform))}}function tB({zoomPanValues:f,panOnDrag:u,panOnScroll:_,onDraggingChange:y,onPanZoomEnd:l,onPaneContextMenu:$}){return(j)=>{if(j.sourceEvent?.internal)return;if(f.isZoomingOrPanning=!1,$&&cK(u,f.mouseButton??0)&&!f.usedRightMouseButton&&j.sourceEvent)$(j.sourceEvent);if(f.usedRightMouseButton=!1,y(!1),l){let J=P5(j.transform);f.prevViewport=J,clearTimeout(f.timerId),f.timerId=setTimeout(()=>{l?.(j.sourceEvent,J)},_?150:0)}}}function sB({zoomActivationKeyPressed:f,zoomOnScroll:u,zoomOnPinch:_,panOnDrag:y,panOnScroll:l,zoomOnDoubleClick:$,userSelectionActive:j,noWheelClassName:J,noPanClassName:F,lib:A,connectionInProgress:U}){return(G)=>{let W=f||u,K=_&&G.ctrlKey,E=G.type==="wheel";if(G.button===1&&G.type==="mousedown"&&(el(G,`${A}-flow__node`)||el(G,`${A}-flow__edge`)))return!0;if(!y&&!W&&!l&&!$&&!_)return!1;if(j)return!1;if(U&&!E)return!1;if(el(G,J)&&E)return!1;if(el(G,F)&&(!E||l&&E&&!f))return!1;if(!_&&G.ctrlKey&&E)return!1;if(!_&&G.type==="touchstart"&&G.touches?.length>1)return G.preventDefault(),!1;if(!W&&!l&&!K&&E)return!1;if(!y&&(G.type==="mousedown"||G.type==="touchstart"))return!1;if(Array.isArray(y)&&!y.includes(G.button)&&G.type==="mousedown")return!1;let H=Array.isArray(y)&&y.includes(G.button)||!G.button||G.button<=1;return(!G.ctrlKey||E)&&H}}function kK({domNode:f,minZoom:u,maxZoom:_,translateExtent:y,viewport:l,onPanZoom:$,onPanZoomStart:j,onPanZoomEnd:J,onDraggingChange:F}){let A={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},U=f.getBoundingClientRect(),G=A6().scaleExtent([u,_]).translateExtent(y),W=R0(f).call(G);q({x:l.x,y:l.y,zoom:f3(l.zoom,u,_)},[[0,0],[U.width,U.height]],y);let K=W.on("wheel.zoom"),E=W.on("dblclick.zoom");G.wheelDelta(pK);function H(v,C){if(W)return new Promise((S)=>{G?.interpolate(C?.interpolate==="linear"?S1:vy).transform(uF(W,C?.duration,C?.ease,()=>S(!0)),v)});return Promise.resolve(!1)}function O({noWheelClassName:v,noPanClassName:C,onPaneContextMenu:S,userSelectionActive:B,panOnScroll:P,panOnDrag:M,panOnScrollMode:w,panOnScrollSpeed:Y,preventScrolling:R,zoomOnPinch:k,zoomOnScroll:p,zoomOnDoubleClick:n,zoomActivationKeyPressed:_f,lib:s,onTransformChange:ff,connectionInProgress:Kf,paneClickDistance:Gf,selectionOnDrag:jf}){if(B&&!A.isZoomingOrPanning)z();let Wf=P&&!_f&&!B;G.clickDistance(jf?1/0:!u1(Gf)||Gf<0?0:Gf);let Of=Wf?mB({zoomPanValues:A,noWheelClassName:v,d3Selection:W,d3Zoom:G,panOnScrollMode:w,panOnScrollSpeed:Y,zoomOnPinch:k,onPanZoomStart:j,onPanZoom:$,onPanZoomEnd:J}):iB({noWheelClassName:v,preventScrolling:R,d3ZoomHandler:K});if(W.on("wheel.zoom",Of,{passive:!1}),!B){let h=gB({zoomPanValues:A,onDraggingChange:F,onPanZoomStart:j});G.on("start",h);let i=nB({zoomPanValues:A,panOnDrag:M,onPaneContextMenu:!!S,onPanZoom:$,onTransformChange:ff});G.on("zoom",i);let I=tB({zoomPanValues:A,panOnDrag:M,panOnScroll:P,onPaneContextMenu:S,onPanZoomEnd:J,onDraggingChange:F});G.on("end",I)}let Zf=sB({zoomActivationKeyPressed:_f,panOnDrag:M,zoomOnScroll:p,panOnScroll:P,zoomOnDoubleClick:n,zoomOnPinch:k,userSelectionActive:B,noPanClassName:C,noWheelClassName:v,lib:s,connectionInProgress:Kf});if(G.filter(Zf),n)W.on("dblclick.zoom",E);else W.on("dblclick.zoom",null)}function z(){G.on("zoom",null)}async function q(v,C,S){let B=fF(v),P=G?.constrain()(B,C,S);if(P)await H(P);return new Promise((M)=>M(P))}async function Z(v,C){let S=fF(v);return await H(S,C),new Promise((B)=>B(S))}function V(v){if(W){let C=fF(v),S=W.property("__zoom");if(S.k!==v.zoom||S.x!==v.x||S.y!==v.y)G?.transform(W,C,null,{sync:!0})}}function L(){let v=W?Q6(W.node()):{x:0,y:0,k:1};return{x:v.x,y:v.y,zoom:v.k}}function r(v,C){if(W)return new Promise((S)=>{G?.interpolate(C?.interpolate==="linear"?S1:vy).scaleTo(uF(W,C?.duration,C?.ease,()=>S(!0)),v)});return Promise.resolve(!1)}function N(v,C){if(W)return new Promise((S)=>{G?.interpolate(C?.interpolate==="linear"?S1:vy).scaleBy(uF(W,C?.duration,C?.ease,()=>S(!0)),v)});return Promise.resolve(!1)}function D(v){G?.scaleExtent(v)}function x(v){G?.translateExtent(v)}function c(v){let C=!u1(v)||v<0?0:v;G?.clickDistance(C)}return{update:O,destroy:z,setViewport:Z,setViewportConstrained:q,getViewport:L,scaleTo:r,scaleBy:N,setScaleExtent:D,setTranslateExtent:x,syncViewport:V,setClickDistance:c}}var s_;(function(f){f.Line="line",f.Handle="handle"})(s_||(s_={}));function oB({width:f,prevWidth:u,height:_,prevHeight:y,affectsX:l,affectsY:$}){let j=f-u,J=_-y,F=[j>0?1:j<0?-1:0,J>0?1:J<0?-1:0];if(j&&l)F[0]=F[0]*-1;if(J&&$)F[1]=F[1]*-1;return F}function KK(f){let u=f.includes("right")||f.includes("left"),_=f.includes("bottom")||f.includes("top"),y=f.includes("left"),l=f.includes("top");return{isHorizontal:u,isVertical:_,affectsX:y,affectsY:l}}function m_(f,u){return Math.max(0,u-f)}function i_(f,u){return Math.max(0,f-u)}function H5(f,u,_){return Math.max(0,u-f,f-_)}function ZK(f,u){return f?!u:u}function aB(f,u,_,y,l,$,j,J){let{affectsX:F,affectsY:A}=u,{isHorizontal:U,isVertical:G}=u,W=U&&G,{xSnapped:K,ySnapped:E}=_,{minWidth:H,maxWidth:O,minHeight:z,maxHeight:q}=y,{x:Z,y:V,width:L,height:r,aspectRatio:N}=f,D=Math.floor(U?K-f.pointerX:0),x=Math.floor(G?E-f.pointerY:0),c=L+(F?-D:D),v=r+(A?-x:x),C=-$[0]*L,S=-$[1]*r,B=H5(c,H,O),P=H5(v,z,q);if(j){let Y=0,R=0;if(F&&D<0)Y=m_(Z+D+C,j[0][0]);else if(!F&&D>0)Y=i_(Z+c+C,j[1][0]);if(A&&x<0)R=m_(V+x+S,j[0][1]);else if(!A&&x>0)R=i_(V+v+S,j[1][1]);B=Math.max(B,Y),P=Math.max(P,R)}if(J){let Y=0,R=0;if(F&&D>0)Y=i_(Z+D,J[0][0]);else if(!F&&D<0)Y=m_(Z+c,J[1][0]);if(A&&x>0)R=i_(V+x,J[0][1]);else if(!A&&x<0)R=m_(V+v,J[1][1]);B=Math.max(B,Y),P=Math.max(P,R)}if(l){if(U){let Y=H5(c/N,z,q)*N;if(B=Math.max(B,Y),j){let R=0;if(!F&&!A||F&&!A&&W)R=i_(V+S+c/N,j[1][1])*N;else R=m_(V+S+(F?D:-D)/N,j[0][1])*N;B=Math.max(B,R)}if(J){let R=0;if(!F&&!A||F&&!A&&W)R=m_(V+c/N,J[1][1])*N;else R=i_(V+(F?D:-D)/N,J[0][1])*N;B=Math.max(B,R)}}if(G){let Y=H5(v*N,H,O)/N;if(P=Math.max(P,Y),j){let R=0;if(!F&&!A||A&&!F&&W)R=i_(Z+v*N+C,j[1][0])/N;else R=m_(Z+(A?x:-x)*N+C,j[0][0])/N;P=Math.max(P,R)}if(J){let R=0;if(!F&&!A||A&&!F&&W)R=m_(Z+v*N,J[1][0])/N;else R=i_(Z+(A?x:-x)*N,J[0][0])/N;P=Math.max(P,R)}}}if(x=x+(x<0?P:-P),D=D+(D<0?B:-B),l)if(W)if(c>v*N)x=(ZK(F,A)?-D:D)/N;else D=(ZK(F,A)?-x:x)*N;else if(U)x=D/N,A=F;else D=x*N,F=A;let M=F?Z+D:Z,w=A?V+x:V;return{width:L+(F?-D:D),height:r+(A?-x:x),x:$[0]*D*(!F?1:-1)+M,y:$[1]*x*(!A?1:-1)+w}}var mK={width:0,height:0,x:0,y:0},dB={...mK,pointerX:0,pointerY:0,aspectRatio:1};function eB(f){return[[0,0],[f.measured.width,f.measured.height]]}function fD(f,u,_){let y=u.position.x+f.position.x,l=u.position.y+f.position.y,$=f.measured.width??0,j=f.measured.height??0,J=_[0]*$,F=_[1]*j;return[[y-J,l-F],[y+$-J,l+j-F]]}function iK({domNode:f,nodeId:u,getStoreItems:_,onChange:y,onEnd:l}){let $=R0(f),j={controlDirection:KK("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function J({controlPosition:A,boundaries:U,keepAspectRatio:G,resizeDirection:W,onResizeStart:K,onResize:E,onResizeEnd:H,shouldResize:O}){let z={...mK},q={...dB};j={boundaries:U,resizeDirection:W,keepAspectRatio:G,controlDirection:KK(A)};let Z=void 0,V=null,L=[],r=void 0,N=void 0,D=void 0,x=!1,c=g$().on("start",(v)=>{let{nodeLookup:C,transform:S,snapGrid:B,snapToGrid:P,nodeOrigin:M,paneDomNode:w}=_();if(Z=C.get(u),!Z)return;V=w?.getBoundingClientRect()??null;let{xSnapped:Y,ySnapped:R}=U6(v.sourceEvent,{transform:S,snapGrid:B,snapToGrid:P,containerBounds:V});if(z={width:Z.measured.width??0,height:Z.measured.height??0,x:Z.position.x??0,y:Z.position.y??0},q={...z,pointerX:Y,pointerY:R,aspectRatio:z.width/z.height},r=void 0,Z.parentId&&(Z.extent==="parent"||Z.expandParent))r=C.get(Z.parentId),N=r&&Z.extent==="parent"?eB(r):void 0;L=[],D=void 0;for(let[k,p]of C)if(p.parentId===u){if(L.push({id:k,position:{...p.position},extent:p.extent}),p.extent==="parent"||p.expandParent){let n=fD(p,Z,p.origin??M);if(D)D=[[Math.min(n[0][0],D[0][0]),Math.min(n[0][1],D[0][1])],[Math.max(n[1][0],D[1][0]),Math.max(n[1][1],D[1][1])]];else D=n}}K?.(v,{...z})}).on("drag",(v)=>{let{transform:C,snapGrid:S,snapToGrid:B,nodeOrigin:P}=_(),M=U6(v.sourceEvent,{transform:C,snapGrid:S,snapToGrid:B,containerBounds:V}),w=[];if(!Z)return;let{x:Y,y:R,width:k,height:p}=z,n={},_f=Z.origin??P,{width:s,height:ff,x:Kf,y:Gf}=aB(q,j.controlDirection,M,j.boundaries,j.keepAspectRatio,_f,N,D),jf=s!==k,Wf=ff!==p,Of=Kf!==Y&&jf,Zf=Gf!==R&&Wf;if(!Of&&!Zf&&!jf&&!Wf)return;if(Of||Zf||_f[0]===1||_f[1]===1){if(n.x=Of?Kf:z.x,n.y=Zf?Gf:z.y,z.x=n.x,z.y=n.y,L.length>0){let lf=Kf-Y,$f=Gf-R;for(let Af of L)Af.position={x:Af.position.x-lf+_f[0]*(s-k),y:Af.position.y-$f+_f[1]*(ff-p)},w.push(Af)}}if(jf||Wf)n.width=jf&&(!j.resizeDirection||j.resizeDirection==="horizontal")?s:z.width,n.height=Wf&&(!j.resizeDirection||j.resizeDirection==="vertical")?ff:z.height,z.width=n.width,z.height=n.height;if(r&&Z.expandParent){let lf=_f[0]*(n.width??0);if(n.x&&n.x{if(!x)return;H?.(v,{...z}),l?.({...z}),x=!1});$.call(c)}function F(){$.on(".drag",null)}return{update:J,destroy:F}}var yZ=Sf(c0(),1),lZ=Sf(eK(),1);var fZ=(f)=>{let u,_=new Set,y=(U,G)=>{let W=typeof U==="function"?U(u):U;if(!Object.is(W,u)){let K=u;u=(G!=null?G:typeof W!=="object"||W===null)?W:Object.assign({},u,W),_.forEach((E)=>E(u,K))}},l=()=>u,F={setState:y,getState:l,getInitialState:()=>A,subscribe:(U)=>{return _.add(U),()=>_.delete(U)},destroy:()=>{_.clear()}},A=u=f(y,l,F);return F},uZ=(f)=>f?fZ(f):fZ;var{useDebugValue:ED}=yZ.default,{useSyncExternalStoreWithSelector:HD}=lZ.default,VD=(f)=>f;function wF(f,u=VD,_){let y=HD(f.subscribe,f.getState,f.getServerState||f.getInitialState,u,_);return ED(y),y}var _Z=(f,u)=>{let _=uZ(f),y=(l,$=u)=>wF(_,l,$);return Object.assign(y,_),y},$Z=(f,u)=>f?_Z(f,u):_Z;function W0(f,u){if(Object.is(f,u))return!0;if(typeof f!=="object"||f===null||typeof u!=="object"||u===null)return!1;if(f instanceof Map&&u instanceof Map){if(f.size!==u.size)return!1;for(let[y,l]of f)if(!Object.is(l,u.get(y)))return!1;return!0}if(f instanceof Set&&u instanceof Set){if(f.size!==u.size)return!1;for(let y of f)if(!u.has(y))return!1;return!0}let _=Object.keys(f);if(_.length!==Object.keys(u).length)return!1;for(let y of _)if(!Object.prototype.hasOwnProperty.call(u,y)||!Object.is(f[y],u[y]))return!1;return!0}var OD=Sf(t7(),1),v5=a.createContext(null),XD=v5.Provider,TZ=Iu.error001();function kf(f,u){let _=a.useContext(v5);if(_===null)throw Error(TZ);return wF(_,f,u)}function z0(){let f=a.useContext(v5);if(f===null)throw Error(TZ);return a.useMemo(()=>({getState:f.getState,setState:f.setState,subscribe:f.subscribe}),[f])}var jZ={display:"none"},ND={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},rZ="react-flow__node-desc",MZ="react-flow__edge-desc",LD="react-flow__aria-live",YD=(f)=>f.ariaLiveMessage,BD=(f)=>f.ariaLabelConfig;function DD({rfId:f}){let u=kf(YD);return o.jsx("div",{id:`${LD}-${f}`,"aria-live":"assertive","aria-atomic":"true",style:ND,children:u})}function wD({rfId:f,disableKeyboardA11y:u}){let _=kf(BD);return o.jsxs(o.Fragment,{children:[o.jsx("div",{id:`${rZ}-${f}`,style:jZ,children:u?_["node.a11yDescription.default"]:_["node.a11yDescription.keyboardDisabled"]}),o.jsx("div",{id:`${MZ}-${f}`,style:jZ,children:_["edge.a11yDescription.default"]}),!u&&o.jsx(DD,{rfId:f})]})}var b5=a.forwardRef(({position:f="top-left",children:u,className:_,style:y,...l},$)=>{let j=`${f}`.split("-");return o.jsx("div",{className:B0(["react-flow__panel",_,...j]),style:y,ref:$,...l,children:u})});b5.displayName="Panel";function TD({proOptions:f,position:u="bottom-right"}){if(f?.hideAttribution)return null;return o.jsx(b5,{position:u,className:"react-flow__attribution","data-message":"Please only hide this attribution when you are subscribed to React Flow Pro: https://pro.reactflow.dev",children:o.jsx("a",{href:"https://reactflow.dev",target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}var rD=(f)=>{let u=[],_=[];for(let[,y]of f.nodeLookup)if(y.selected)u.push(y.internals.userNode);for(let[,y]of f.edgeLookup)if(y.selected)_.push(y);return{selectedNodes:u,selectedEdges:_}},C5=(f)=>f.id;function MD(f,u){return W0(f.selectedNodes.map(C5),u.selectedNodes.map(C5))&&W0(f.selectedEdges.map(C5),u.selectedEdges.map(C5))}function PD({onSelectionChange:f}){let u=z0(),{selectedNodes:_,selectedEdges:y}=kf(rD,MD);return a.useEffect(()=>{let l={nodes:_,edges:y};f?.(l),u.getState().onSelectionChangeHandlers.forEach(($)=>$(l))},[_,y,f]),null}var SD=(f)=>!!f.onSelectionChangeHandlers;function CD({onSelectionChange:f}){let u=kf(SD);if(f||u)return o.jsx(PD,{onSelectionChange:f});return null}var MF=typeof window<"u"?a.useLayoutEffect:a.useEffect,PZ=[0,0],RD={x:0,y:0,zoom:1},xD=["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"],JZ=[...xD,"rfId"],vD=(f)=>({setNodes:f.setNodes,setEdges:f.setEdges,setMinZoom:f.setMinZoom,setMaxZoom:f.setMaxZoom,setTranslateExtent:f.setTranslateExtent,setNodeExtent:f.setNodeExtent,reset:f.reset,setDefaultNodesAndEdges:f.setDefaultNodesAndEdges}),FZ={translateExtent:_3,nodeOrigin:PZ,minZoom:0.5,maxZoom:2,elementsSelectable:!0,noPanClassName:"nopan",rfId:"1"};function bD(f){let{setNodes:u,setEdges:_,setMinZoom:y,setMaxZoom:l,setTranslateExtent:$,setNodeExtent:j,reset:J,setDefaultNodesAndEdges:F}=kf(vD,W0),A=z0();MF(()=>{return F(f.defaultNodes,f.defaultEdges),()=>{U.current=FZ,J()}},[]);let U=a.useRef(FZ);return MF(()=>{for(let G of JZ){let W=f[G],K=U.current[G];if(W===K)continue;if(typeof f[G]>"u")continue;if(G==="nodes")u(W);else if(G==="edges")_(W);else if(G==="minZoom")y(W);else if(G==="maxZoom")l(W);else if(G==="translateExtent")$(W);else if(G==="nodeExtent")j(W);else if(G==="ariaLabelConfig")A.setState({ariaLabelConfig:LK(W)});else if(G==="fitView")A.setState({fitViewQueued:W});else if(G==="fitViewOptions")A.setState({fitViewOptions:W});else A.setState({[G]:W})}U.current=f},JZ.map((G)=>f[G])),null}function QZ(){if(typeof window>"u"||!window.matchMedia)return null;return window.matchMedia("(prefers-color-scheme: dark)")}function hD(f){let[u,_]=a.useState(f==="system"?null:f);return a.useEffect(()=>{if(f!=="system"){_(f);return}let y=QZ(),l=()=>_(y?.matches?"dark":"light");return l(),y?.addEventListener("change",l),()=>{y?.removeEventListener("change",l)}},[f]),u!==null?u:QZ()?.matches?"dark":"light"}var AZ=typeof document<"u"?document:null;function Z6(f=null,u={target:AZ,actInsideInputWithModifier:!0}){let[_,y]=a.useState(!1),l=a.useRef(!1),$=a.useRef(new Set([])),[j,J]=a.useMemo(()=>{if(f!==null){let A=(Array.isArray(f)?f:[f]).filter((G)=>typeof G==="string").map((G)=>G.replace("+",` `).replace(` `,` +`).split(` -`)),U=A.reduce((z,W)=>z.concat(...W),[]);return[A,U]}return[[],[]]},[f]);return d.useEffect(()=>{let F=u?.target??JZ,A=u?.actInsideInputWithModifier??!0;if(f!==null){let U=(K)=>{if($.current=K.ctrlKey||K.metaKey||K.shiftKey||K.altKey,(!$.current||$.current&&!A)&&ZF(K))return!1;let E=QZ(K.code,J);if(l.current.add(K[E]),FZ(j,l.current,!1)){let O=K.composedPath?.()?.[0]||K.target,G=O?.nodeName==="BUTTON"||O?.nodeName==="A";if(u.preventDefault!==!1&&($.current||!G))K.preventDefault();y(!0)}},z=(K)=>{let q=QZ(K.code,J);if(FZ(j,l.current,!0))y(!1),l.current.clear();else l.current.delete(K[q]);if(K.key==="Meta")l.current.clear();$.current=!1},W=()=>{l.current.clear(),y(!1)};return F?.addEventListener("keydown",U),F?.addEventListener("keyup",z),window.addEventListener("blur",W),window.addEventListener("contextmenu",W),()=>{F?.removeEventListener("keydown",U),F?.removeEventListener("keyup",z),window.removeEventListener("blur",W),window.removeEventListener("contextmenu",W)}}},[f,y]),_}function FZ(f,u,_){return f.filter((y)=>_||y.length===u.size).some((y)=>y.every(($)=>u.has($)))}function QZ(f,u){return u.includes(f)?"code":"key"}var bw=()=>{let f=W0();return d.useMemo(()=>{return{zoomIn:(u)=>{let{panZoom:_}=f.getState();return _?_.scaleBy(1.2,u):Promise.resolve(!1)},zoomOut:(u)=>{let{panZoom:_}=f.getState();return _?_.scaleBy(0.8333333333333334,u):Promise.resolve(!1)},zoomTo:(u,_)=>{let{panZoom:y}=f.getState();return y?y.scaleTo(u,_):Promise.resolve(!1)},getZoom:()=>f.getState().transform[2],setViewport:async(u,_)=>{let{transform:[y,$,l],panZoom:j}=f.getState();if(!j)return Promise.resolve(!1);return await j.setViewport({x:u.x??y,y:u.y??$,zoom:u.zoom??l},_),Promise.resolve(!0)},getViewport:()=>{let[u,_,y]=f.getState().transform;return{x:u,y:_,zoom:y}},setCenter:async(u,_,y)=>{return f.getState().setCenter(u,_,y)},fitBounds:async(u,_)=>{let{width:y,height:$,minZoom:l,maxZoom:j,panZoom:J}=f.getState(),F=ql(u,y,$,l,j,_?.padding??0.1);if(!J)return Promise.resolve(!1);return await J.setViewport(F,{duration:_?.duration,ease:_?.ease,interpolate:_?.interpolate}),Promise.resolve(!0)},screenToFlowPosition:(u,_={})=>{let{transform:y,snapGrid:$,snapToGrid:l,domNode:j}=f.getState();if(!j)return u;let{x:J,y:F}=j.getBoundingClientRect(),A={x:u.x-J,y:u.y-F},U=_.snapGrid??$,z=_.snapToGrid??l;return j$(A,y,z,U)},flowToScreenPosition:(u)=>{let{transform:_,domNode:y}=f.getState();if(!y)return u;let{x:$,y:l}=y.getBoundingClientRect(),j=Kl(u,_);return{x:j.x+$,y:j.y+l}}}},[])};function MZ(f,u){let _=[],y=new Map,$=[];for(let l of f)if(l.type==="add"){$.push(l);continue}else if(l.type==="remove"||l.type==="replace")y.set(l.id,[l]);else{let j=y.get(l.id);if(j)j.push(l);else y.set(l.id,[l])}for(let l of u){let j=y.get(l.id);if(!j){_.push(l);continue}if(j[0].type==="remove")continue;if(j[0].type==="replace"){_.push({...j[0].item});continue}let J={...l};for(let F of j)hw(F,J);_.push(J)}if($.length)$.forEach((l)=>{if(l.index!==void 0)_.splice(l.index,0,{...l.item});else _.push({...l.item})});return _}function hw(f,u){switch(f.type){case"select":{u.selected=f.selected;break}case"position":{if(typeof f.position<"u")u.position=f.position;if(typeof f.dragging<"u")u.dragging=f.dragging;break}case"dimensions":{if(typeof f.dimensions<"u"){if(u.measured={...f.dimensions},f.setAttributes){if(f.setAttributes===!0||f.setAttributes==="width")u.width=f.dimensions.width;if(f.setAttributes===!0||f.setAttributes==="height")u.height=f.dimensions.height}}if(typeof f.resizing==="boolean")u.resizing=f.resizing;break}}}function Iw(f,u){return MZ(f,u)}function cw(f,u){return MZ(f,u)}function ty(f,u){return{id:f,type:"select",selected:u}}function Q$(f,u=new Set,_=!1){let y=[];for(let[$,l]of f){let j=u.has($);if(!(l.selected===void 0&&!j)&&l.selected!==j){if(_)l.selected=j;y.push(ty(l.id,j))}}return y}function AZ({items:f=[],lookup:u}){let _=[],y=new Map(f.map(($)=>[$.id,$]));for(let[$,l]of f.entries()){let j=u.get(l.id),J=j?.internals?.userNode??j;if(J!==void 0&&J!==l)_.push({id:l.id,item:l,type:"replace"});if(J===void 0)_.push({item:l,type:"add",index:$})}for(let[$]of u)if(y.get($)===void 0)_.push({id:$,type:"remove"});return _}function UZ(f){return{id:f.id,type:"remove"}}var WZ=(f)=>GK(f),pw=(f)=>lF(f);function SZ(f){return d.forwardRef(f)}function zZ(f){let[u,_]=d.useState(BigInt(0)),[y]=d.useState(()=>mw(()=>_(($)=>$+BigInt(1))));return TF(()=>{let $=y.get();if($.length)f($),y.reset()},[u]),y}function mw(f){let u=[];return{get:()=>u,reset:()=>{u=[]},push:(_)=>{u.push(_),f()}}}var rZ=d.createContext(null);function kw({children:f}){let u=W0(),_=d.useCallback((J)=>{let{nodes:F=[],setNodes:A,hasDefaultNodes:U,onNodesChange:z,nodeLookup:W,fitViewQueued:K,onNodesChangeMiddlewareMap:q}=u.getState(),E=F;for(let G of J)E=typeof G==="function"?G(E):G;let O=AZ({items:E,lookup:W});for(let G of q.values())O=G(O);if(U)A(E);if(O.length>0)z?.(O);else if(K)window.requestAnimationFrame(()=>{let{fitViewQueued:G,nodes:H,setNodes:Z}=u.getState();if(G)Z(H)})},[]),y=zZ(_),$=d.useCallback((J)=>{let{edges:F=[],setEdges:A,hasDefaultEdges:U,onEdgesChange:z,edgeLookup:W}=u.getState(),K=F;for(let q of J)K=typeof q==="function"?q(K):q;if(U)A(K);else if(z)z(AZ({items:K,lookup:W}))},[]),l=zZ($),j=d.useMemo(()=>({nodeQueue:y,edgeQueue:l}),[]);return o.jsx(rZ.Provider,{value:j,children:f})}function iw(){let f=d.useContext(rZ);if(!f)throw Error("useBatchContext must be used within a BatchProvider");return f}var gw=(f)=>!!f.panZoom;function SF(){let f=bw(),u=W0(),_=iw(),y=mf(gw),$=d.useMemo(()=>{let l=(z)=>u.getState().nodeLookup.get(z),j=(z)=>{_.nodeQueue.push(z)},J=(z)=>{_.edgeQueue.push(z)},F=(z)=>{let{nodeLookup:W,nodeOrigin:K}=u.getState(),q=WZ(z)?z:W.get(z.id),E=q.parentId?zF(q.position,q.measured,q.parentId,W,K):q.position,O={...q,position:E,width:q.measured?.width??q.width,height:q.measured?.height??q.height};return ny(O)},A=(z,W,K={replace:!1})=>{j((q)=>q.map((E)=>{if(E.id===z){let O=typeof W==="function"?W(E):W;return K.replace&&WZ(O)?O:{...E,...O}}return E}))},U=(z,W,K={replace:!1})=>{J((q)=>q.map((E)=>{if(E.id===z){let O=typeof W==="function"?W(E):W;return K.replace&&pw(O)?O:{...E,...O}}return E}))};return{getNodes:()=>u.getState().nodes.map((z)=>({...z})),getNode:(z)=>l(z)?.internals.userNode,getInternalNode:l,getEdges:()=>{let{edges:z=[]}=u.getState();return z.map((W)=>({...W}))},getEdge:(z)=>u.getState().edgeLookup.get(z),setNodes:j,setEdges:J,addNodes:(z)=>{let W=Array.isArray(z)?z:[z];_.nodeQueue.push((K)=>[...K,...W])},addEdges:(z)=>{let W=Array.isArray(z)?z:[z];_.edgeQueue.push((K)=>[...K,...W])},toObject:()=>{let{nodes:z=[],edges:W=[],transform:K}=u.getState(),[q,E,O]=K;return{nodes:z.map((G)=>({...G})),edges:W.map((G)=>({...G})),viewport:{x:q,y:E,zoom:O}}},deleteElements:async({nodes:z=[],edges:W=[]})=>{let{nodes:K,edges:q,onNodesDelete:E,onEdgesDelete:O,triggerNodeChanges:G,triggerEdgeChanges:H,onDelete:Z,onBeforeDelete:V}=u.getState(),{nodes:L,edges:M}=await qK({nodesToRemove:z,edgesToRemove:W,nodes:K,edges:q,onBeforeDelete:V}),N=M.length>0,D=L.length>0;if(N){let x=M.map(UZ);O?.(M),H(x)}if(D){let x=L.map(UZ);E?.(L),G(x)}if(D||N)Z?.({nodes:L,edges:M});return{deletedNodes:L,deletedEdges:M}},getIntersectingNodes:(z,W=!0,K)=>{let q=AF(z),E=q?z:F(z),O=K!==void 0;if(!E)return[];return(K||u.getState().nodes).filter((G)=>{let H=u.getState().nodeLookup.get(G.id);if(H&&!q&&(G.id===z.id||!H.internals.positionAbsolute))return!1;let Z=ny(O?G:H),V=$$(Z,E);return W&&V>0||V>=Z.width*Z.height||V>=E.width*E.height})},isNodeIntersecting:(z,W,K=!0)=>{let E=AF(z)?z:F(z);if(!E)return!1;let O=$$(E,W);return K&&O>0||O>=W.width*W.height||O>=E.width*E.height},updateNode:A,updateNodeData:(z,W,K={replace:!1})=>{A(z,(q)=>{let E=typeof W==="function"?W(q):W;return K.replace?{...q,data:E}:{...q,data:{...q.data,...E}}},K)},updateEdge:U,updateEdgeData:(z,W,K={replace:!1})=>{U(z,(q)=>{let E=typeof W==="function"?W(q):W;return K.replace?{...q,data:E}:{...q,data:{...q.data,...E}}},K)},getNodesBounds:(z)=>{let{nodeLookup:W,nodeOrigin:K}=u.getState();return JF(z,{nodeLookup:W,nodeOrigin:K})},getHandleConnections:({type:z,id:W,nodeId:K})=>Array.from(u.getState().connectionLookup.get(`${K}-${z}${W?`-${W}`:""}`)?.values()??[]),getNodeConnections:({type:z,handleId:W,nodeId:K})=>Array.from(u.getState().connectionLookup.get(`${K}${z?W?`-${z}-${W}`:`-${z}`:""}`)?.values()??[]),fitView:async(z)=>{let W=u.getState().fitViewResolver??VK();return u.setState({fitViewQueued:!0,fitViewOptions:z,fitViewResolver:W}),_.nodeQueue.push((K)=>[...K]),W.promise}}},[]);return d.useMemo(()=>{return{...$,...f,viewportInitialized:y}},[y])}var GZ=(f)=>f.selected,nw=typeof window<"u"?window:void 0;function tw({deleteKeyCode:f,multiSelectionKeyCode:u}){let _=W0(),{deleteElements:y}=SF(),$=El(f,{actInsideInputWithModifier:!1}),l=El(u,{target:nw});d.useEffect(()=>{if($){let{edges:j,nodes:J}=_.getState();y({nodes:J.filter(GZ),edges:j.filter(GZ)}),_.setState({nodesSelectionActive:!1})}},[$]),d.useEffect(()=>{_.setState({multiSelectionActive:l})},[l])}function sw(f){let u=W0();d.useEffect(()=>{let _=()=>{if(!f.current||!(f.current.checkVisibility?.()??!0))return!1;let y=B5(f.current);if(y.height===0||y.width===0)u.getState().onError?.("004",hu.error004());u.setState({width:y.width||500,height:y.height||500})};if(f.current){_(),window.addEventListener("resize",_);let y=new ResizeObserver(()=>_());return y.observe(f.current),()=>{if(window.removeEventListener("resize",_),y&&f.current)y.unobserve(f.current)}}},[])}var c5={position:"absolute",width:"100%",height:"100%",top:0,left:0},ow=(f)=>({userSelectionActive:f.userSelectionActive,lib:f.lib,connectionInProgress:f.connection.inProgress});function aw({onPaneContextMenu:f,zoomOnScroll:u=!0,zoomOnPinch:_=!0,panOnScroll:y=!1,panOnScrollSpeed:$=0.5,panOnScrollMode:l=Q_.Free,zoomOnDoubleClick:j=!0,panOnDrag:J=!0,defaultViewport:F,translateExtent:A,minZoom:U,maxZoom:z,zoomActivationKeyCode:W,preventScrolling:K=!0,children:q,noWheelClassName:E,noPanClassName:O,onViewportChange:G,isControlledViewport:H,paneClickDistance:Z,selectionOnDrag:V}){let L=W0(),M=d.useRef(null),{userSelectionActive:N,lib:D,connectionInProgress:x}=mf(ow,A0),c=El(W),v=d.useRef();sw(M);let C=d.useCallback((P)=>{if(G?.({x:P[0],y:P[1],zoom:P[2]}),!H)L.setState({transform:P})},[G,H]);return d.useEffect(()=>{if(M.current){v.current=IK({domNode:M.current,minZoom:U,maxZoom:z,translateExtent:A,viewport:F,onDraggingChange:(S)=>L.setState((T)=>T.paneDragging===S?T:{paneDragging:S}),onPanZoomStart:(S,T)=>{let{onViewportChangeStart:Y,onMoveStart:R}=L.getState();R?.(S,T),Y?.(T)},onPanZoom:(S,T)=>{let{onViewportChange:Y,onMove:R}=L.getState();R?.(S,T),Y?.(T)},onPanZoomEnd:(S,T)=>{let{onViewportChangeEnd:Y,onMoveEnd:R}=L.getState();R?.(S,T),Y?.(T)}});let{x:P,y:w,zoom:r}=v.current.getViewport();return L.setState({panZoom:v.current,transform:[P,w,r],domNode:M.current.closest(".react-flow")}),()=>{v.current?.destroy()}}},[]),d.useEffect(()=>{v.current?.update({onPaneContextMenu:f,zoomOnScroll:u,zoomOnPinch:_,panOnScroll:y,panOnScrollSpeed:$,panOnScrollMode:l,zoomOnDoubleClick:j,panOnDrag:J,zoomActivationKeyPressed:c,preventScrolling:K,noPanClassName:O,userSelectionActive:N,noWheelClassName:E,lib:D,onTransformChange:C,connectionInProgress:x,selectionOnDrag:V,paneClickDistance:Z})},[f,u,_,y,$,l,j,J,c,K,O,N,E,D,C,x,V,Z]),o.jsx("div",{className:"react-flow__renderer",ref:M,style:c5,children:q})}var dw=(f)=>({userSelectionActive:f.userSelectionActive,userSelectionRect:f.userSelectionRect});function ew(){let{userSelectionActive:f,userSelectionRect:u}=mf(dw,A0);if(!(f&&u))return null;return o.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:u.width,height:u.height,transform:`translate(${u.x}px, ${u.y}px)`}})}var wF=(f,u)=>{return(_)=>{if(_.target!==u.current)return;f?.(_)}},fD=(f)=>({userSelectionActive:f.userSelectionActive,elementsSelectable:f.elementsSelectable,connectionInProgress:f.connection.inProgress,dragging:f.paneDragging});function uD({isSelecting:f,selectionKeyPressed:u,selectionMode:_=iy.Full,panOnDrag:y,paneClickDistance:$,selectionOnDrag:l,onSelectionStart:j,onSelectionEnd:J,onPaneClick:F,onPaneContextMenu:A,onPaneScroll:U,onPaneMouseEnter:z,onPaneMouseMove:W,onPaneMouseLeave:K,children:q}){let E=W0(),{userSelectionActive:O,elementsSelectable:G,dragging:H,connectionInProgress:Z}=mf(fD,A0),V=G&&(f||O),L=d.useRef(null),M=d.useRef(),N=d.useRef(new Set),D=d.useRef(new Set),x=d.useRef(!1),c=(Y)=>{if(x.current||Z){x.current=!1;return}F?.(Y),E.getState().resetSelectedElements(),E.setState({nodesSelectionActive:!1})},v=(Y)=>{if(Array.isArray(y)&&y?.includes(2)){Y.preventDefault();return}A?.(Y)},C=U?(Y)=>U(Y):void 0,P=(Y)=>{if(x.current)Y.stopPropagation(),x.current=!1},w=(Y)=>{let{domNode:R}=E.getState();if(M.current=R?.getBoundingClientRect(),!M.current)return;let m=Y.target===L.current;if(!m&&!!Y.target.closest(".nokey")||!f||!(l&&m||u)||Y.button!==0||!Y.isPrimary)return;Y.target?.setPointerCapture?.(Y.pointerId),x.current=!1;let{x:_f,y:t}=_1(Y.nativeEvent,M.current);if(E.setState({userSelectionRect:{width:0,height:0,startX:_f,startY:t,x:_f,y:t}}),!m)Y.stopPropagation(),Y.preventDefault()},r=(Y)=>{let{userSelectionRect:R,transform:m,nodeLookup:p,edgeLookup:n,connectionLookup:_f,triggerNodeChanges:t,triggerEdgeChanges:ff,defaultEdgeOptions:Gf,resetSelectedElements:zf}=E.getState();if(!M.current||!R)return;let{x:jf,y:Wf}=_1(Y.nativeEvent,M.current),{startX:Vf,startY:Zf}=R;if(!x.current){let lf=u?0:$;if(Math.hypot(jf-Vf,Wf-Zf)<=lf)return;zf(),j?.(Y)}x.current=!0;let h={startX:Vf,startY:Zf,x:jflf.id)),D.current=new Set;let $f=Gf?.selectable??!0;for(let lf of N.current){let Af=_f.get(lf);if(!Af)continue;for(let{edgeId:Yf}of Af.values()){let xf=n.get(Yf);if(xf&&(xf.selectable??$f))D.current.add(Yf)}}if(!GF(g,N.current)){let lf=Q$(p,N.current,!0);t(lf)}if(!GF(I,D.current)){let lf=Q$(n,D.current);ff(lf)}E.setState({userSelectionRect:h,userSelectionActive:!0,nodesSelectionActive:!1})},S=(Y)=>{if(Y.button!==0)return;if(Y.target?.releasePointerCapture?.(Y.pointerId),!O&&Y.target===L.current&&E.getState().userSelectionRect)c?.(Y);if(E.setState({userSelectionActive:!1,userSelectionRect:null}),x.current)J?.(Y),E.setState({nodesSelectionActive:N.current.size>0})},T=y===!0||Array.isArray(y)&&y.includes(0);return o.jsxs("div",{className:Y0(["react-flow__pane",{draggable:T,dragging:H,selection:f}]),onClick:V?void 0:wF(c,L),onContextMenu:wF(v,L),onWheel:wF(C,L),onPointerEnter:V?void 0:z,onPointerMove:V?r:W,onPointerUp:V?S:void 0,onPointerDownCapture:V?w:void 0,onClickCapture:V?P:void 0,onPointerLeave:K,ref:L,style:c5,children:[q,o.jsx(ew,{})]})}function MF({id:f,store:u,unselect:_=!1,nodeRef:y}){let{addSelectedNodes:$,unselectNodesAndEdges:l,multiSelectionActive:j,nodeLookup:J,onError:F}=u.getState(),A=J.get(f);if(!A){F?.("012",hu.error012(f));return}if(u.setState({nodesSelectionActive:!1}),!A.selected)$([f]);else if(_||A.selected&&j)l({nodes:[A],edges:[]}),requestAnimationFrame(()=>y?.current?.blur())}function PZ({nodeRef:f,disabled:u=!1,noDragClassName:_,handleSelector:y,nodeId:$,isSelectable:l,nodeClickDistance:j}){let J=W0(),[F,A]=d.useState(!1),U=d.useRef();return d.useEffect(()=>{U.current=rK({getStoreItems:()=>J.getState(),onNodeMouseDown:(z)=>{MF({id:z,store:J,nodeRef:f})},onDragStart:()=>{A(!0)},onDragStop:()=>{A(!1)}})},[]),d.useEffect(()=>{if(u||!f.current||!U.current)return;return U.current.update({noDragClassName:_,handleSelector:y,domNode:f.current,isSelectable:l,nodeId:$,nodeClickDistance:j}),()=>{U.current?.destroy()}},[_,y,u,l,f,$,j]),F}var _D=(f)=>(u)=>u.selected&&(u.draggable||f&&typeof u.draggable>"u");function CZ(){let f=W0();return d.useCallback((_)=>{let{nodeExtent:y,snapToGrid:$,snapGrid:l,nodesDraggable:j,onError:J,updateNodePositions:F,nodeLookup:A,nodeOrigin:U}=f.getState(),z=new Map,W=_D(j),K=$?l[0]:5,q=$?l[1]:5,E=_.direction.x*K*_.factor,O=_.direction.y*q*_.factor;for(let[,G]of A){if(!W(G))continue;let H={x:G.internals.positionAbsolute.x+E,y:G.internals.positionAbsolute.y+O};if($)H=l$(H,l);let{position:Z,positionAbsolute:V}=FF({nodeId:G.id,nextPosition:H,nodeLookup:A,nodeExtent:y,nodeOrigin:U,onError:J});G.position=Z,G.internals.positionAbsolute=V,z.set(G.id,G)}F(z)},[])}var rF=d.createContext(null),yD=rF.Provider;rF.Consumer;var RZ=()=>{return d.useContext(rF)},$D=(f)=>({connectOnClick:f.connectOnClick,noPanClassName:f.noPanClassName,rfId:f.rfId}),lD=(f,u,_)=>(y)=>{let{connectionClickStartHandle:$,connectionMode:l,connection:j}=y,{fromHandle:J,toHandle:F,isValid:A}=j,U=F?.nodeId===f&&F?.id===u&&F?.type===_;return{connectingFrom:J?.nodeId===f&&J?.id===u&&J?.type===_,connectingTo:U,clickConnecting:$?.nodeId===f&&$?.id===u&&$?.type===_,isPossibleEndHandle:l===g_.Strict?J?.type!==_:f!==J?.nodeId||u!==J?.id,connectionInProcess:!!J,clickConnectionInProcess:!!$,valid:U&&A}};function jD({type:f="source",position:u=Uf.Top,isValidConnection:_,isConnectable:y=!0,isConnectableStart:$=!0,isConnectableEnd:l=!0,id:j,onConnect:J,children:F,className:A,onMouseDown:U,onTouchStart:z,...W},K){let q=j||null,E=f==="target",O=W0(),G=RZ(),{connectOnClick:H,noPanClassName:Z,rfId:V}=mf($D,A0),{connectingFrom:L,connectingTo:M,clickConnecting:N,isPossibleEndHandle:D,connectionInProcess:x,clickConnectionInProcess:c,valid:v}=mf(lD(G,q,f),A0);if(!G)O.getState().onError?.("010",hu.error010());let C=(r)=>{let{defaultEdgeOptions:S,onConnect:T,hasDefaultEdges:Y}=O.getState(),R={...S,...r};if(Y){let{edges:m,setEdges:p}=O.getState();p(EF(R,m))}T?.(R),J?.(R)},P=(r)=>{if(!G)return;let S=qF(r.nativeEvent);if($&&(S&&r.button===0||!S)){let T=O.getState();P5.onPointerDown(r.nativeEvent,{handleDomNode:r.currentTarget,autoPanOnConnect:T.autoPanOnConnect,connectionMode:T.connectionMode,connectionRadius:T.connectionRadius,domNode:T.domNode,nodeLookup:T.nodeLookup,lib:T.lib,isTarget:E,handleId:q,nodeId:G,flowId:T.rfId,panBy:T.panBy,cancelConnection:T.cancelConnection,onConnectStart:T.onConnectStart,onConnectEnd:(...Y)=>O.getState().onConnectEnd?.(...Y),updateConnection:T.updateConnection,onConnect:C,isValidConnection:_||((...Y)=>O.getState().isValidConnection?.(...Y)??!0),getTransform:()=>O.getState().transform,getFromHandle:()=>O.getState().connection.fromHandle,autoPanSpeed:T.autoPanSpeed,dragThreshold:T.connectionDragThreshold})}if(S)U?.(r);else z?.(r)},w=(r)=>{let{onClickConnectStart:S,onClickConnectEnd:T,connectionClickStartHandle:Y,connectionMode:R,isValidConnection:m,lib:p,rfId:n,nodeLookup:_f,connection:t}=O.getState();if(!G||!Y&&!$)return;if(!Y){S?.(r.nativeEvent,{nodeId:G,handleId:q,handleType:f}),O.setState({connectionClickStartHandle:{nodeId:G,type:f,id:q}});return}let ff=KF(r.target),Gf=_||m,{connection:zf,isValid:jf}=P5.isValid(r.nativeEvent,{handle:{nodeId:G,id:q,type:f},connectionMode:R,fromNodeId:Y.nodeId,fromHandleId:Y.id||null,fromType:Y.type,isValidConnection:Gf,flowId:n,doc:ff,lib:p,nodeLookup:_f});if(jf&&zf)C(zf);let Wf=structuredClone(t);delete Wf.inProgress,Wf.toPosition=Wf.toHandle?Wf.toHandle.position:null,T?.(r,Wf),O.setState({connectionClickStartHandle:null})};return o.jsx("div",{"data-handleid":q,"data-nodeid":G,"data-handlepos":u,"data-id":`${V}-${G}-${q}-${f}`,className:Y0(["react-flow__handle",`react-flow__handle-${u}`,"nodrag",Z,A,{source:!E,target:E,connectable:y,connectablestart:$,connectableend:l,clickconnecting:N,connectingfrom:L,connectingto:M,valid:v,connectionindicator:y&&(!x||D)&&(x||c?l:$)}]),onMouseDown:P,onTouchStart:P,onClick:H?w:void 0,ref:K,...W,children:F})}var sy=d.memo(SZ(jD));function JD({data:f,isConnectable:u,sourcePosition:_=Uf.Bottom}){return o.jsxs(o.Fragment,{children:[f?.label,o.jsx(sy,{type:"source",position:_,isConnectable:u})]})}function FD({data:f,isConnectable:u,targetPosition:_=Uf.Top,sourcePosition:y=Uf.Bottom}){return o.jsxs(o.Fragment,{children:[o.jsx(sy,{type:"target",position:_,isConnectable:u}),f?.label,o.jsx(sy,{type:"source",position:y,isConnectable:u})]})}function QD(){return null}function AD({data:f,isConnectable:u,targetPosition:_=Uf.Top}){return o.jsxs(o.Fragment,{children:[o.jsx(sy,{type:"target",position:_,isConnectable:u}),f?.label]})}var b5={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},KZ={input:JD,default:FD,output:AD,group:QD};function UD(f){if(f.internals.handleBounds===void 0)return{width:f.width??f.initialWidth??f.style?.width,height:f.height??f.initialHeight??f.style?.height};return{width:f.width??f.style?.width,height:f.height??f.style?.height}}var WD=(f)=>{let{width:u,height:_,x:y,y:$}=y$(f.nodeLookup,{filter:(l)=>!!l.selected});return{width:u1(u)?u:null,height:u1(_)?_:null,userSelectionActive:f.userSelectionActive,transformString:`translate(${f.transform[0]}px,${f.transform[1]}px) scale(${f.transform[2]}) translate(${y}px,${$}px)`}};function zD({onSelectionContextMenu:f,noPanClassName:u,disableKeyboardA11y:_}){let y=W0(),{width:$,height:l,transformString:j,userSelectionActive:J}=mf(WD,A0),F=CZ(),A=d.useRef(null);d.useEffect(()=>{if(!_)A.current?.focus({preventScroll:!0})},[_]);let U=!J&&$!==null&&l!==null;if(PZ({nodeRef:A,disabled:!U}),!U)return null;let z=f?(K)=>{let q=y.getState().nodes.filter((E)=>E.selected);f(K,q)}:void 0,W=(K)=>{if(Object.prototype.hasOwnProperty.call(b5,K.key))K.preventDefault(),F({direction:b5[K.key],factor:K.shiftKey?4:1})};return o.jsx("div",{className:Y0(["react-flow__nodesselection","react-flow__container",u]),style:{transform:j},children:o.jsx("div",{ref:A,className:"react-flow__nodesselection-rect",onContextMenu:z,tabIndex:_?void 0:-1,onKeyDown:_?void 0:W,style:{width:$,height:l}})})}var ZZ=typeof window<"u"?window:void 0,GD=(f)=>{return{nodesSelectionActive:f.nodesSelectionActive,userSelectionActive:f.userSelectionActive}};function xZ({children:f,onPaneClick:u,onPaneMouseEnter:_,onPaneMouseMove:y,onPaneMouseLeave:$,onPaneContextMenu:l,onPaneScroll:j,paneClickDistance:J,deleteKeyCode:F,selectionKeyCode:A,selectionOnDrag:U,selectionMode:z,onSelectionStart:W,onSelectionEnd:K,multiSelectionKeyCode:q,panActivationKeyCode:E,zoomActivationKeyCode:O,elementsSelectable:G,zoomOnScroll:H,zoomOnPinch:Z,panOnScroll:V,panOnScrollSpeed:L,panOnScrollMode:M,zoomOnDoubleClick:N,panOnDrag:D,defaultViewport:x,translateExtent:c,minZoom:v,maxZoom:C,preventScrolling:P,onSelectionContextMenu:w,noWheelClassName:r,noPanClassName:S,disableKeyboardA11y:T,onViewportChange:Y,isControlledViewport:R}){let{nodesSelectionActive:m,userSelectionActive:p}=mf(GD,A0),n=El(A,{target:ZZ}),_f=El(E,{target:ZZ}),t=_f||D,ff=_f||V,Gf=U&&t!==!0,zf=n||p||Gf;return tw({deleteKeyCode:F,multiSelectionKeyCode:q}),o.jsx(aw,{onPaneContextMenu:l,elementsSelectable:G,zoomOnScroll:H,zoomOnPinch:Z,panOnScroll:ff,panOnScrollSpeed:L,panOnScrollMode:M,zoomOnDoubleClick:N,panOnDrag:!n&&t,defaultViewport:x,translateExtent:c,minZoom:v,maxZoom:C,zoomActivationKeyCode:O,preventScrolling:P,noWheelClassName:r,noPanClassName:S,onViewportChange:Y,isControlledViewport:R,paneClickDistance:J,selectionOnDrag:Gf,children:o.jsxs(uD,{onSelectionStart:W,onSelectionEnd:K,onPaneClick:u,onPaneMouseEnter:_,onPaneMouseMove:y,onPaneMouseLeave:$,onPaneContextMenu:l,onPaneScroll:j,panOnDrag:t,isSelecting:!!zf,selectionMode:z,selectionKeyPressed:n,paneClickDistance:J,selectionOnDrag:Gf,children:[f,m&&o.jsx(zD,{onSelectionContextMenu:w,noPanClassName:S,disableKeyboardA11y:T})]})})}xZ.displayName="FlowRenderer";var KD=d.memo(xZ),ZD=(f)=>(u)=>{return f?N5(u.nodeLookup,{x:0,y:0,width:u.width,height:u.height},u.transform,!0).map((_)=>_.id):Array.from(u.nodeLookup.keys())};function qD(f){return mf(d.useCallback(ZD(f),[f]),A0)}var HD=(f)=>f.updateNodeInternals;function ED(){let f=mf(HD),[u]=d.useState(()=>{if(typeof ResizeObserver>"u")return null;return new ResizeObserver((_)=>{let y=new Map;_.forEach(($)=>{let l=$.target.getAttribute("data-id");y.set(l,{id:l,nodeElement:$.target,force:!0})}),f(y)})});return d.useEffect(()=>{return()=>{u?.disconnect()}},[u]),u}function VD({node:f,nodeType:u,hasDimensions:_,resizeObserver:y}){let $=W0(),l=d.useRef(null),j=d.useRef(null),J=d.useRef(f.sourcePosition),F=d.useRef(f.targetPosition),A=d.useRef(u),U=_&&!!f.internals.handleBounds;return d.useEffect(()=>{if(l.current&&!f.hidden&&(!U||j.current!==l.current)){if(j.current)y?.unobserve(j.current);y?.observe(l.current),j.current=l.current}},[U,f.hidden]),d.useEffect(()=>{return()=>{if(j.current)y?.unobserve(j.current),j.current=null}},[]),d.useEffect(()=>{if(l.current){let z=A.current!==u,W=J.current!==f.sourcePosition,K=F.current!==f.targetPosition;if(z||W||K)A.current=u,J.current=f.sourcePosition,F.current=f.targetPosition,$.getState().updateNodeInternals(new Map([[f.id,{id:f.id,nodeElement:l.current,force:!0}]]))}},[f.id,u,f.sourcePosition,f.targetPosition]),l}function OD({id:f,onClick:u,onMouseEnter:_,onMouseMove:y,onMouseLeave:$,onContextMenu:l,onDoubleClick:j,nodesDraggable:J,elementsSelectable:F,nodesConnectable:A,nodesFocusable:U,resizeObserver:z,noDragClassName:W,noPanClassName:K,disableKeyboardA11y:q,rfId:E,nodeTypes:O,nodeClickDistance:G,onError:H}){let{node:Z,internals:V,isParent:L}=mf((jf)=>{let Wf=jf.nodeLookup.get(f),Vf=jf.parentLookup.has(f);return{node:Wf,internals:Wf.internals,isParent:Vf}},A0),M=Z.type||"default",N=O?.[M]||KZ[M];if(N===void 0)H?.("003",hu.error003(M)),M="default",N=O?.default||KZ.default;let D=!!(Z.draggable||J&&typeof Z.draggable>"u"),x=!!(Z.selectable||F&&typeof Z.selectable>"u"),c=!!(Z.connectable||A&&typeof Z.connectable>"u"),v=!!(Z.focusable||U&&typeof Z.focusable>"u"),C=W0(),P=WF(Z),w=VD({node:Z,nodeType:M,hasDimensions:P,resizeObserver:z}),r=PZ({nodeRef:w,disabled:Z.hidden||!D,noDragClassName:W,handleSelector:Z.dragHandle,nodeId:f,isSelectable:x,nodeClickDistance:G}),S=CZ();if(Z.hidden)return null;let T=b1(Z),Y=UD(Z),R=x||D||u||_||y||$,m=_?(jf)=>_(jf,{...V.userNode}):void 0,p=y?(jf)=>y(jf,{...V.userNode}):void 0,n=$?(jf)=>$(jf,{...V.userNode}):void 0,_f=l?(jf)=>l(jf,{...V.userNode}):void 0,t=j?(jf)=>j(jf,{...V.userNode}):void 0,ff=(jf)=>{let{selectNodesOnDrag:Wf,nodeDragThreshold:Vf}=C.getState();if(x&&(!Wf||!D||Vf>0))MF({id:f,store:C,nodeRef:w});if(u)u(jf,{...V.userNode})},Gf=(jf)=>{if(ZF(jf.nativeEvent)||q)return;if(uF.includes(jf.key)&&x){let Wf=jf.key==="Escape";MF({id:f,store:C,unselect:Wf,nodeRef:w})}else if(D&&Z.selected&&Object.prototype.hasOwnProperty.call(b5,jf.key)){jf.preventDefault();let{ariaLabelConfig:Wf}=C.getState();C.setState({ariaLiveMessage:Wf["node.a11yDescription.ariaLiveMessage"]({direction:jf.key.replace("Arrow","").toLowerCase(),x:~~V.positionAbsolute.x,y:~~V.positionAbsolute.y})}),S({direction:b5[jf.key],factor:jf.shiftKey?4:1})}},zf=()=>{if(q||!w.current?.matches(":focus-visible"))return;let{transform:jf,width:Wf,height:Vf,autoPanOnNodeFocus:Zf,setCenter:h}=C.getState();if(!Zf)return;if(!(N5(new Map([[f,Z]]),{x:0,y:0,width:Wf,height:Vf},jf,!0).length>0))h(Z.position.x+T.width/2,Z.position.y+T.height/2,{zoom:jf[2]})};return o.jsx("div",{className:Y0(["react-flow__node",`react-flow__node-${M}`,{[K]:D},Z.className,{selected:Z.selected,selectable:x,parent:L,draggable:D,dragging:r}]),ref:w,style:{zIndex:V.z,transform:`translate(${V.positionAbsolute.x}px,${V.positionAbsolute.y}px)`,pointerEvents:R?"all":"none",visibility:P?"visible":"hidden",...Z.style,...Y},"data-id":f,"data-testid":`rf__node-${f}`,onMouseEnter:m,onMouseMove:p,onMouseLeave:n,onContextMenu:_f,onClick:ff,onDoubleClick:t,onKeyDown:v?Gf:void 0,tabIndex:v?0:void 0,onFocus:v?zf:void 0,role:Z.ariaRole??(v?"group":void 0),"aria-roledescription":"node","aria-describedby":q?void 0:`${wZ}-${E}`,"aria-label":Z.ariaLabel,...Z.domAttributes,children:o.jsx(yD,{value:f,children:o.jsx(N,{id:f,data:Z.data,type:M,positionAbsoluteX:V.positionAbsolute.x,positionAbsoluteY:V.positionAbsolute.y,selected:Z.selected??!1,selectable:x,draggable:D,deletable:Z.deletable??!0,isConnectable:c,sourcePosition:Z.sourcePosition,targetPosition:Z.targetPosition,dragging:r,dragHandle:Z.dragHandle,zIndex:V.z,parentId:Z.parentId,...T})})})}var XD=d.memo(OD),ND=(f)=>({nodesDraggable:f.nodesDraggable,nodesConnectable:f.nodesConnectable,nodesFocusable:f.nodesFocusable,elementsSelectable:f.elementsSelectable,onError:f.onError});function vZ(f){let{nodesDraggable:u,nodesConnectable:_,nodesFocusable:y,elementsSelectable:$,onError:l}=mf(ND,A0),j=qD(f.onlyRenderVisibleElements),J=ED();return o.jsx("div",{className:"react-flow__nodes",style:c5,children:j.map((F)=>{return o.jsx(XD,{id:F,nodeTypes:f.nodeTypes,nodeExtent:f.nodeExtent,onClick:f.onNodeClick,onMouseEnter:f.onNodeMouseEnter,onMouseMove:f.onNodeMouseMove,onMouseLeave:f.onNodeMouseLeave,onContextMenu:f.onNodeContextMenu,onDoubleClick:f.onNodeDoubleClick,noDragClassName:f.noDragClassName,noPanClassName:f.noPanClassName,rfId:f.rfId,disableKeyboardA11y:f.disableKeyboardA11y,resizeObserver:J,nodesDraggable:u,nodesConnectable:_,nodesFocusable:y,elementsSelectable:$,nodeClickDistance:f.nodeClickDistance,onError:l},F)})})}vZ.displayName="NodeRenderer";var LD=d.memo(vZ);function YD(f){return mf(d.useCallback((_)=>{if(!f)return _.edges.map(($)=>$.id);let y=[];if(_.width&&_.height)for(let $ of _.edges){let l=_.nodeLookup.get($.source),j=_.nodeLookup.get($.target);if(l&&j&&NK({sourceNode:l,targetNode:j,width:_.width,height:_.height,transform:_.transform}))y.push($.id)}return y},[f]),A0)}var BD=({color:f="none",strokeWidth:u=1})=>{let _={strokeWidth:u,...f&&{stroke:f}};return o.jsx("polyline",{className:"arrow",style:_,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},wD=({color:f="none",strokeWidth:u=1})=>{let _={strokeWidth:u,...f&&{stroke:f,fill:f}};return o.jsx("polyline",{className:"arrowclosed",style:_,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},qZ={[n_.Arrow]:BD,[n_.ArrowClosed]:wD};function DD(f){let u=W0();return d.useMemo(()=>{if(!Object.prototype.hasOwnProperty.call(qZ,f))return u.getState().onError?.("009",hu.error009(f)),null;return qZ[f]},[f])}var TD=({id:f,type:u,color:_,width:y=12.5,height:$=12.5,markerUnits:l="strokeWidth",strokeWidth:j,orient:J="auto-start-reverse"})=>{let F=DD(u);if(!F)return null;return o.jsx("marker",{className:"react-flow__arrowhead",id:f,markerWidth:`${y}`,markerHeight:`${$}`,viewBox:"-10 -10 20 20",markerUnits:l,orient:J,refX:"0",refY:"0",children:o.jsx(F,{color:_,strokeWidth:j})})},bZ=({defaultColor:f,rfId:u})=>{let _=mf((l)=>l.edges),y=mf((l)=>l.defaultEdgeOptions),$=d.useMemo(()=>{return YK(_,{id:u,defaultColor:f,defaultMarkerStart:y?.markerStart,defaultMarkerEnd:y?.markerEnd})},[_,y,u,f]);if(!$.length)return null;return o.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:o.jsx("defs",{children:$.map((l)=>o.jsx(TD,{id:l.id,type:l.type,color:l.color,width:l.width,height:l.height,markerUnits:l.markerUnits,strokeWidth:l.strokeWidth,orient:l.orient},l.id))})})};bZ.displayName="MarkerDefinitions";var MD=d.memo(bZ);function hZ({x:f,y:u,label:_,labelStyle:y,labelShowBg:$=!0,labelBgStyle:l,labelBgPadding:j=[2,4],labelBgBorderRadius:J=2,children:F,className:A,...U}){let[z,W]=d.useState({x:1,y:0,width:0,height:0}),K=Y0(["react-flow__edge-textwrapper",A]),q=d.useRef(null);if(d.useEffect(()=>{if(q.current){let E=q.current.getBBox();W({x:E.x,y:E.y,width:E.width,height:E.height})}},[_]),!_)return null;return o.jsxs("g",{transform:`translate(${f-z.width/2} ${u-z.height/2})`,className:K,visibility:z.width?"visible":"hidden",...U,children:[$&&o.jsx("rect",{width:z.width+2*j[0],x:-j[0],y:-j[1],height:z.height+2*j[1],className:"react-flow__edge-textbg",style:l,rx:J,ry:J}),o.jsx("text",{className:"react-flow__edge-text",y:z.height/2,dy:"0.3em",ref:q,style:y,children:_}),F]})}hZ.displayName="EdgeText";var SD=d.memo(hZ);function A$({path:f,labelX:u,labelY:_,label:y,labelStyle:$,labelShowBg:l,labelBgStyle:j,labelBgPadding:J,labelBgBorderRadius:F,interactionWidth:A=20,...U}){return o.jsxs(o.Fragment,{children:[o.jsx("path",{...U,d:f,fill:"none",className:Y0(["react-flow__edge-path",U.className])}),A?o.jsx("path",{d:f,fill:"none",strokeOpacity:0,strokeWidth:A,className:"react-flow__edge-interaction"}):null,y&&u1(u)&&u1(_)?o.jsx(SD,{x:u,y:_,label:y,labelStyle:$,labelShowBg:l,labelBgStyle:j,labelBgPadding:J,labelBgBorderRadius:F}):null]})}function HZ({pos:f,x1:u,y1:_,x2:y,y2:$}){if(f===Uf.Left||f===Uf.Right)return[0.5*(u+y),_];return[u,0.5*(_+$)]}function IZ({sourceX:f,sourceY:u,sourcePosition:_=Uf.Bottom,targetX:y,targetY:$,targetPosition:l=Uf.Top}){let[j,J]=HZ({pos:_,x1:f,y1:u,x2:y,y2:$}),[F,A]=HZ({pos:l,x1:y,y1:$,x2:f,y2:u}),[U,z,W,K]=w5({sourceX:f,sourceY:u,targetX:y,targetY:$,sourceControlX:j,sourceControlY:J,targetControlX:F,targetControlY:A});return[`M${f},${u} C${j},${J} ${F},${A} ${y},${$}`,U,z,W,K]}function cZ(f){return d.memo(({id:u,sourceX:_,sourceY:y,targetX:$,targetY:l,sourcePosition:j,targetPosition:J,label:F,labelStyle:A,labelShowBg:U,labelBgStyle:z,labelBgPadding:W,labelBgBorderRadius:K,style:q,markerEnd:E,markerStart:O,interactionWidth:G})=>{let[H,Z,V]=IZ({sourceX:_,sourceY:y,sourcePosition:j,targetX:$,targetY:l,targetPosition:J}),L=f.isInternal?void 0:u;return o.jsx(A$,{id:L,path:H,labelX:Z,labelY:V,label:F,labelStyle:A,labelShowBg:U,labelBgStyle:z,labelBgPadding:W,labelBgBorderRadius:K,style:q,markerEnd:E,markerStart:O,interactionWidth:G})})}var rD=cZ({isInternal:!1}),pZ=cZ({isInternal:!0});rD.displayName="SimpleBezierEdge";pZ.displayName="SimpleBezierEdgeInternal";function mZ(f){return d.memo(({id:u,sourceX:_,sourceY:y,targetX:$,targetY:l,label:j,labelStyle:J,labelShowBg:F,labelBgStyle:A,labelBgPadding:U,labelBgBorderRadius:z,style:W,sourcePosition:K=Uf.Bottom,targetPosition:q=Uf.Top,markerEnd:E,markerStart:O,pathOptions:G,interactionWidth:H})=>{let[Z,V,L]=Hl({sourceX:_,sourceY:y,sourcePosition:K,targetX:$,targetY:l,targetPosition:q,borderRadius:G?.borderRadius,offset:G?.offset,stepPosition:G?.stepPosition}),M=f.isInternal?void 0:u;return o.jsx(A$,{id:M,path:Z,labelX:V,labelY:L,label:j,labelStyle:J,labelShowBg:F,labelBgStyle:A,labelBgPadding:U,labelBgBorderRadius:z,style:W,markerEnd:E,markerStart:O,interactionWidth:H})})}var kZ=mZ({isInternal:!1}),iZ=mZ({isInternal:!0});kZ.displayName="SmoothStepEdge";iZ.displayName="SmoothStepEdgeInternal";function gZ(f){return d.memo(({id:u,..._})=>{let y=f.isInternal?void 0:u;return o.jsx(kZ,{..._,id:y,pathOptions:d.useMemo(()=>({borderRadius:0,offset:_.pathOptions?.offset}),[_.pathOptions?.offset])})})}var PD=gZ({isInternal:!1}),nZ=gZ({isInternal:!0});PD.displayName="StepEdge";nZ.displayName="StepEdgeInternal";function tZ(f){return d.memo(({id:u,sourceX:_,sourceY:y,targetX:$,targetY:l,label:j,labelStyle:J,labelShowBg:F,labelBgStyle:A,labelBgPadding:U,labelBgBorderRadius:z,style:W,markerEnd:K,markerStart:q,interactionWidth:E})=>{let[O,G,H]=T5({sourceX:_,sourceY:y,targetX:$,targetY:l}),Z=f.isInternal?void 0:u;return o.jsx(A$,{id:Z,path:O,labelX:G,labelY:H,label:j,labelStyle:J,labelShowBg:F,labelBgStyle:A,labelBgPadding:U,labelBgBorderRadius:z,style:W,markerEnd:K,markerStart:q,interactionWidth:E})})}var CD=tZ({isInternal:!1}),sZ=tZ({isInternal:!0});CD.displayName="StraightEdge";sZ.displayName="StraightEdgeInternal";function oZ(f){return d.memo(({id:u,sourceX:_,sourceY:y,targetX:$,targetY:l,sourcePosition:j=Uf.Bottom,targetPosition:J=Uf.Top,label:F,labelStyle:A,labelShowBg:U,labelBgStyle:z,labelBgPadding:W,labelBgBorderRadius:K,style:q,markerEnd:E,markerStart:O,pathOptions:G,interactionWidth:H})=>{let[Z,V,L]=D5({sourceX:_,sourceY:y,sourcePosition:j,targetX:$,targetY:l,targetPosition:J,curvature:G?.curvature}),M=f.isInternal?void 0:u;return o.jsx(A$,{id:M,path:Z,labelX:V,labelY:L,label:F,labelStyle:A,labelShowBg:U,labelBgStyle:z,labelBgPadding:W,labelBgBorderRadius:K,style:q,markerEnd:E,markerStart:O,interactionWidth:H})})}var RD=oZ({isInternal:!1}),aZ=oZ({isInternal:!0});RD.displayName="BezierEdge";aZ.displayName="BezierEdgeInternal";var EZ={default:aZ,straight:sZ,step:nZ,smoothstep:iZ,simplebezier:pZ},VZ={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null},xD=(f,u,_)=>{if(_===Uf.Left)return f-u;if(_===Uf.Right)return f+u;return f},vD=(f,u,_)=>{if(_===Uf.Top)return f-u;if(_===Uf.Bottom)return f+u;return f},OZ="react-flow__edgeupdater";function XZ({position:f,centerX:u,centerY:_,radius:y=10,onMouseDown:$,onMouseEnter:l,onMouseOut:j,type:J}){return o.jsx("circle",{onMouseDown:$,onMouseEnter:l,onMouseOut:j,className:Y0([OZ,`${OZ}-${J}`]),cx:xD(u,y,f),cy:vD(_,y,f),r:y,stroke:"transparent",fill:"transparent"})}function bD({isReconnectable:f,reconnectRadius:u,edge:_,sourceX:y,sourceY:$,targetX:l,targetY:j,sourcePosition:J,targetPosition:F,onReconnect:A,onReconnectStart:U,onReconnectEnd:z,setReconnecting:W,setUpdateHover:K}){let q=W0(),E=(V,L)=>{if(V.button!==0)return;let{autoPanOnConnect:M,domNode:N,connectionMode:D,connectionRadius:x,lib:c,onConnectStart:v,cancelConnection:C,nodeLookup:P,rfId:w,panBy:r,updateConnection:S}=q.getState(),T=L.type==="target",Y=(p,n)=>{W(!1),z?.(p,_,L.type,n)},R=(p)=>A?.(_,p),m=(p,n)=>{W(!0),U?.(V,_,L.type),v?.(p,n)};P5.onPointerDown(V.nativeEvent,{autoPanOnConnect:M,connectionMode:D,connectionRadius:x,domNode:N,handleId:L.id,nodeId:L.nodeId,nodeLookup:P,isTarget:T,edgeUpdaterType:L.type,lib:c,flowId:w,cancelConnection:C,panBy:r,isValidConnection:(...p)=>q.getState().isValidConnection?.(...p)??!0,onConnect:R,onConnectStart:m,onConnectEnd:(...p)=>q.getState().onConnectEnd?.(...p),onReconnectEnd:Y,updateConnection:S,getTransform:()=>q.getState().transform,getFromHandle:()=>q.getState().connection.fromHandle,dragThreshold:q.getState().connectionDragThreshold,handleDomNode:V.currentTarget})},O=(V)=>E(V,{nodeId:_.target,id:_.targetHandle??null,type:"target"}),G=(V)=>E(V,{nodeId:_.source,id:_.sourceHandle??null,type:"source"}),H=()=>K(!0),Z=()=>K(!1);return o.jsxs(o.Fragment,{children:[(f===!0||f==="source")&&o.jsx(XZ,{position:J,centerX:y,centerY:$,radius:u,onMouseDown:O,onMouseEnter:H,onMouseOut:Z,type:"source"}),(f===!0||f==="target")&&o.jsx(XZ,{position:F,centerX:l,centerY:j,radius:u,onMouseDown:G,onMouseEnter:H,onMouseOut:Z,type:"target"})]})}function hD({id:f,edgesFocusable:u,edgesReconnectable:_,elementsSelectable:y,onClick:$,onDoubleClick:l,onContextMenu:j,onMouseEnter:J,onMouseMove:F,onMouseLeave:A,reconnectRadius:U,onReconnect:z,onReconnectStart:W,onReconnectEnd:K,rfId:q,edgeTypes:E,noPanClassName:O,onError:G,disableKeyboardA11y:H}){let Z=mf((h)=>h.edgeLookup.get(f)),V=mf((h)=>h.defaultEdgeOptions);Z=V?{...V,...Z}:Z;let L=Z.type||"default",M=E?.[L]||EZ[L];if(M===void 0)G?.("011",hu.error011(L)),L="default",M=E?.default||EZ.default;let N=!!(Z.focusable||u&&typeof Z.focusable>"u"),D=typeof z<"u"&&(Z.reconnectable||_&&typeof Z.reconnectable>"u"),x=!!(Z.selectable||y&&typeof Z.selectable>"u"),c=d.useRef(null),[v,C]=d.useState(!1),[P,w]=d.useState(!1),r=W0(),{zIndex:S,sourceX:T,sourceY:Y,targetX:R,targetY:m,sourcePosition:p,targetPosition:n}=mf(d.useCallback((h)=>{let g=h.nodeLookup.get(Z.source),I=h.nodeLookup.get(Z.target);if(!g||!I)return{zIndex:Z.zIndex,...VZ};let $f=LK({id:f,sourceNode:g,targetNode:I,sourceHandle:Z.sourceHandle||null,targetHandle:Z.targetHandle||null,connectionMode:h.connectionMode,onError:G});return{zIndex:XK({selected:Z.selected,zIndex:Z.zIndex,sourceNode:g,targetNode:I,elevateOnSelect:h.elevateEdgesOnSelect,zIndexMode:h.zIndexMode}),...$f||VZ}},[Z.source,Z.target,Z.sourceHandle,Z.targetHandle,Z.selected,Z.zIndex]),A0),_f=d.useMemo(()=>Z.markerStart?`url('#${M5(Z.markerStart,q)}')`:void 0,[Z.markerStart,q]),t=d.useMemo(()=>Z.markerEnd?`url('#${M5(Z.markerEnd,q)}')`:void 0,[Z.markerEnd,q]);if(Z.hidden||T===null||Y===null||R===null||m===null)return null;let ff=(h)=>{let{addSelectedEdges:g,unselectNodesAndEdges:I,multiSelectionActive:$f}=r.getState();if(x)if(r.setState({nodesSelectionActive:!1}),Z.selected&&$f)I({nodes:[],edges:[Z]}),c.current?.blur();else g([f]);if($)$(h,Z)},Gf=l?(h)=>{l(h,{...Z})}:void 0,zf=j?(h)=>{j(h,{...Z})}:void 0,jf=J?(h)=>{J(h,{...Z})}:void 0,Wf=F?(h)=>{F(h,{...Z})}:void 0,Vf=A?(h)=>{A(h,{...Z})}:void 0,Zf=(h)=>{if(!H&&uF.includes(h.key)&&x){let{unselectNodesAndEdges:g,addSelectedEdges:I}=r.getState();if(h.key==="Escape")c.current?.blur(),g({edges:[Z]});else I([f])}};return o.jsx("svg",{style:{zIndex:S},children:o.jsxs("g",{className:Y0(["react-flow__edge",`react-flow__edge-${L}`,Z.className,O,{selected:Z.selected,animated:Z.animated,inactive:!x&&!$,updating:v,selectable:x}]),onClick:ff,onDoubleClick:Gf,onContextMenu:zf,onMouseEnter:jf,onMouseMove:Wf,onMouseLeave:Vf,onKeyDown:N?Zf:void 0,tabIndex:N?0:void 0,role:Z.ariaRole??(N?"group":"img"),"aria-roledescription":"edge","data-id":f,"data-testid":`rf__edge-${f}`,"aria-label":Z.ariaLabel===null?void 0:Z.ariaLabel||`Edge from ${Z.source} to ${Z.target}`,"aria-describedby":N?`${DZ}-${q}`:void 0,ref:c,...Z.domAttributes,children:[!P&&o.jsx(M,{id:f,source:Z.source,target:Z.target,type:Z.type,selected:Z.selected,animated:Z.animated,selectable:x,deletable:Z.deletable??!0,label:Z.label,labelStyle:Z.labelStyle,labelShowBg:Z.labelShowBg,labelBgStyle:Z.labelBgStyle,labelBgPadding:Z.labelBgPadding,labelBgBorderRadius:Z.labelBgBorderRadius,sourceX:T,sourceY:Y,targetX:R,targetY:m,sourcePosition:p,targetPosition:n,data:Z.data,style:Z.style,sourceHandleId:Z.sourceHandle,targetHandleId:Z.targetHandle,markerStart:_f,markerEnd:t,pathOptions:"pathOptions"in Z?Z.pathOptions:void 0,interactionWidth:Z.interactionWidth}),D&&o.jsx(bD,{edge:Z,isReconnectable:D,reconnectRadius:U,onReconnect:z,onReconnectStart:W,onReconnectEnd:K,sourceX:T,sourceY:Y,targetX:R,targetY:m,sourcePosition:p,targetPosition:n,setUpdateHover:C,setReconnecting:w})]})})}var ID=d.memo(hD),cD=(f)=>({edgesFocusable:f.edgesFocusable,edgesReconnectable:f.edgesReconnectable,elementsSelectable:f.elementsSelectable,connectionMode:f.connectionMode,onError:f.onError});function dZ({defaultMarkerColor:f,onlyRenderVisibleElements:u,rfId:_,edgeTypes:y,noPanClassName:$,onReconnect:l,onEdgeContextMenu:j,onEdgeMouseEnter:J,onEdgeMouseMove:F,onEdgeMouseLeave:A,onEdgeClick:U,reconnectRadius:z,onEdgeDoubleClick:W,onReconnectStart:K,onReconnectEnd:q,disableKeyboardA11y:E}){let{edgesFocusable:O,edgesReconnectable:G,elementsSelectable:H,onError:Z}=mf(cD,A0),V=YD(u);return o.jsxs("div",{className:"react-flow__edges",children:[o.jsx(MD,{defaultColor:f,rfId:_}),V.map((L)=>{return o.jsx(ID,{id:L,edgesFocusable:O,edgesReconnectable:G,elementsSelectable:H,noPanClassName:$,onReconnect:l,onContextMenu:j,onMouseEnter:J,onMouseMove:F,onMouseLeave:A,onClick:U,reconnectRadius:z,onDoubleClick:W,onReconnectStart:K,onReconnectEnd:q,rfId:_,onError:Z,edgeTypes:y,disableKeyboardA11y:E},L)})]})}dZ.displayName="EdgeRenderer";var pD=d.memo(dZ),mD=(f)=>`translate(${f.transform[0]}px,${f.transform[1]}px) scale(${f.transform[2]})`;function kD({children:f}){let u=mf(mD);return o.jsx("div",{className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:u},children:f})}function iD(f){let u=SF(),_=d.useRef(!1);d.useEffect(()=>{if(!_.current&&u.viewportInitialized&&f)setTimeout(()=>f(u),1),_.current=!0},[f,u.viewportInitialized])}var gD=(f)=>f.panZoom?.syncViewport;function nD(f){let u=mf(gD),_=W0();return d.useEffect(()=>{if(f)u?.(f),_.setState({transform:[f.x,f.y,f.zoom]})},[f,u]),null}function NZ(f){return f.connection.inProgress?{...f.connection,to:j$(f.connection.to,f.transform)}:{...f.connection}}function tD(f){if(f)return(_)=>{let y=NZ(_);return f(y)};return NZ}function sD(f){let u=tD(f);return mf(u,A0)}var oD=(f)=>({nodesConnectable:f.nodesConnectable,isValid:f.connection.isValid,inProgress:f.connection.inProgress,width:f.width,height:f.height});function aD({containerStyle:f,style:u,type:_,component:y}){let{nodesConnectable:$,width:l,height:j,isValid:J,inProgress:F}=mf(oD,A0);if(!(l&&$&&F))return null;return o.jsx("svg",{style:f,width:l,height:j,className:"react-flow__connectionline react-flow__container",children:o.jsx("g",{className:Y0(["react-flow__connection",$F(J)]),children:o.jsx(eZ,{style:u,type:_,CustomComponent:y,isValid:J})})})}var eZ=({style:f,type:u=v1.Bezier,CustomComponent:_,isValid:y})=>{let{inProgress:$,from:l,fromNode:j,fromHandle:J,fromPosition:F,to:A,toNode:U,toHandle:z,toPosition:W,pointer:K}=sD();if(!$)return;if(_)return o.jsx(_,{connectionLineType:u,connectionLineStyle:f,fromNode:j,fromHandle:J,fromX:l.x,fromY:l.y,toX:A.x,toY:A.y,fromPosition:F,toPosition:W,connectionStatus:$F(y),toNode:U,toHandle:z,pointer:K});let q="",E={sourceX:l.x,sourceY:l.y,sourcePosition:F,targetX:A.x,targetY:A.y,targetPosition:W};switch(u){case v1.Bezier:[q]=D5(E);break;case v1.SimpleBezier:[q]=IZ(E);break;case v1.Step:[q]=Hl({...E,borderRadius:0});break;case v1.SmoothStep:[q]=Hl(E);break;default:[q]=T5(E)}return o.jsx("path",{d:q,fill:"none",className:"react-flow__connection-path",style:f})};eZ.displayName="ConnectionLine";var dD={};function LZ(f=dD){let u=d.useRef(f),_=W0();d.useEffect(()=>{},[f])}function eD(){let f=W0(),u=d.useRef(!1);d.useEffect(()=>{},[])}function fq({nodeTypes:f,edgeTypes:u,onInit:_,onNodeClick:y,onEdgeClick:$,onNodeDoubleClick:l,onEdgeDoubleClick:j,onNodeMouseEnter:J,onNodeMouseMove:F,onNodeMouseLeave:A,onNodeContextMenu:U,onSelectionContextMenu:z,onSelectionStart:W,onSelectionEnd:K,connectionLineType:q,connectionLineStyle:E,connectionLineComponent:O,connectionLineContainerStyle:G,selectionKeyCode:H,selectionOnDrag:Z,selectionMode:V,multiSelectionKeyCode:L,panActivationKeyCode:M,zoomActivationKeyCode:N,deleteKeyCode:D,onlyRenderVisibleElements:x,elementsSelectable:c,defaultViewport:v,translateExtent:C,minZoom:P,maxZoom:w,preventScrolling:r,defaultMarkerColor:S,zoomOnScroll:T,zoomOnPinch:Y,panOnScroll:R,panOnScrollSpeed:m,panOnScrollMode:p,zoomOnDoubleClick:n,panOnDrag:_f,onPaneClick:t,onPaneMouseEnter:ff,onPaneMouseMove:Gf,onPaneMouseLeave:zf,onPaneScroll:jf,onPaneContextMenu:Wf,paneClickDistance:Vf,nodeClickDistance:Zf,onEdgeContextMenu:h,onEdgeMouseEnter:g,onEdgeMouseMove:I,onEdgeMouseLeave:$f,reconnectRadius:lf,onReconnect:Af,onReconnectStart:Yf,onReconnectEnd:xf,noDragClassName:sf,noWheelClassName:j0,noPanClassName:u0,disableKeyboardA11y:D0,nodeExtent:Fu,rfId:O0,viewport:x0,onViewportChange:ku}){return LZ(f),LZ(u),eD(),iD(_),nD(x0),o.jsx(KD,{onPaneClick:t,onPaneMouseEnter:ff,onPaneMouseMove:Gf,onPaneMouseLeave:zf,onPaneContextMenu:Wf,onPaneScroll:jf,paneClickDistance:Vf,deleteKeyCode:D,selectionKeyCode:H,selectionOnDrag:Z,selectionMode:V,onSelectionStart:W,onSelectionEnd:K,multiSelectionKeyCode:L,panActivationKeyCode:M,zoomActivationKeyCode:N,elementsSelectable:c,zoomOnScroll:T,zoomOnPinch:Y,zoomOnDoubleClick:n,panOnScroll:R,panOnScrollSpeed:m,panOnScrollMode:p,panOnDrag:_f,defaultViewport:v,translateExtent:C,minZoom:P,maxZoom:w,onSelectionContextMenu:z,preventScrolling:r,noDragClassName:sf,noWheelClassName:j0,noPanClassName:u0,disableKeyboardA11y:D0,onViewportChange:ku,isControlledViewport:!!x0,children:o.jsxs(kD,{children:[o.jsx(pD,{edgeTypes:u,onEdgeClick:$,onEdgeDoubleClick:j,onReconnect:Af,onReconnectStart:Yf,onReconnectEnd:xf,onlyRenderVisibleElements:x,onEdgeContextMenu:h,onEdgeMouseEnter:g,onEdgeMouseMove:I,onEdgeMouseLeave:$f,reconnectRadius:lf,defaultMarkerColor:S,noPanClassName:u0,disableKeyboardA11y:D0,rfId:O0}),o.jsx(aD,{style:E,type:q,component:O,containerStyle:G}),o.jsx("div",{className:"react-flow__edgelabel-renderer"}),o.jsx(LD,{nodeTypes:f,onNodeClick:y,onNodeDoubleClick:l,onNodeMouseEnter:J,onNodeMouseMove:F,onNodeMouseLeave:A,onNodeContextMenu:U,nodeClickDistance:Zf,onlyRenderVisibleElements:x,noPanClassName:u0,noDragClassName:sf,disableKeyboardA11y:D0,nodeExtent:Fu,rfId:O0}),o.jsx("div",{className:"react-flow__viewport-portal"})]})})}fq.displayName="GraphView";var fT=d.memo(fq),YZ=({nodes:f,edges:u,defaultNodes:_,defaultEdges:y,width:$,height:l,fitView:j,fitViewOptions:J,minZoom:F=0.5,maxZoom:A=2,nodeOrigin:U,nodeExtent:z,zIndexMode:W="basic"}={})=>{let K=new Map,q=new Map,E=new Map,O=new Map,G=y??u??[],H=_??f??[],Z=U??[0,0],V=z??_$;LF(E,O,G);let{nodesInitialized:L}=S5(H,K,q,{nodeOrigin:Z,nodeExtent:V,zIndexMode:W}),M=[0,0,1];if(j&&$&&l){let N=y$(K,{filter:(v)=>!!((v.width||v.initialWidth)&&(v.height||v.initialHeight))}),{x:D,y:x,zoom:c}=ql(N,$,l,F,A,J?.padding??0.1);M=[D,x,c]}return{rfId:"1",width:$??0,height:l??0,transform:M,nodes:H,nodesInitialized:L,nodeLookup:K,parentLookup:q,edges:G,edgeLookup:O,connectionLookup:E,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:_!==void 0,hasDefaultEdges:y!==void 0,panZoom:null,minZoom:F,maxZoom:A,translateExtent:_$,nodeExtent:V,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:g_.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:Z,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:j??!1,fitViewOptions:J,fitViewResolver:null,connection:{...yF},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:UF,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:_F,zIndexMode:W,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},uT=({nodes:f,edges:u,defaultNodes:_,defaultEdges:y,width:$,height:l,fitView:j,fitViewOptions:J,minZoom:F,maxZoom:A,nodeOrigin:U,nodeExtent:z,zIndexMode:W})=>_Z((K,q)=>{async function E(){let{nodeLookup:O,panZoom:G,fitViewOptions:H,fitViewResolver:Z,width:V,height:L,minZoom:M,maxZoom:N}=q();if(!G)return;await ZK({nodes:O,width:V,height:L,panZoom:G,minZoom:M,maxZoom:N},H),Z?.resolve(!0),K({fitViewResolver:null})}return{...YZ({nodes:f,edges:u,width:$,height:l,fitView:j,fitViewOptions:J,minZoom:F,maxZoom:A,nodeOrigin:U,nodeExtent:z,defaultNodes:_,defaultEdges:y,zIndexMode:W}),setNodes:(O)=>{let{nodeLookup:G,parentLookup:H,nodeOrigin:Z,elevateNodesOnSelect:V,fitViewQueued:L,zIndexMode:M,nodesSelectionActive:N}=q(),{nodesInitialized:D,hasSelectedNodes:x}=S5(O,G,H,{nodeOrigin:Z,nodeExtent:z,elevateNodesOnSelect:V,checkEquality:!0,zIndexMode:M}),c=N&&x;if(L&&D)E(),K({nodes:O,nodesInitialized:D,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:c});else K({nodes:O,nodesInitialized:D,nodesSelectionActive:c})},setEdges:(O)=>{let{connectionLookup:G,edgeLookup:H}=q();LF(G,H,O),K({edges:O})},setDefaultNodesAndEdges:(O,G)=>{if(O){let{setNodes:H}=q();H(O),K({hasDefaultNodes:!0})}if(G){let{setEdges:H}=q();H(G),K({hasDefaultEdges:!0})}},updateNodeInternals:(O)=>{let{triggerNodeChanges:G,nodeLookup:H,parentLookup:Z,domNode:V,nodeOrigin:L,nodeExtent:M,debug:N,fitViewQueued:D,zIndexMode:x}=q(),{changes:c,updatedInternals:v}=TK(O,H,Z,V,L,M,x);if(!v)return;if(wK(H,Z,{nodeOrigin:L,nodeExtent:M,zIndexMode:x}),D)E(),K({fitViewQueued:!1,fitViewOptions:void 0});else K({});if(c?.length>0){if(N)console.log("React Flow: trigger node changes",c);G?.(c)}},updateNodePositions:(O,G=!1)=>{let H=[],Z=[],{nodeLookup:V,triggerNodeChanges:L,connection:M,updateConnection:N,onNodesChangeMiddlewareMap:D}=q();for(let[x,c]of O){let v=V.get(x),C=!!(v?.expandParent&&v?.parentId&&c?.position),P={id:x,type:"position",position:C?{x:Math.max(0,c.position.x),y:Math.max(0,c.position.y)}:c.position,dragging:G};if(v&&M.inProgress&&M.fromNode.id===v.id){let w=t_(v,M.fromHandle,Uf.Left,!0);N({...M,from:w})}if(C&&v.parentId)H.push({id:x,parentId:v.parentId,rect:{...c.internals.positionAbsolute,width:c.measured.width??0,height:c.measured.height??0}});Z.push(P)}if(H.length>0){let{parentLookup:x,nodeOrigin:c}=q(),v=r5(H,V,x,c);Z.push(...v)}for(let x of D.values())Z=x(Z);L(Z)},triggerNodeChanges:(O)=>{let{onNodesChange:G,setNodes:H,nodes:Z,hasDefaultNodes:V,debug:L}=q();if(O?.length){if(V){let M=Iw(O,Z);H(M)}if(L)console.log("React Flow: trigger node changes",O);G?.(O)}},triggerEdgeChanges:(O)=>{let{onEdgesChange:G,setEdges:H,edges:Z,hasDefaultEdges:V,debug:L}=q();if(O?.length){if(V){let M=cw(O,Z);H(M)}if(L)console.log("React Flow: trigger edge changes",O);G?.(O)}},addSelectedNodes:(O)=>{let{multiSelectionActive:G,edgeLookup:H,nodeLookup:Z,triggerNodeChanges:V,triggerEdgeChanges:L}=q();if(G){let M=O.map((N)=>ty(N,!0));V(M);return}V(Q$(Z,new Set([...O]),!0)),L(Q$(H))},addSelectedEdges:(O)=>{let{multiSelectionActive:G,edgeLookup:H,nodeLookup:Z,triggerNodeChanges:V,triggerEdgeChanges:L}=q();if(G){let M=O.map((N)=>ty(N,!0));L(M);return}L(Q$(H,new Set([...O]))),V(Q$(Z,new Set,!0))},unselectNodesAndEdges:({nodes:O,edges:G}={})=>{let{edges:H,nodes:Z,nodeLookup:V,triggerNodeChanges:L,triggerEdgeChanges:M}=q(),N=O?O:Z,D=G?G:H,x=[];for(let v of N){if(!v.selected)continue;let C=V.get(v.id);if(C)C.selected=!1;x.push(ty(v.id,!1))}let c=[];for(let v of D){if(!v.selected)continue;c.push(ty(v.id,!1))}L(x),M(c)},setMinZoom:(O)=>{let{panZoom:G,maxZoom:H}=q();G?.setScaleExtent([O,H]),K({minZoom:O})},setMaxZoom:(O)=>{let{panZoom:G,minZoom:H}=q();G?.setScaleExtent([H,O]),K({maxZoom:O})},setTranslateExtent:(O)=>{q().panZoom?.setTranslateExtent(O),K({translateExtent:O})},resetSelectedElements:()=>{let{edges:O,nodes:G,triggerNodeChanges:H,triggerEdgeChanges:Z,elementsSelectable:V}=q();if(!V)return;let L=G.reduce((N,D)=>D.selected?[...N,ty(D.id,!1)]:N,[]),M=O.reduce((N,D)=>D.selected?[...N,ty(D.id,!1)]:N,[]);H(L),Z(M)},setNodeExtent:(O)=>{let{nodes:G,nodeLookup:H,parentLookup:Z,nodeOrigin:V,elevateNodesOnSelect:L,nodeExtent:M,zIndexMode:N}=q();if(O[0][0]===M[0][0]&&O[0][1]===M[0][1]&&O[1][0]===M[1][0]&&O[1][1]===M[1][1])return;S5(G,H,Z,{nodeOrigin:V,nodeExtent:O,elevateNodesOnSelect:L,checkEquality:!1,zIndexMode:N}),K({nodeExtent:O})},panBy:(O)=>{let{transform:G,width:H,height:Z,panZoom:V,translateExtent:L}=q();return MK({delta:O,panZoom:V,transform:G,translateExtent:L,width:H,height:Z})},setCenter:async(O,G,H)=>{let{width:Z,height:V,maxZoom:L,panZoom:M}=q();if(!M)return Promise.resolve(!1);let N=typeof H?.zoom<"u"?H.zoom:L;return await M.setViewport({x:Z/2-O*N,y:V/2-G*N,zoom:N},{duration:H?.duration,ease:H?.ease,interpolate:H?.interpolate}),Promise.resolve(!0)},cancelConnection:()=>{K({connection:{...yF}})},updateConnection:(O)=>{K({connection:O})},reset:()=>K({...YZ()})}},Object.is);function _T({initialNodes:f,initialEdges:u,defaultNodes:_,defaultEdges:y,initialWidth:$,initialHeight:l,initialMinZoom:j,initialMaxZoom:J,initialFitViewOptions:F,fitView:A,nodeOrigin:U,nodeExtent:z,zIndexMode:W,children:K}){let[q]=d.useState(()=>uT({nodes:f,edges:u,defaultNodes:_,defaultEdges:y,width:$,height:l,fitView:A,minZoom:j,maxZoom:J,fitViewOptions:F,nodeOrigin:U,nodeExtent:z,zIndexMode:W}));return o.jsx(Vw,{value:q,children:o.jsx(kw,{children:K})})}function yT({children:f,nodes:u,edges:_,defaultNodes:y,defaultEdges:$,width:l,height:j,fitView:J,fitViewOptions:F,minZoom:A,maxZoom:U,nodeOrigin:z,nodeExtent:W,zIndexMode:K}){if(d.useContext(h5))return o.jsx(o.Fragment,{children:f});return o.jsx(_T,{initialNodes:u,initialEdges:_,defaultNodes:y,defaultEdges:$,initialWidth:l,initialHeight:j,fitView:J,initialFitViewOptions:F,initialMinZoom:A,initialMaxZoom:U,nodeOrigin:z,nodeExtent:W,zIndexMode:K,children:f})}var $T={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function lT({nodes:f,edges:u,defaultNodes:_,defaultEdges:y,className:$,nodeTypes:l,edgeTypes:j,onNodeClick:J,onEdgeClick:F,onInit:A,onMove:U,onMoveStart:z,onMoveEnd:W,onConnect:K,onConnectStart:q,onConnectEnd:E,onClickConnectStart:O,onClickConnectEnd:G,onNodeMouseEnter:H,onNodeMouseMove:Z,onNodeMouseLeave:V,onNodeContextMenu:L,onNodeDoubleClick:M,onNodeDragStart:N,onNodeDrag:D,onNodeDragStop:x,onNodesDelete:c,onEdgesDelete:v,onDelete:C,onSelectionChange:P,onSelectionDragStart:w,onSelectionDrag:r,onSelectionDragStop:S,onSelectionContextMenu:T,onSelectionStart:Y,onSelectionEnd:R,onBeforeDelete:m,connectionMode:p,connectionLineType:n=v1.Bezier,connectionLineStyle:_f,connectionLineComponent:t,connectionLineContainerStyle:ff,deleteKeyCode:Gf="Backspace",selectionKeyCode:zf="Shift",selectionOnDrag:jf=!1,selectionMode:Wf=iy.Full,panActivationKeyCode:Vf="Space",multiSelectionKeyCode:Zf=J$()?"Meta":"Control",zoomActivationKeyCode:h=J$()?"Meta":"Control",snapToGrid:g,snapGrid:I,onlyRenderVisibleElements:$f=!1,selectNodesOnDrag:lf,nodesDraggable:Af,autoPanOnNodeFocus:Yf,nodesConnectable:xf,nodesFocusable:sf,nodeOrigin:j0=TZ,edgesFocusable:u0,edgesReconnectable:D0,elementsSelectable:Fu=!0,defaultViewport:O0=Pw,minZoom:x0=0.5,maxZoom:ku=2,translateExtent:X0=_$,preventScrolling:Qu=!0,nodeExtent:uf,defaultMarkerColor:vf="#b1b1b7",zoomOnScroll:a0=!0,zoomOnPinch:Bf=!0,panOnScroll:v0=!1,panOnScrollSpeed:i0=0.5,panOnScrollMode:d0=Q_.Free,zoomOnDoubleClick:b0=!0,panOnDrag:m1=!0,onPaneClick:ef,onPaneMouseEnter:iu,onPaneMouseMove:f3,onPaneMouseLeave:u3,onPaneScroll:s,onPaneContextMenu:Of,paneClickDistance:qf=1,nodeClickDistance:Cf=0,children:_0,onReconnect:G0,onReconnectStart:If,onReconnectEnd:h0,onEdgeContextMenu:Au,onEdgeDoubleClick:xl,onEdgeMouseEnter:L1,onEdgeMouseMove:vl,onEdgeMouseLeave:_3,reconnectRadius:y3=10,onNodesChange:ly,onEdgesChange:W_,noDragClassName:bl="nodrag",noWheelClassName:Z2="nowheel",noPanClassName:hl="nopan",fitView:k1,fitViewOptions:jy,connectOnClick:Il,attributionPosition:q2,proOptions:V$,defaultEdgeOptions:O$,elevateNodesOnSelect:j1=!0,elevateEdgesOnSelect:Jy=!1,disableKeyboardA11y:X$=!1,autoPanOnConnect:H2,autoPanOnNodeDrag:cl,autoPanSpeed:N$,connectionRadius:E2,isValidConnection:V2,onError:i1,style:pl,id:L$,nodeDragThreshold:Y1,connectionDragThreshold:Y$,viewport:ml,onViewportChange:O2,width:X2,height:ZQ,colorMode:gu="light",debug:kl,onScroll:il,ariaLabelConfig:Tu,zIndexMode:$3="basic",...B$},w$){let D$=L$||"1",N2=vw(gu),L2=d.useCallback((gl)=>{gl.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),il?.(gl)},[il]);return o.jsx("div",{"data-testid":"rf__wrapper",...B$,onScroll:L2,style:{...pl,...$T},ref:w$,className:Y0(["react-flow",$,N2]),id:L$,role:"application",children:o.jsxs(yT,{nodes:f,edges:u,width:X2,height:ZQ,fitView:k1,fitViewOptions:jy,minZoom:x0,maxZoom:ku,nodeOrigin:j0,nodeExtent:uf,zIndexMode:$3,children:[o.jsx(xw,{nodes:f,edges:u,defaultNodes:_,defaultEdges:y,onConnect:K,onConnectStart:q,onConnectEnd:E,onClickConnectStart:O,onClickConnectEnd:G,nodesDraggable:Af,autoPanOnNodeFocus:Yf,nodesConnectable:xf,nodesFocusable:sf,edgesFocusable:u0,edgesReconnectable:D0,elementsSelectable:Fu,elevateNodesOnSelect:j1,elevateEdgesOnSelect:Jy,minZoom:x0,maxZoom:ku,nodeExtent:uf,onNodesChange:ly,onEdgesChange:W_,snapToGrid:g,snapGrid:I,connectionMode:p,translateExtent:X0,connectOnClick:Il,defaultEdgeOptions:O$,fitView:k1,fitViewOptions:jy,onNodesDelete:c,onEdgesDelete:v,onDelete:C,onNodeDragStart:N,onNodeDrag:D,onNodeDragStop:x,onSelectionDrag:r,onSelectionDragStart:w,onSelectionDragStop:S,onMove:U,onMoveStart:z,onMoveEnd:W,noPanClassName:hl,nodeOrigin:j0,rfId:D$,autoPanOnConnect:H2,autoPanOnNodeDrag:cl,autoPanSpeed:N$,onError:i1,connectionRadius:E2,isValidConnection:V2,selectNodesOnDrag:lf,nodeDragThreshold:Y1,connectionDragThreshold:Y$,onBeforeDelete:m,debug:kl,ariaLabelConfig:Tu,zIndexMode:$3}),o.jsx(fT,{onInit:A,onNodeClick:J,onEdgeClick:F,onNodeMouseEnter:H,onNodeMouseMove:Z,onNodeMouseLeave:V,onNodeContextMenu:L,onNodeDoubleClick:M,nodeTypes:l,edgeTypes:j,connectionLineType:n,connectionLineStyle:_f,connectionLineComponent:t,connectionLineContainerStyle:ff,selectionKeyCode:zf,selectionOnDrag:jf,selectionMode:Wf,deleteKeyCode:Gf,multiSelectionKeyCode:Zf,panActivationKeyCode:Vf,zoomActivationKeyCode:h,onlyRenderVisibleElements:$f,defaultViewport:O0,translateExtent:X0,minZoom:x0,maxZoom:ku,preventScrolling:Qu,zoomOnScroll:a0,zoomOnPinch:Bf,zoomOnDoubleClick:b0,panOnScroll:v0,panOnScrollSpeed:i0,panOnScrollMode:d0,panOnDrag:m1,onPaneClick:ef,onPaneMouseEnter:iu,onPaneMouseMove:f3,onPaneMouseLeave:u3,onPaneScroll:s,onPaneContextMenu:Of,paneClickDistance:qf,nodeClickDistance:Cf,onSelectionContextMenu:T,onSelectionStart:Y,onSelectionEnd:R,onReconnect:G0,onReconnectStart:If,onReconnectEnd:h0,onEdgeContextMenu:Au,onEdgeDoubleClick:xl,onEdgeMouseEnter:L1,onEdgeMouseMove:vl,onEdgeMouseLeave:_3,reconnectRadius:y3,defaultMarkerColor:vf,noDragClassName:bl,noWheelClassName:Z2,noPanClassName:hl,rfId:D$,disableKeyboardA11y:X$,nodeExtent:uf,viewport:ml,onViewportChange:O2}),o.jsx(rw,{onSelectionChange:P}),_0,o.jsx(ww,{proOptions:V$,position:q2}),o.jsx(Bw,{rfId:D$,disableKeyboardA11y:X$})]})})}var uq=SZ(lT);var db=hu.error014();function jT({dimensions:f,lineWidth:u,variant:_,className:y}){return o.jsx("path",{strokeWidth:u,d:`M${f[0]/2} 0 V${f[1]} M0 ${f[1]/2} H${f[0]}`,className:Y0(["react-flow__background-pattern",_,y])})}function JT({radius:f,className:u}){return o.jsx("circle",{cx:f,cy:f,r:f,className:Y0(["react-flow__background-pattern","dots",u])})}var o_;(function(f){f.Lines="lines",f.Dots="dots",f.Cross="cross"})(o_||(o_={}));var FT={[o_.Dots]:1,[o_.Lines]:1,[o_.Cross]:6},QT=(f)=>({transform:f.transform,patternId:`pattern-${f.rfId}`});function _q({id:f,variant:u=o_.Dots,gap:_=20,size:y,lineWidth:$=1,offset:l=0,color:j,bgColor:J,style:F,className:A,patternClassName:U}){let z=d.useRef(null),{transform:W,patternId:K}=mf(QT,A0),q=y||FT[u],E=u===o_.Dots,O=u===o_.Cross,G=Array.isArray(_)?_:[_,_],H=[G[0]*W[2]||1,G[1]*W[2]||1],Z=q*W[2],V=Array.isArray(l)?l:[l,l],L=O?[Z,Z]:H,M=[V[0]*W[2]||1+L[0]/2,V[1]*W[2]||1+L[1]/2],N=`${K}${f?f:""}`;return o.jsxs("svg",{className:Y0(["react-flow__background",A]),style:{...F,...c5,"--xy-background-color-props":J,"--xy-background-pattern-color-props":j},ref:z,"data-testid":"rf__background",children:[o.jsx("pattern",{id:N,x:W[0]%H[0],y:W[1]%H[1],width:H[0],height:H[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${M[0]},-${M[1]})`,children:E?o.jsx(JT,{radius:Z/2,className:U}):o.jsx(jT,{dimensions:L,lineWidth:$,variant:u,className:U})}),o.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${N})`})]})}_q.displayName="Background";var yq=d.memo(_q);function AT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:o.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function UT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:o.jsx("path",{d:"M0 0h32v4.2H0z"})})}function WT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:o.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 zT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:o.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 GT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:o.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 v5({children:f,className:u,..._}){return o.jsx("button",{type:"button",className:Y0(["react-flow__controls-button",u]),..._,children:f})}var KT=(f)=>({isInteractive:f.nodesDraggable||f.nodesConnectable||f.elementsSelectable,minZoomReached:f.transform[2]<=f.minZoom,maxZoomReached:f.transform[2]>=f.maxZoom,ariaLabelConfig:f.ariaLabelConfig});function $q({style:f,showZoom:u=!0,showFitView:_=!0,showInteractive:y=!0,fitViewOptions:$,onZoomIn:l,onZoomOut:j,onFitView:J,onInteractiveChange:F,className:A,children:U,position:z="bottom-left",orientation:W="vertical","aria-label":K}){let q=W0(),{isInteractive:E,minZoomReached:O,maxZoomReached:G,ariaLabelConfig:H}=mf(KT,A0),{zoomIn:Z,zoomOut:V,fitView:L}=SF(),M=()=>{Z(),l?.()},N=()=>{V(),j?.()},D=()=>{L($),J?.()},x=()=>{q.setState({nodesDraggable:!E,nodesConnectable:!E,elementsSelectable:!E}),F?.(!E)};return o.jsxs(I5,{className:Y0(["react-flow__controls",W==="horizontal"?"horizontal":"vertical",A]),position:z,style:f,"data-testid":"rf__controls","aria-label":K??H["controls.ariaLabel"],children:[u&&o.jsxs(o.Fragment,{children:[o.jsx(v5,{onClick:M,className:"react-flow__controls-zoomin",title:H["controls.zoomIn.ariaLabel"],"aria-label":H["controls.zoomIn.ariaLabel"],disabled:G,children:o.jsx(AT,{})}),o.jsx(v5,{onClick:N,className:"react-flow__controls-zoomout",title:H["controls.zoomOut.ariaLabel"],"aria-label":H["controls.zoomOut.ariaLabel"],disabled:O,children:o.jsx(UT,{})})]}),_&&o.jsx(v5,{className:"react-flow__controls-fitview",onClick:D,title:H["controls.fitView.ariaLabel"],"aria-label":H["controls.fitView.ariaLabel"],children:o.jsx(WT,{})}),y&&o.jsx(v5,{className:"react-flow__controls-interactive",onClick:x,title:H["controls.interactive.ariaLabel"],"aria-label":H["controls.interactive.ariaLabel"],children:E?o.jsx(GT,{}):o.jsx(zT,{})}),U]})}$q.displayName="Controls";var lq=d.memo($q);function ZT({id:f,x:u,y:_,width:y,height:$,style:l,color:j,strokeColor:J,strokeWidth:F,className:A,borderRadius:U,shapeRendering:z,selected:W,onClick:K}){let{background:q,backgroundColor:E}=l||{},O=j||q||E;return o.jsx("rect",{className:Y0(["react-flow__minimap-node",{selected:W},A]),x:u,y:_,rx:U,ry:U,width:y,height:$,style:{fill:O,stroke:J,strokeWidth:F},shapeRendering:z,onClick:K?(G)=>K(G,f):void 0})}var qT=d.memo(ZT),HT=(f)=>f.nodes.map((u)=>u.id),DF=(f)=>f instanceof Function?f:()=>f;function ET({nodeStrokeColor:f,nodeColor:u,nodeClassName:_="",nodeBorderRadius:y=5,nodeStrokeWidth:$,nodeComponent:l=qT,onClick:j}){let J=mf(HT,A0),F=DF(u),A=DF(f),U=DF(_),z=typeof window>"u"||!!window.chrome?"crispEdges":"geometricPrecision";return o.jsx(o.Fragment,{children:J.map((W)=>o.jsx(OT,{id:W,nodeColorFunc:F,nodeStrokeColorFunc:A,nodeClassNameFunc:U,nodeBorderRadius:y,nodeStrokeWidth:$,NodeComponent:l,onClick:j,shapeRendering:z},W))})}function VT({id:f,nodeColorFunc:u,nodeStrokeColorFunc:_,nodeClassNameFunc:y,nodeBorderRadius:$,nodeStrokeWidth:l,shapeRendering:j,NodeComponent:J,onClick:F}){let{node:A,x:U,y:z,width:W,height:K}=mf((q)=>{let E=q.nodeLookup.get(f);if(!E)return{node:void 0,x:0,y:0,width:0,height:0};let O=E.internals.userNode,{x:G,y:H}=E.internals.positionAbsolute,{width:Z,height:V}=b1(O);return{node:O,x:G,y:H,width:Z,height:V}},A0);if(!A||A.hidden||!WF(A))return null;return o.jsx(J,{x:U,y:z,width:W,height:K,style:A.style,selected:!!A.selected,className:y(A),color:u(A),borderRadius:$,strokeColor:_(A),strokeWidth:l,shapeRendering:j,onClick:F,id:A.id})}var OT=d.memo(VT),XT=d.memo(ET),NT=200,LT=150,YT=(f)=>!f.hidden,BT=(f)=>{let u={x:-f.transform[0]/f.transform[2],y:-f.transform[1]/f.transform[2],width:f.width/f.transform[2],height:f.height/f.transform[2]};return{viewBB:u,boundingRect:f.nodeLookup.size>0?QF(y$(f.nodeLookup,{filter:YT}),u):u,rfId:f.rfId,panZoom:f.panZoom,translateExtent:f.translateExtent,flowWidth:f.width,flowHeight:f.height,ariaLabelConfig:f.ariaLabelConfig}},wT="react-flow__minimap-desc";function jq({style:f,className:u,nodeStrokeColor:_,nodeColor:y,nodeClassName:$="",nodeBorderRadius:l=5,nodeStrokeWidth:j,nodeComponent:J,bgColor:F,maskColor:A,maskStrokeColor:U,maskStrokeWidth:z,position:W="bottom-right",onClick:K,onNodeClick:q,pannable:E=!1,zoomable:O=!1,ariaLabel:G,inversePan:H,zoomStep:Z=1,offsetScale:V=5}){let L=W0(),M=d.useRef(null),{boundingRect:N,viewBB:D,rfId:x,panZoom:c,translateExtent:v,flowWidth:C,flowHeight:P,ariaLabelConfig:w}=mf(BT,A0),r=f?.width??NT,S=f?.height??LT,T=N.width/r,Y=N.height/S,R=Math.max(T,Y),m=R*r,p=R*S,n=V*R,_f=N.x-(m-N.width)/2-n,t=N.y-(p-N.height)/2-n,ff=m+n*2,Gf=p+n*2,zf=`${wT}-${x}`,jf=d.useRef(0),Wf=d.useRef();jf.current=R,d.useEffect(()=>{if(M.current&&c)return Wf.current=vK({domNode:M.current,panZoom:c,getTransform:()=>L.getState().transform,getViewScale:()=>jf.current}),()=>{Wf.current?.destroy()}},[c]),d.useEffect(()=>{Wf.current?.update({translateExtent:v,width:C,height:P,inversePan:H,pannable:E,zoomStep:Z,zoomable:O})},[E,O,H,Z,v,C,P]);let Vf=K?(g)=>{let[I,$f]=Wf.current?.pointer(g)||[0,0];K(g,{x:I,y:$f})}:void 0,Zf=q?d.useCallback((g,I)=>{let $f=L.getState().nodeLookup.get(I).internals.userNode;q(g,$f)},[]):void 0,h=G??w["minimap.ariaLabel"];return o.jsx(I5,{position:W,style:{...f,"--xy-minimap-background-color-props":typeof F==="string"?F:void 0,"--xy-minimap-mask-background-color-props":typeof A==="string"?A:void 0,"--xy-minimap-mask-stroke-color-props":typeof U==="string"?U:void 0,"--xy-minimap-mask-stroke-width-props":typeof z==="number"?z*R:void 0,"--xy-minimap-node-background-color-props":typeof y==="string"?y:void 0,"--xy-minimap-node-stroke-color-props":typeof _==="string"?_:void 0,"--xy-minimap-node-stroke-width-props":typeof j==="number"?j:void 0},className:Y0(["react-flow__minimap",u]),"data-testid":"rf__minimap",children:o.jsxs("svg",{width:r,height:S,viewBox:`${_f} ${t} ${ff} ${Gf}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":zf,ref:M,onClick:Vf,children:[h&&o.jsx("title",{id:zf,children:h}),o.jsx(XT,{onClick:Zf,nodeColor:y,nodeStrokeColor:_,nodeBorderRadius:l,nodeClassName:$,nodeStrokeWidth:j,nodeComponent:J}),o.jsx("path",{className:"react-flow__minimap-mask",d:`M${_f-n},${t-n}h${ff+n*2}v${Gf+n*2}h${-ff-n*2}z - M${D.x},${D.y}h${D.width}v${D.height}h${-D.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}jq.displayName="MiniMap";var eb=d.memo(jq),DT=(f)=>(u)=>f?`${Math.max(1/u.transform[2],1)}`:void 0,TT={[s_.Line]:"right",[s_.Handle]:"bottom-right"};function MT({nodeId:f,position:u,variant:_=s_.Handle,className:y,style:$=void 0,children:l,color:j,minWidth:J=10,minHeight:F=10,maxWidth:A=Number.MAX_VALUE,maxHeight:U=Number.MAX_VALUE,keepAspectRatio:z=!1,resizeDirection:W,autoScale:K=!0,shouldResize:q,onResizeStart:E,onResize:O,onResizeEnd:G}){let H=RZ(),Z=typeof f==="string"?f:H,V=W0(),L=d.useRef(null),M=_===s_.Handle,N=mf(d.useCallback(DT(M&&K),[M,K]),A0),D=d.useRef(null),x=u??TT[_];d.useEffect(()=>{if(!L.current||!Z)return;if(!D.current)D.current=pK({domNode:L.current,nodeId:Z,getStoreItems:()=>{let{nodeLookup:v,transform:C,snapGrid:P,snapToGrid:w,nodeOrigin:r,domNode:S}=V.getState();return{nodeLookup:v,transform:C,snapGrid:P,snapToGrid:w,nodeOrigin:r,paneDomNode:S}},onChange:(v,C)=>{let{triggerNodeChanges:P,nodeLookup:w,parentLookup:r,nodeOrigin:S}=V.getState(),T=[],Y={x:v.x,y:v.y},R=w.get(Z);if(R&&R.expandParent&&R.parentId){let m=R.origin??S,p=v.width??R.measured.width??0,n=v.height??R.measured.height??0,_f={id:R.id,parentId:R.parentId,rect:{width:p,height:n,...zF({x:v.x??R.position.x,y:v.y??R.position.y},{width:p,height:n},R.parentId,w,m)}},t=r5([_f],w,r,S);T.push(...t),Y.x=v.x?Math.max(m[0]*p,v.x):void 0,Y.y=v.y?Math.max(m[1]*n,v.y):void 0}if(Y.x!==void 0&&Y.y!==void 0){let m={id:Z,type:"position",position:{...Y}};T.push(m)}if(v.width!==void 0&&v.height!==void 0){let p={id:Z,type:"dimensions",resizing:!0,setAttributes:!W?!0:W==="horizontal"?"width":"height",dimensions:{width:v.width,height:v.height}};T.push(p)}for(let m of C){let p={...m,type:"position"};T.push(p)}P(T)},onEnd:({width:v,height:C})=>{let P={id:Z,type:"dimensions",resizing:!1,dimensions:{width:v,height:C}};V.getState().triggerNodeChanges([P])}});return D.current.update({controlPosition:x,boundaries:{minWidth:J,minHeight:F,maxWidth:A,maxHeight:U},keepAspectRatio:z,resizeDirection:W,onResizeStart:E,onResize:O,onResizeEnd:G,shouldResize:q}),()=>{D.current?.destroy()}},[x,J,F,A,U,z,E,O,G,q]);let c=x.split("-");return o.jsx("div",{className:Y0(["react-flow__resize-control","nodrag",...c,_,y]),ref:L,style:{...$,scale:N,...j&&{[M?"backgroundColor":"borderColor"]:j}},children:l})}var fh=d.memo(MT);var X=fy.default.createElement,{useEffect:c1}=fy.default,Bu=fy.default.useState,e_=fy.default.useRef,Bl=[{id:"in-left",side:"left",position:Uf.Left,style:{top:"50%"}},{id:"in-top-left",side:"top",slot:"left",slotIndex:-1,position:Uf.Top,style:{left:"28%"}},{id:"in-top-mid",side:"top",slot:"mid",slotIndex:0,position:Uf.Top,style:{left:"50%"}},{id:"in-top-right",side:"top",slot:"right",slotIndex:1,position:Uf.Top,style:{left:"72%"}},{id:"in-bottom-left",side:"bottom",slot:"left",slotIndex:-1,position:Uf.Bottom,style:{left:"28%"}},{id:"in-bottom-mid",side:"bottom",slot:"mid",slotIndex:0,position:Uf.Bottom,style:{left:"50%"}},{id:"in-bottom-right",side:"bottom",slot:"right",slotIndex:1,position:Uf.Bottom,style:{left:"72%"}}],Xl=[{id:"out-right",position:Uf.Right,style:{top:"50%"}}],Jq=["#4eb7a8","#d7a13a","#69aee8","#e0835f","#b7d86b","#d98bd2","#5fc6bf"],U$=236,W$=88,Fq=15000,ST=10,PF=96,h1=72,CF=64,Qq=12;function p5(){return typeof document>"u"||document.visibilityState!=="hidden"}function Aq(f,u){let _=Number.parseFloat(String(f||""));return Number.isFinite(_)?_/100:u}function rT(f,u,_){let y=String(f.side||"");if(y!=="top"&&y!=="bottom")return 0;let $=Number(f.slotIndex||0),l=y==="top"?"in-top-mid":"in-bottom-mid",j=u.get(f.id)||0,J=u.get(l)||0;if($===0)return J===0?-26:28+j*74;let F=_===0?Math.abs($)*2:Math.sign(_)===Math.sign($)?-3:3;if(J>0&&j===0)return-14+F;return 8+j*74+F}function m5(f){let u=f.filter((l,j)=>{let J=f[j-1];return!J||Math.abs(J.x-l.x)>0.5||Math.abs(J.y-l.y)>0.5});if(u.length<2)return"";let _=`M ${u[0].x},${u[0].y}`,y=u[0];for(let l=1;l0.5||Math.abs(W.y-y.y)>0.5)_+=` L ${W.x},${W.y}`;_+=` Q ${J.x},${J.y} ${K.x},${K.y}`,y=K}let $=u[u.length-1];return`${_} L ${$.x},${$.y}`}function Sq(f,u,_,y,$,l,j=""){let J=_>=f,F=Math.max(1,Math.abs(_-f)),A=Math.abs(y-u),U=Math.max(34,Math.min(118,F*0.26)),z=Math.min(280,Math.abs(l));if(J&&$===Uf.Left&&z<4&&A<28&&F<420)return`M ${f},${u} C ${f+U},${u} ${_-U},${y} ${_},${y}`;if(J&&$===Uf.Left&&(j==="direct-forward-left"||F<=260&&A<=210)){let G=Math.max(42,Math.min(140,F*0.48)),H=Math.max(-28,Math.min(28,l*0.18));return`M ${f},${u} C ${f+G},${u+H} ${_-G},${y} ${_},${y}`}if(J){let G=f+U;if($===Uf.Top||$===Uf.Bottom){let V=$===Uf.Top?-1:1,L=y+V*(54+z*0.42);return m5([{x:f,y:u},{x:G,y:u},{x:G+Math.min(120,F*0.18),y:L},{x:_,y:L},{x:_,y:y+V*34},{x:_,y}])}let H=_-U,Z=(u+y)/2+l;return m5([{x:f,y:u},{x:G,y:u},{x:G+Math.min(110,F*0.16),y:Z},{x:H-Math.min(90,F*0.12),y:Z},{x:H,y},{x:_,y}])}let q=$===Uf.Bottom?1:$===Uf.Top?-1:l>=0?1:-1,E=Math.max(f,_)+92+Math.min(180,z*0.52),O=q<0?Math.min(u,y)-84-z*0.62:Math.max(u,y)+84+z*0.62;if($===Uf.Top||$===Uf.Bottom)return m5([{x:f,y:u},{x:f+U,y:u},{x:E,y:O},{x:_,y:O},{x:_,y:y+q*38},{x:_,y}]);return m5([{x:f,y:u},{x:f+U,y:u},{x:E,y:O},{x:_-U,y:O},{x:_-U,y},{x:_,y}])}function PT({data:f}){return X("div",{className:"pipeline-flow-node-body"},Bl.map((u)=>X(sy,{key:u.id,id:u.id,type:"target",position:u.position,isConnectable:!1,className:`pipeline-flow-handle input ${u.side} slot-${u.slot||"mid"}`,style:u.style})),Xl.map((u)=>X(sy,{key:u.id,id:u.id,type:"source",position:u.position,isConnectable:!1,className:"pipeline-flow-handle output right",style:u.style})),f?.label)}function CT({id:f,sourceX:u,sourceY:_,targetX:y,targetY:$,targetPosition:l,markerEnd:j,markerStart:J,style:F,data:A}){let U=Number(A?.laneOffset||0),z=Sq(u,_,y,$,l,U,String(A?.routeMode||""));return X(A$,{id:f,path:z,markerEnd:j,markerStart:J,style:F,interactionWidth:28})}var RT={pipelineCurve:CT},xT={pipelineNode:PT};function z0(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return u.toLocaleString("zh-CN",{hour12:!1})}function u2(f){return f.toLocaleTimeString("zh-CN",{hour12:!1})}function n5(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return u2(u)}function $1(f){let u=Number(f);if(!Number.isFinite(u)||u<0)return"--";let _=Math.round(u/1000);if(_<60)return`${_}s`;if(_<3600)return`${Math.floor(_/60)}m ${_%60}s`;return`${Math.floor(_/3600)}h ${Math.floor(_%3600/60)}m`}function RF(f){let u=Number(f);if(!Number.isFinite(u))return"--";return u.toLocaleString("zh-CN")}function Uq(f){let u=Number(f);if(!Number.isFinite(u))return"--";return`${Math.round(Math.max(0,Math.min(1,u))*100)}%`}function Nf(f){return typeof f==="object"&&f!==null&&!Array.isArray(f)}function Ef(f){return Array.isArray(f)?f:[]}function Pf(f){if(!f)return null;let u=new Date(f);return Number.isNaN(u.getTime())?null:u.getTime()}function wl(f){return Number.isFinite(Number(f))?new Date(Number(f)).toISOString():""}function Ml(...f){for(let u of f){let _=Pf(u);if(_!==null)return new Date(_).toISOString()}return""}function sF(...f){let u=f.map(Pf).filter((_)=>_!==null);return u.length>0?new Date(Math.max(...u)).toISOString():""}function oF(f){return["succeeded","failed","skipped","cancelled","canceled","completed"].includes(String(f||"").toLowerCase())}function rq(f){let u=Rq(f).toLowerCase();return["running","active","in-progress","in_progress"].includes(u)}function Wq(f,u="status"){return f.reduce((_,y)=>{let $=String(y?.[u]||"unknown").toLowerCase();return _[$]=(_[$]||0)+1,_},{})}function Pq(f){if(!f||typeof f!=="string")return null;try{let u=JSON.parse(f);return Nf(u)?u:null}catch{return null}}function xF(f){let u=f.map(Pq).filter((l)=>Boolean(l)),_=u.flatMap((l)=>[l.timestamp,l.createdAt,l.updatedAt]).filter(Boolean),y=sF(..._),$=Array.from(new Set(u.map((l)=>String(l.event||l.action||l.type||"")).filter(Boolean))).slice(0,3);return{total:f.length,parsed:u.length,lastAt:y,eventKinds:$}}function t5(f){if(f===null||f===void 0)return"--";if(typeof f==="boolean")return f?"是":"否";if(typeof f==="number")return String(f);if(typeof f==="string")return f.length>80?`${f.slice(0,77)}...`:f;if(Array.isArray(f))return`${f.length} 项`;if(typeof f==="object")return`${Object.keys(f).length} 字段`;return String(f)}function Cq(f,u=280){if(f===null||f===void 0)return"";let y=(typeof f==="string"?f:String(f)).replace(/\r\n/gu,` -`).trim();return y.length>u?`${y.slice(0,Math.max(0,u-1))}...`:y}function Rq(f){if(typeof f==="string")return f;if(Nf(f))return String(f.status||f.state||f.phase||"unknown");return"unknown"}function vT(f){return f.filter((u)=>u&&u.value!==void 0&&u.value!==null&&String(u.value)!=="")}function pF({items:f}){let u=vT(Ef(f));return X("div",{className:"pipeline-kv-grid"},u.map((_)=>X("span",{key:_.label},X("b",null,_.label),X("span",null,_.value))))}function aF({items:f}){let u=Ef(f).map((_)=>String(_||"")).filter(Boolean);if(u.length===0)return null;return X("div",{className:"pipeline-chip-row"},u.map((_,y)=>X("span",{key:`${y}-${_}`},_)))}function mF(f,u){let _=String(u?.procedureRunId||""),y=Ef(f?.procedureRuns);return y.find(($)=>String(l1($))===_)||y.at(-1)||null}function bT(f,u){let _=String(u||"");if(!_)return null;return Ef(f?.procedureRuns).find((y)=>l1(y)===_)||null}function vF(f){return Ef(f?.attempts).length}function zq(f){return Ef(f?.attempts).reduce((u,_)=>u+_2(_).length,0)}function _2(f){return Ef(f?.opencodeMessages?.steps).filter(Nf)}function xq(f){let u=String(f?.status||"").toLowerCase();if(["error","failed","failure"].includes(u))return"failed";if(["completed","succeeded","success"].includes(u))return"succeeded";if(["running","started","in_progress"].includes(u))return"running";return"unknown"}function hT(f,u){let _=kF(f.map((l)=>l?.agent)).slice(0,3),y=kF(f.map((l)=>l?.model)).slice(0,3),$=u.length<=2?u.map((l)=>`session ${l}`):[`sessions ${u.length}`,...u.slice(0,2).map((l)=>`session ${l}`)];return[..._.map((l)=>`agent ${l}`),...y.map((l)=>`model ${l}`),...$]}function Nl(f,u=0){return String(f?.messageId||f?.index||"")||`step-${u}`}function IT({steps:f,sessionIds:u,sessionFacts:_,matchedStepKey:y}){let $=Ef(f),l=$.findIndex((O,G)=>Nl(O,G)===y),j=l>=0?$[l]:null,J=$.flatMap((O)=>[Pf(O?.createdAt),Pf(O?.completedAt)]).filter((O)=>O!==null),F=J.length>0?Math.min(...J):null,A=J.length>0?Math.max(...J):null,U=F!==null&&A!==null?Math.max(0,A-F):null,z=$.reduce((O,G)=>O+Ef(G?.parts).filter((H)=>String(H?.type||"").toLowerCase()==="tool").length,0),W=$.reduce((O,G)=>O+Ef(G?.parts).filter((H)=>["text","reasoning"].includes(String(H?.type||"").toLowerCase())).length,0),K=$.reduce((O,G)=>O+Ef(G?.parts).filter((H)=>String(H?.type||"").toLowerCase()==="tool"&&xq(H)==="failed").length,0),q=[`${$.length} steps`,`${u.length} sessions`,`${W} messages`,`${z} tools`,U!==null?`duration ${$1(U)}`:"",K>0?`${K} failed tools`:""].filter(Boolean),E=j?[`Step ${j?.index??l+1}`,String(j?.role||"role --"),j?.model?`model ${j.model}`:"",j?.finish?`finish ${j.finish}`:"",j?.durationMs!==void 0&&j?.durationMs!==null?`duration ${$1(j.durationMs)}`:""].filter(Boolean):[];return X("section",{className:"pipeline-trace-timeline","data-testid":"pipeline-step-timeline"},X("div",{className:"pipeline-trace-head"},X("div",null,X("b",null,"OpenCode Trace"),X("span",null,"Trace 使用 Codex Queue 统一样式展示完整 agent loop;Pipeline 旧 step/message/tool 卡片样式已废弃。")),X("div",{className:"pipeline-trace-session-head","data-testid":"pipeline-step-timeline-session"},X("span",null,q.join(" / ")||"Trace"),_.length>0?X(aF,{items:_}):null)),j?X("div",{className:"pipeline-trace-focus","data-testid":"pipeline-trace-matched-step"},X("span",{className:"codex-output-channel"},"Matched"),X("strong",null,`Gantt selection -> ${E.join(" / ")}`),X("time",null,`${n5(j?.createdAt)} -> ${n5(j?.completedAt)}`)):null,X(X4,{port:Bz,input:$,className:"codex-transcript pipeline-trace",testId:"pipeline-opencode-step-trace",emptyText:"暂无 OpenCode Trace 输出",keepRecentToolCalls:3}))}function Ll(f){return Ef(f).flatMap((u)=>{if(Nf(u))return[u];let _=Pq(u);return _?[_]:[]})}function O1(f){return String(f?.event||f?.action||f?.requestedAction||f?.type||"").toLowerCase()}function oy(f){return Ml(f?.timestamp,f?.createdAt,f?.updatedAt,f?.startedAt,f?.finishedAt)}function cT(f){return Pf(oy(f))}function y2(f){return String(f?.attempt||f?.id||"")}function kF(f){let u=new Set,_=[];for(let y of f){let $=String(y||"");if(!$||u.has($))continue;u.add($),_.push($)}return _}function Gq(f){switch(String(f||"").toLowerCase()){case"monitor":return"monitor";case"webui":return"webui";case"cli":return"cli";case"system":return"runner";default:return String(f||"--")}}function ay(f){return String(f?.requestedAction||f?.action||"").toLowerCase()}function Yl(f){switch(ay(f)){case"guide":return"引导";case"modify":return"修改";case"approve":return"审核通过";case"restart":return"重启";case"redo":return"重做";default:return String(f?.requestedAction||f?.action||"控制")}}function Kq(f){switch(O1(f)){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`${Yl(f)} 已发起`;case"control-command-applied":return`${Yl(f)} 已生效`;case"control-command-ignored":return`${Yl(f)} 已忽略`;default:return String(f?.event||f?.action||f?.requestedAction||"event")}}function Zq(f){return Cq(f?.promptPreview||f?.reasonPreview||f?.prompt||f?.reason||"",240)}function pT(f){let u=String(f?.prompt||""),_=String(f?.reason||f?.restartReason||""),y=u?"":String(f?.promptPreview||""),$=_?"":String(f?.reasonPreview||"");return[u||y?{label:u?"prompt":"prompt preview",value:u||y}:null,_||$?{label:_?"reason":"reason preview",value:_||$}:null,Ef(f?.resetNodeIds).length>0?{label:"reset nodes",value:Ef(f.resetNodeIds).join(", ")}:null,Ef(f?.runningResetNodeIds).length>0?{label:"interrupted running nodes",value:Ef(f.runningResetNodeIds).join(", ")}:null,Ef(f?.interruptedProcedureRunIds).length>0?{label:"interrupted procedures",value:Ef(f.interruptedProcedureRunIds).join(", ")}:null,f?.interruptedProcedureRunId?{label:"interrupted procedure",value:String(f.interruptedProcedureRunId)}:null].filter(Boolean)}function bF(f){let u=_2(f),_=u.map((F)=>Pf(F?.createdAt)).filter((F)=>F!==null),y=u.map((F)=>Pf(F?.completedAt)??Pf(F?.createdAt)).filter((F)=>F!==null),$=Ll(f?.controlEventRecords).map((F)=>cT(F)).filter((F)=>F!==null),l=Ef(f?.assistantOutputs).map((F)=>Pf(F?.updatedAt)).filter((F)=>F!==null),j=_[0]??$[0]??l[0]??null,J=y.at(-1)??$.at(-1)??l.at(-1)??j;return{startMs:j,endMs:J}}function mT(f,u,_,y,$=""){let l=Ef(f?.procedureRuns).filter((J)=>$2(J,u)===_);if(l.length===0)return null;if($){let J=l.find((F)=>l1(F)===$);if(J)return J}if(y===null)return l.at(-1)||null;let j=l.find((J)=>{let F=Pf(k5(J,f)),A=Pf(i5(J,f))??F;return F!==null&&A!==null&&y>=F-1000&&y<=A+1000});if(j)return j;return l.slice().sort((J,F)=>{let A=Pf(k5(J,f))??y,U=Pf(i5(J,f))??A,z=Pf(k5(F,f))??y,W=Pf(i5(F,f))??z,K=Math.min(Math.abs(A-y),Math.abs(U-y)),q=Math.min(Math.abs(z-y),Math.abs(W-y));return K-q})[0]||null}function vq(f,u){let _=Ef(f?.attempts).filter(Nf);if(_.length===0)return null;let y=String(u?.attempt||"");if(y){let j=_.find((J)=>y2(J)===y);if(j)return j}let $=Number.isFinite(Number(u?.ms))?Number(u.ms):null;if($===null)return _.at(-1)||null;let l=_.find((j)=>{let J=bF(j);return Number.isFinite(J.startMs)&&Number.isFinite(J.endMs)&&$>=Number(J.startMs)-1000&&$<=Number(J.endMs)+1000});if(l)return l;return _.slice().sort((j,J)=>{let F=bF(j),A=bF(J),U=Math.min(Math.abs(Number(F.startMs??$)-$),Math.abs(Number(F.endMs??$)-$)),z=Math.min(Math.abs(Number(A.startMs??$)-$),Math.abs(Number(A.endMs??$)-$));return U-z})[0]||_.at(-1)||null}function bq(f,u){let _=_2(f);if(_.length===0)return{step:null,stepIndex:-1,stepKey:""};if(u===null){let l=_[0];return{step:l,stepIndex:0,stepKey:Nl(l,0)}}for(let l=0;l<_.length;l+=1){let j=_[l],J=Pf(j?.createdAt)??Pf(j?.completedAt),F=Pf(j?.completedAt)??J;if(J!==null&&F!==null&&u>=J-1000&&u<=F+1000)return{step:j,stepIndex:l,stepKey:Nl(j,l)}}let y=_.findIndex((l)=>{let j=Pf(l?.createdAt)??Pf(l?.completedAt);return j!==null&&j>=u});if(y>=0){let l=_[y];return{step:l,stepIndex:y,stepKey:Nl(l,y)}}let $=Math.max(0,_.length-1);return{step:_[$],stepIndex:$,stepKey:Nl(_[$],$)}}function kT(f,u){let _=String(u?.runId||f?.runId||"");if(String(u?.mode||"")==="interval"){let A=u?.interval||{},U=mF(f,A)||A.raw||{};return{mode:"interval",runId:_,interval:A,marker:null,nodeId:String(A?.nodeId||$2(U,_)||""),procedure:U,attempt:null,matchedStep:null,matchedStepIndex:-1,matchedStepKey:""}}let y=Nf(u?.marker)?u.marker:{},$=Number.isFinite(Number(y?.ms))?Number(y.ms):null,l=String(y?.nodeId||""),j=l?mT(f,_,l,$,String(y?.procedureRunId||"")):null,J=j?vq(j,y):null,F=J?bq(J,$):{step:null,stepIndex:-1,stepKey:""};return{mode:"event",runId:_,interval:null,marker:y,nodeId:l,procedure:j,attempt:J,matchedStep:F.step,matchedStepIndex:F.stepIndex,matchedStepKey:F.stepKey}}function iT({procedure:f,matchedStepKey:u="",matchedAttemptId:_=""}){let y=Ef(f?.attempts);if(y.length===0)return X(cu,{title:"暂无 attempt 详情",text:"当前 procedure 还没有可展示的 attempt / OpenCode Trace;若刚点击甘特线,请等待 node 详情抓取完成。"});return y.map(($,l)=>{let j=$?.opencodeMessages||{},J=_2($),F=Ef(j.sessionIds).map((W)=>String(W)).filter(Boolean),A=hT(J,F),U=y2($)||`attempt-${l+1}`,z=J.reduce((W,K)=>W+Ef(K?.parts).filter((q)=>String(q?.type||"").toLowerCase()==="tool"&&xq(q)==="failed").length,0);return X("article",{key:U,className:`pipeline-attempt-card ${_===U?"matched":""}`},X("div",{className:"pipeline-attempt-head"},X("div",null,X("strong",null,U),X("span",null,j.source||"opencode")),X("div",{className:"pipeline-attempt-badges"},X("span",null,`${J.length} steps`),X("span",null,`${j.toolCallCount??"--"} tools`),z>0?X("span",{className:"danger"},`${z} failed`):null)),X(pF,{items:[{label:"messages",value:j.messageCount??"--"},{label:"steps",value:j.stepCount??J.length},{label:"tools",value:j.toolCallCount??"--"},{label:"updated",value:z0(j.updatedAt)},{label:"sessions",value:F.join(", ")||"--"}]}),J.length===0?X("p",{className:"muted paragraph"},"当前 attempt 尚未返回 OpenCode Trace;请确认 D601 pipeline-control 已重建并重新抓取。"):X(IT,{steps:J,sessionIds:F,sessionFacts:A,matchedStepKey:u}))})}function hF(f,u){return`${f}::${u}`}function s5(f,u,_){if(!Nf(f))return null;return String(f.runId||"")===u&&String(f.nodeId||"")===_?f:null}function gT(f,u){let _=Nf(f)?f:{};if(!Nf(u))return _;let y=Ef(u.attempts),$=Ef(_.attempts);return{..._,...u,attempts:y.length>0?y:$}}function nT(f,u,_,y){if(!s5(u,_,y))return f;let $=Ef(u.procedureRuns),l=Nf(f)?f:{};return{...l,...u,controlCommands:Ef(u.controlCommands).length>0?u.controlCommands:l.controlCommands,controlEvents:Ef(u.controlEvents).length>0?u.controlEvents:l.controlEvents,procedureRuns:$.length>0?$:l.procedureRuns}}function tT({selection:f,runDetails:u,nodeDetails:_,nodeDetailsState:y,onRaw:$,onCollapse:l}){if(!f?.mode)return X("aside",{className:"pipeline-gantt-detail-panel empty","data-testid":"pipeline-gantt-detail-panel"},X("div",{className:"pipeline-gantt-detail-head"},X("div",null,X("span",{className:"panel-eyebrow"},"Gantt Detail"),X("h3",null,"未选择元素")),X("button",{type:"button",className:"ghost-btn mini",onClick:l,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起")),X(cu,{title:"选择一条执行线或一个控制点",text:"点击甘特图中的 node 执行线、prompt 点或控制点,在这里查看结构化过程和 OpenCode step。"}));let j=String(f?.runId||""),J=String(f?.interval?.nodeId||f?.marker?.nodeId||""),F=u?.runId===j?u.details:null,A=s5(_,j,J),U=String(y?.runId||"")===j&&String(y?.nodeId||"")===J,z=nT(F,A,j,J),W=(String(u?.runId||"")!==j||Boolean(u?.loading))&&!z,K=String(u?.runId||"")===j?String(u?.error||""):"",q=U?String(y?.error||""):"",E=z?kT(z,f):null,O=E?.interval||f?.interval||null,G=E?.marker||f?.marker||null,H=String(O?.procedureRunId||G?.procedureRunId||""),Z=A?bT(A,H)||mF(A,O||{procedureRunId:H}):null,V=E?.procedure||(z?mF(z,O||{procedureRunId:H}):null)||O?.raw||{};if(Z&&(vF(V)===0||zq(Z)>=zq(V)))V=gT(V,Z);let L=E?.attempt||null,M=String(E?.matchedStepKey||"");if(!L&&G&&vF(V)>0)L=vq(V,G),M=String(bq(L,Number.isFinite(Number(G?.ms))?Number(G.ms):null).stepKey||"");let N=y2(L),D=vF(V)>0,x=U&&Boolean(y?.loading)&&!D,c=Boolean(W||x),v=[D?"":K,q].filter(Boolean).join(" / "),C=U&&y?.fetchedAt?y.fetchedAt:u?.fetchedAt,P=Rq(V?.status||O?.status||G?.status||G?.event),w=f?.mode==="event"?G?.label||Kq(G?.raw||G)||"event":E?.nodeId||O?.nodeId||"node",r=G?pT(G?.raw||G):[],S=G?[O1(G?.raw||G)?`event ${O1(G?.raw||G)}`:"",G?.promptEvent?`prompt ${G.promptEvent}`:"",G?.action?`action ${G.action}`:"",G?.sourceKind?`source ${Gq(G.sourceKind)}`:"",G?.sourceNodeId?`from ${G.sourceNodeId}`:"",G?.targetNodeId?`to ${G.targetNodeId}`:"",G?.snapReason?`draw ${G.snapReason}`:""].filter(Boolean):[];return X("aside",{className:"pipeline-gantt-detail-panel","data-testid":"pipeline-gantt-detail-panel"},X("div",{className:"pipeline-gantt-detail-head"},X("div",null,X("span",{className:"panel-eyebrow"},f?.mode==="event"?"Gantt Event Detail":"Gantt Line Detail"),X("h3",null,w)),X("div",{className:"pipeline-gantt-detail-head-actions"},X(uy,{status:P},P),X("button",{type:"button",className:"ghost-btn mini",onClick:l,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起"))),G?X("article",{className:"pipeline-event-card"},X("div",{className:"pipeline-event-card-head"},X("strong",null,G?.label||Kq(G?.raw||G)),X(aF,{items:S})),X(pF,{items:[{label:"event time",value:z0(G?.timestampIso||G?.timestamp||"--")},G?.snapped?{label:"drawn time",value:z0(G?.renderedTimestampIso||G?.ms)}:null,{label:"node",value:G?.nodeId||"--"},{label:"procedure",value:G?.procedureRunId||l1(V)||"--"},{label:"attempt",value:G?.attempt||N||"--"},{label:"source kind",value:G?.sourceKind?Gq(G.sourceKind):"--"},{label:"source node",value:G?.sourceNodeId||"--"},{label:"target node",value:G?.targetNodeId||"--"},{label:"command",value:G?.commandId||G?.eventId||"--"},G?.snapReason?{label:"placement",value:G.snapReason}:null]}),r.length>0?X("div",{className:"pipeline-event-blocks"},r.map((T,Y)=>X("section",{key:`${T.label}-${Y}`,className:"pipeline-event-text-block"},X("b",null,T.label),X("p",null,T.value)))):null,Zq(G?.raw||G)?X("p",{className:"pipeline-text-preview"},Zq(G?.raw||G)):null):null,X(pF,{items:[{label:"epoch",value:j||O?.runId||"--"},{label:"node",value:E?.nodeId||O?.nodeId||G?.nodeId||"--"},{label:"procedure",value:O?.procedureRunId||G?.procedureRunId||l1(V)||"--"},{label:"started",value:z0(O?.startedAt||V?.startedAt)},{label:"finished",value:z0(O?.finishedAt||V?.finishedAt)},{label:"duration",value:$1(O?.durationMs||V?.durationMs)},{label:"fetched",value:C?u2(C):"--"},E?.matchedStep?{label:"matched step",value:`Step ${E.matchedStep.index??E.matchedStepIndex+1}`}:null]}),c?X("div",{className:"form-success"},x?"正在抓取该 node 的 attempt / Trace...":"正在抓取 epoch 执行过程..."):null,X(H0,{error:v}),X("div",{className:"pipeline-gantt-detail-actions"},X(X1,{title:`Procedure ${O?.procedureRunId||G?.procedureRunId||E?.nodeId||"node"}`,data:V,onOpen:$,testId:"raw-pipeline-gantt-procedure"}),G?X(X1,{title:`Pipeline event ${G?.id||G?.commandId||G?.eventId||E?.nodeId||"event"}`,data:G?.raw||G,onOpen:$,testId:"raw-pipeline-gantt-event"}):null,z?X(X1,{title:`Pipeline run ${j||"--"}`,data:z,onOpen:$,testId:"raw-pipeline-gantt-node-details"}):null),!c&&!l1(V)&&!G?X(cu,{title:"暂无过程详情",text:"当前选择还没有可匹配的 procedure 运行记录。"}):null,!c&&l1(V)?X(iT,{procedure:V,matchedStepKey:M,matchedAttemptId:N}):null)}function sT({value:f}){let _=String(f||"--").split(/([_-])/u);return X(fy.default.Fragment,null,_.map((y,$)=>y==="-"||y==="_"?X(fy.default.Fragment,{key:$},y,X("wbr",null)):X(fy.default.Fragment,{key:$},y)))}async function a_(f,u={}){return wf(f,{invalidJsonPrefix:"Pipeline 返回了无效 JSON",...u})}function uy({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return X("span",{className:`status-badge ${_}`},u||f||"unknown")}function Hu({label:f,value:u,hint:_,tone:y}){return X("article",{className:`metric-card ${y||""}`},X("div",{className:"metric-label"},f),X("div",{className:"metric-value"},u),X("div",{className:"metric-hint"},_))}function I1({title:f,eyebrow:u,actions:_,children:y,className:$}){return X("section",{className:`panel ${$||""}`},X("div",{className:"panel-head"},X("div",null,u?X("p",{className:"panel-eyebrow"},u):null,X("h2",null,f)),_?X("div",{className:"panel-actions"},_):null),X("div",{className:"panel-body"},y))}function X1({title:f,data:u,onOpen:_,testId:y}){return X("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function y1({title:f,subtitle:u,facts:_,data:y,onRaw:$,testId:l}){let j=Ef(_).map((J)=>String(J||"")).filter(Boolean);return X("article",{className:"pipeline-evidence-row"},X("div",{className:"pipeline-evidence-main"},X("strong",null,f),u?X("span",null,u):null),X("div",{className:"pipeline-evidence-facts"},j.map((J,F)=>X("span",{key:`${F}-${J.slice(0,16)}`},J))),y!==void 0?X(X1,{title:f,data:y,onOpen:$,testId:l}):null)}function cu({title:f,text:u}){return X("div",{className:"empty-state"},X("strong",null,f),X("span",null,u))}function oT(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function aT(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function dT(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function eT(f){return{components:Array.isArray(f?.registry?.components)?f.registry.components:[],pipelines:Array.isArray(f?.pipelines)?f.pipelines:[],runs:Array.isArray(f?.runs)?f.runs:[]}}function qq(f,u,_){let y=f?._unidesk?.arrayLimits?.[u],$=Number(y?.originalLength);return Number.isFinite($)?$:_}function hq(f){if(!f||typeof f!=="object"||Array.isArray(f))return"--";return`${f.componentClass||"--"}/${f.id||"--"}`}function o5(f){if(!f||typeof f!=="object"||Array.isArray(f))return"";let u=String(f.componentClass||"").trim(),_=String(f.id||"").trim();return u&&_?`${u}/${_}`:""}function dF(f){return f?.config&&typeof f.config==="object"&&!Array.isArray(f.config)?f.config:{}}function Iq(f){let u=dF(f),_=Array.isArray(u.nodes)?u.nodes:Array.isArray(f?.nodes)?f.nodes:[],y=new Map;for(let j of _){let J=String(j?.id||j?.nodeId||"");if(J)y.set(J,{...j,id:J})}let $=eF(f),l=(j)=>{if(j&&!y.has(j))y.set(j,{id:j})};for(let j of fQ(f))Dl(j).forEach(l);for(let j of $)l(String(j?.from||j?.source||"")),l(String(j?.to||j?.target||""));return Array.from(y.values())}function eF(f){let u=dF(f);return Array.isArray(u.edges)?u.edges:Array.isArray(f?.edges)?f.edges:[]}function fQ(f){let u=dF(f);return Array.isArray(u.topologicalBatches)?u.topologicalBatches:Array.isArray(f?.topologicalBatches)?f.topologicalBatches:[]}function fM(f){let u=new Map;for(let _ of f){let y=o5(_);if(y)u.set(y,_);let $=Array.isArray(_?.refs)?_.refs:[];for(let l of $){let j=o5(l);if(j)u.set(j,_)}}return u}function Hq(f,u){let _=u.get(o5(f?.componentRef));if(_)return _;let y=o5({componentClass:f?.kind,id:f?.id});return y?u.get(y)||null:null}function Eq(f,u){let _=cq(f,u);return String(_?.status||"pending")}function cq(f,u){return(Array.isArray(f?.nodes)?f.nodes:[]).find((y)=>y?.nodeId===u||y?.id===u)||null}function uM(f){return f.reduce((u,_)=>{let y=String(_?.status||"unknown").toLowerCase();return u[y]=(u[y]||0)+1,u},{})}function _M(f){if(Array.isArray(f?.scorers))return f.scorers.filter(Nf);if(Array.isArray(f?.summary?.scorers))return f.summary.scorers.filter(Nf);if(Array.isArray(f?.artifact?.summary?.scorers))return f.artifact.summary.scorers.filter(Nf);return[]}function yM(f){if(Nf(f?.run))return f.run;if(Nf(f?.runSummary))return f.runSummary;return null}function $M(f,u){if(!Nf(f)&&!Nf(u))return null;if(!Nf(f))return u;if(!Nf(u))return f;return{...f,...u,request:Nf(f.request)||Nf(u.request)?{...Nf(f.request)?f.request:{},...Nf(u.request)?u.request:{}}:u.request??f.request,artifact:Nf(f.artifact)||Nf(u.artifact)?{...Nf(f.artifact)?f.artifact:{},...Nf(u.artifact)?u.artifact:{}}:u.artifact??f.artifact,summary:Nf(f.summary)||Nf(u.summary)?{...Nf(f.summary)?f.summary:{},...Nf(u.summary)?u.summary:{}}:u.summary??f.summary}}function a5(f){let u=_M(f),_=u.find((U)=>Nf(U?.score))||u[0]||null,y=Nf(_?.score)?_.score:{},$=Number(y.passed),l=Number(y.total),j=Number(y.ratio),J=Number.isFinite(j)?j:Number.isFinite($)&&Number.isFinite(l)&&l>0?$/l:null,F=J===null?null:Math.round(Math.max(0,Math.min(100,J<=1?J*100:J))),A=String(y.text||(Number.isFinite($)&&Number.isFinite(l)?`${$}/${l}`:""));return{scorer:_,scorers:u,score:y,passed:Number.isFinite($)?$:null,total:Number.isFinite(l)?l:null,percent:F,text:A}}function iF(f){let u=a5(f);return u.text||(u.scorers.length>0?String(u.scorer?.status||"pending"):"--")}function uQ(f){let u=a5(f);if(u.total>0&&u.passed===u.total)return"succeeded";if(u.total>0&&u.passed>0)return"running";if(u.scorers.length>0)return"failed";return"pending"}function lM(f){return Array.isArray(f?.items)?f.items.filter(Nf):[]}function jM({run:f}){let u=iF(f);return X("span",{className:`pipeline-score-badge ${uQ(f)}`},`score ${u}`)}function JM({run:f,onRaw:u}){let y=a5(f).scorers;if(!f)return X(cu,{title:"暂无评分",text:"选择一个 epoch 后会显示 scorer 结果。"});if(y.length===0)return X("div",{className:"pipeline-score-empty"},X("strong",null,"评分器等待中"),X("span",null,"DAG 完成后,Pipeline control backend 会把 scorer summary 追加到 run artifact,并通过 UniDesk 显示。"));return X("div",{className:"pipeline-score-board","data-testid":"pipeline-score-board"},y.map(($,l)=>{let j=a5({scorers:[$]}),J=lM($),F=j.percent??0;return X("article",{key:`${$.scorerId||$.component||l}`,className:`pipeline-score-card ${uQ({scorers:[$]})}`},X("div",{className:"pipeline-score-head"},X("div",null,X("span",null,$.scorerId||$.component||"scorer"),X("strong",null,j.text||$.status||"--")),X(uy,{status:$.status||"unknown"},$.status||"unknown")),X("div",{className:"pipeline-score-meter","aria-label":`score ${F}%`},X("span",{style:{width:`${F}%`}})),X("div",{className:"pipeline-score-facts"},X("span",null,`${F}%`),X("span",null,$.component||"--"),X("span",null,$.applicationCheckoutRef||"--")),J.length>0?X("div",{className:"pipeline-score-items"},J.map((A)=>X("span",{key:`${A.id||A.filter}`,className:`pipeline-score-item ${String(A.status||"").toLowerCase()}`,title:`${A.filter||"--"} / ran=${A.ran??"?"}`},X("b",null,A.id||"--"),X("small",null,A.status||"--")))):X("p",{className:"muted paragraph"},"当前 scorer 尚未返回 item 级结果。"),$.error?X("p",{className:"pipeline-score-error"},Cq($.error,360)):null,X("div",{className:"panel-actions inline-actions"},X(X1,{title:`Scorer ${$.scorerId||l}`,data:$,onOpen:u,testId:"raw-pipeline-score"})))}))}function FM(f){let u=f.reduce((_,y)=>{let $=String(y?.componentClass||"unknown");return _[$]=(_[$]||0)+1,_},{});return Object.entries(u).map(([_,y])=>({name:_,count:Number(y)})).sort((_,y)=>y.count-_.count||_.name.localeCompare(y.name))}function Dl(f){if(Array.isArray(f))return f.map((u)=>typeof u==="string"?u:String(u?.id||u?.nodeId||"")).filter(Boolean);if(Array.isArray(f?.nodes))return Dl(f.nodes);if(Array.isArray(f?.nodeIds))return Dl(f.nodeIds);return[]}function QM(f){return Nf(f?.instanceInputs?.monitor)?f.instanceInputs.monitor:{}}function pq(f,u){if(String(f?.kind||"").toLowerCase()!=="procedure")return!1;let _=QM(f);if(f?.instanceInputs?.monitorMode===!0||_.enabled===!0)return!0;let y=hq(f?.componentRef);return String(u?.id||u?.config?.id||y||"").toLowerCase().includes("monitor")}function AM(f){return f.filter((u)=>pq(u)).map((u)=>String(u?.id||"")).filter(Boolean)}function UM(f,u){if(u.length===0)return f;let _=new Set(u),y=u.filter(($)=>f.includes($));if(y.length===0)return f;return[...y,...f.filter(($)=>!_.has($))]}function WM(f,u){if(u.length===0)return f;let _=new Set(u),y=u.filter((l)=>f.some((j)=>j.includes(l)));if(y.length===0)return f;let $=f.map((l)=>l.filter((j)=>!_.has(j))).filter((l)=>l.length>0);return[y,...$]}function zM(f,u,_){let $=fQ(f).map(Dl).filter((W)=>W.length>0);if($.length>0)return $;let l=u.map((W)=>String(W?.id||"")).filter(Boolean),j=new Set(l),J=new Map(l.map((W)=>[W,0])),F=new Map(l.map((W)=>[W,[]]));for(let W of _){let K=String(W?.from||W?.source||""),q=String(W?.to||W?.target||"");if(!j.has(K)||!j.has(q))continue;F.get(K)?.push(q),J.set(q,(J.get(q)||0)+1)}let A=new Map,U=l.filter((W)=>(J.get(W)||0)===0);for(let W of U)A.set(W,0);while(U.length>0){let W=U.shift(),K=(A.get(W)||0)+1;for(let q of F.get(W)||[])if(J.set(q,Math.max(0,(J.get(q)||0)-1)),A.set(q,Math.max(A.get(q)||0,K)),(J.get(q)||0)===0)U.push(q)}l.forEach((W)=>{if(!A.has(W))A.set(W,0)});let z=Math.max(0,...Array.from(A.values()));return Array.from({length:z+1},(W,K)=>l.filter((q)=>A.get(q)===K)).filter((W)=>W.length>0)}function GM(f,u,_){let $=fQ(f).map(Dl).filter((J)=>J.length>0),l=$.length>0?$.flatMap((J)=>J):(()=>{let J=u.map((E)=>String(E?.id||"")).filter(Boolean),F=new Set(J),A=_.filter((E)=>String(E?.edgeType||"").toLowerCase()!=="rework"),U=new Map(J.map((E)=>[E,0])),z=new Map(J.map((E)=>[E,[]]));for(let E of A){let O=String(E?.from||E?.source||""),G=String(E?.to||E?.target||"");if(!F.has(O)||!F.has(G))continue;z.get(O)?.push(G),U.set(G,(U.get(G)||0)+1)}let W=new Map,K=J.filter((E)=>(U.get(E)||0)===0);for(let E of K)W.set(E,0);while(K.length>0){let E=K.shift(),O=(W.get(E)||0)+1;for(let G of z.get(E)||[])if(U.set(G,Math.max(0,(U.get(G)||0)-1)),W.set(G,Math.max(W.get(G)||0,O)),(U.get(G)||0)===0)K.push(G)}J.forEach((E)=>{if(!W.has(E))W.set(E,0)});let q=Math.max(0,...Array.from(W.values()));return Array.from({length:q+1},(E,O)=>J.filter((G)=>W.get(G)===O)).flatMap((E)=>E)})(),j=new Set(l);for(let J of u){let F=String(J?.id||"");if(!F||j.has(F))continue;l.push(F),j.add(F)}return UM(l,AM(u))}function Vl(f){return`${f.source}->${f.target}-${f.index}`}function Vq(f,u,_){let y=Iq(f),$=eF(f),l=fM(_),j=new Map(y.map((P)=>[String(P?.id||""),P])),J=y.filter((P)=>pq(P,Hq(P,l))).map((P)=>String(P?.id||"")).filter(Boolean),F=WM(zM(f,y,$),J),A=[],U=new Map,z=330,W=122;F.forEach((P,w)=>{let r=P.length*122;P.forEach((S,T)=>{let Y=j.get(S)||{id:S},R=Hq(Y,l),m=Eq(u,S).toLowerCase(),p=String(Y.kind||R?.componentClass||"node").toLowerCase(),n=hq(Y.componentRef||R),_f=String(R?.config?.version||R?.version||""),t=String(R?.config?.description||R?.description||""),ff=T*122-Math.floor(r/2);U.set(S,{column:w,row:T,y:ff}),A.push({id:S,type:"pipelineNode",position:{x:w*330,y:ff},data:{exportLabel:{id:S,kind:p,componentRef:n,componentVersion:_f,componentDescription:t,status:m},label:X("div",{className:"flow-node-label"},X("strong",null,S),X("span",null,p),X("code",{title:t||n},_f?`${n}@${_f}`:n),X(uy,{status:m},m))},className:`pipeline-flow-node ${p} ${m}`})})});let K=$.flatMap((P,w)=>{let r=String(P?.from||P?.source||""),S=String(P?.to||P?.target||"");if(!j.has(r)||!j.has(S))return[];return[{source:r,target:S,index:w,condition:P?.condition,edgeType:P?.edgeType}]}),q=K.reduce((P,w)=>P.set(w.source,(P.get(w.source)||0)+1),new Map),E=K.reduce((P,w)=>P.set(w.target,(P.get(w.target)||0)+1),new Map),O=K.reduce((P,w)=>{let r=`${w.source}->${w.target}`;return P.set(r,(P.get(r)||0)+1)},new Map),G=new Map,H=new Map,Z=new Map,V=new Map,L=new Map,M=new Map,N=K.reduce((P,w)=>{let r=U.get(w.source),S=U.get(w.target),T=(S?.column||0)-(r?.column||0);if(T<=0||String(w.edgeType||"").toLowerCase()==="rework"||T!==1)return P;let R=`${w.source}->column:${S?.column??""}`,m=P.get(R)||[];return m.push(w),P.set(R,m),P},new Map);for(let P of N.values()){if(P.length<2)continue;P.slice().sort((w,r)=>{let S=U.get(w.target),T=U.get(r.target);return(S?.y||0)-(T?.y||0)||w.index-r.index}).forEach((w,r,S)=>{M.set(Vl(w),{slot:r-(S.length-1)/2,count:S.length})})}[...K].sort((P,w)=>{let r=U.get(P.source),S=U.get(P.target),T=U.get(w.source),Y=U.get(w.target),R=Math.abs((S?.column||0)-(r?.column||0))*330+Math.abs((S?.y||0)-(r?.y||0)),m=Math.abs((Y?.column||0)-(T?.column||0))*330+Math.abs((Y?.y||0)-(T?.y||0));return R-m||P.index-w.index}).forEach((P)=>{let w=U.get(P.source)||{column:0,row:0,y:0},r=U.get(P.target)||{column:0,row:0,y:0},S=r.column-w.column,T=Math.max(0,S),Y=S<=0||String(P.edgeType||"").toLowerCase()==="rework",R=w.y-r.y,m=E.get(P.target)||1,p=M.has(Vl(P)),n=!Y&&T<=1&&(p||m===1),_f=L.get(P.target)||new Map;L.set(P.target,_f);let t=Bl.slice().sort((ff,Gf)=>{let zf=(Zf)=>{let h=String(Zf.side),g=0;if(Y){if(h==="left")g+=86;if(h==="top")g+=r.y<=0?-22:12;if(h==="bottom")g+=r.y>=0?-22:12;if(Math.abs(r.y)<12&&h!=="left")g+=P.index%2===0?h==="top"?-6:6:h==="bottom"?-6:6;return g}if(n){if(h==="left")g-=p?72:44;if(h!=="left")g+=p?72:44;return g+Math.abs(R)*0.02}if(h==="left")g+=T<=1?0:24;if(h==="top")g+=R<-36?-18:42;if(h==="bottom")g+=R>36?-18:42;if(T<=1&&Math.abs(R)<=82&&h!=="left")g+=38;if(T>1&&h!=="left")g-=10;return g},jf=w.y-r.y,Wf=jf!==0?jf:P.index%2===0?-1:1,Vf=(Zf)=>{let h=_f.get(Zf.id)||0;return zf(Zf)+h*64+rT(Zf,_f,Wf)};return Vf(ff)-Vf(Gf)||String(ff.id).localeCompare(String(Gf.id))})[0];_f.set(t.id,(_f.get(t.id)||0)+1),V.set(Vl(P),t)});let x=K.map((P)=>{let w=Eq(u,P.target).toLowerCase(),r=`${P.source}->${P.target}`,S=G.get(P.source)||0,T=H.get(P.target)||0,Y=Z.get(r)||0;G.set(P.source,S+1),H.set(P.target,T+1),Z.set(r,Y+1);let R=S-((q.get(P.source)||1)-1)/2,m=T-((E.get(P.target)||1)-1)/2,p=Y-((O.get(r)||1)-1)/2,n=U.get(P.source),_f=U.get(P.target),t=(_f?.column||0)-(n?.column||0),ff=Math.max(1,Math.abs(t)),Gf=t<=0||String(P.edgeType||"").toLowerCase()==="rework",zf=Math.abs((_f?.y||0)-(n?.y||0)),jf=M.get(Vl(P)),Wf=!Gf&&t===1&&(E.get(P.target)||0)>1,Vf=jf?jf.slot:p*2+R+m*0.45,Zf=Vf===0?P.index%2===0?-1:1:Math.sign(Vf),h=V.get(Vl(P))||Bl[1],g=h.side==="top"?-1:h.side==="bottom"?1:Zf,I=Gf||ff>1||zf>96||Math.abs(Vf)>0.2||h.side!=="left",$f=Gf?118+ff*18:22+ff*16,lf=h.side==="left"?0:28,Af=I?Math.max(-280,Math.min(280,g*Math.min(180,$f+lf+zf*0.22)+Vf*28)):0,Yf=Math.max(0,Math.min(Xl.length-1,Math.round(R+(Xl.length-1)/2))),xf=Xl[Yf]||Xl[1],sf=w==="succeeded"?"var(--accent-2)":w==="running"?"var(--accent)":w==="failed"?"var(--danger)":"rgba(129, 147, 159, 0.78)",j0=n?.column||0,u0=_f?.column||0,D0=Af===0?0:Math.sign(Af),Fu=Gf?`feedback:${j0}->${u0}:${D0}`:jf?`fanout:${j0}->${u0}:${P.source}`:Wf?`fanin:${j0}->${u0}:${P.target}`:h.side!=="left"||ff>1?`corridor:${j0}->${u0}:${h.side}:${D0}:${Math.round(Math.abs(Af)/56)}`:"";return{id:`${P.source}->${P.target}-${P.index}`,source:P.source,target:P.target,sourceHandle:xf.id,targetHandle:h.id,type:"pipelineCurve",zIndex:12,animated:w==="running",data:{baseEdgeColor:sf,laneOffset:Af,routeMode:jf&&h.side==="left"?"direct-forward-left":"",targetSide:h.side,isFeedback:Gf,overlapGroup:Fu},targetStatus:w}}),c=x.reduce((P,w)=>{let r=String(w.data?.overlapGroup||"");return r?P.set(r,(P.get(r)||0)+1):P},new Map),v=new Map,C=x.map((P)=>{let w=String(P.targetStatus||"pending"),r={...P};delete r.targetStatus;let S=String(P.data?.overlapGroup||""),T=S?c.get(S)||0:0,Y=T>1?v.get(S)||0:-1;if(T>1)v.set(S,Y+1);let R=Y>=0?Jq[Y%Jq.length]:String(P.data.baseEdgeColor),m={stroke:R};if(P.data.isFeedback)m.strokeDasharray="9 7";return{...r,data:{...P.data,edgeColor:R,overlapSlot:Y,overlapCount:T},style:m,markerEnd:{type:n_.ArrowClosed,color:R},className:`pipeline-flow-edge ${w} ${P.data.isFeedback?"feedback":""} ${Y>=0?"overlap-colored":""}`}});return{nodes:A,edges:C}}function wu(f){return String(f??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function Oq(f){let u=String(f||"");if(u.includes("--accent-2"))return"#4eb7a8";if(u.includes("--accent"))return"#d7a13a";if(u.includes("--danger"))return"#cf6a54";return u.startsWith("#")?u:"#81939f"}function d5(f){return`arrow-${f.replace(/[^a-zA-Z0-9_-]+/g,"")}`}function mq(f,u="pipeline"){return String(f||u).replace(/[^a-zA-Z0-9_-]+/g,"-").replace(/^-|-$/g,"")||u}function Xq(f,u){let _=f.position.x,y=f.position.y,$=Bl.find((l)=>l.id===u);if($?.side==="top")return{x:_+U$*Aq($.style?.left,0.5),y,position:Uf.Top};if($?.side==="bottom")return{x:_+U$*Aq($.style?.left,0.5),y:y+W$,position:Uf.Bottom};return{x:_,y:y+W$/2,position:Uf.Left}}function KM(f){return{x:f.position.x+U$,y:f.position.y+W$/2}}function ZM(f,u){let _=Math.min(...f.nodes.map((E)=>E.position.x),0)-220,y=Math.min(...f.nodes.map((E)=>E.position.y),0)-220,$=Math.max(...f.nodes.map((E)=>E.position.x+U$),1)+220,l=Math.max(...f.nodes.map((E)=>E.position.y+W$),1)+220,j=Math.ceil($-_),J=Math.ceil(l-y),F=new Map(f.nodes.map((E)=>[E.id,E])),A=f.edges.map((E)=>Oq(E.data?.edgeColor||E.style?.stroke)),z=Array.from(new Set(["#4eb7a8","#d7a13a","#cf6a54","#81939f",...A])).map((E)=>``).join(""),W=f.edges.flatMap((E)=>{let O=F.get(E.source),G=F.get(E.target);if(!O||!G)return[];let H=KM(O),Z=Xq(G,String(E.targetHandle||"in-left")),V=Sq(H.x,H.y,Z.x,Z.y,Z.position,Number(E.data?.laneOffset||0),String(E.data?.routeMode||"")),L=Oq(E.data?.edgeColor||E.style?.stroke),M=E.data?.isFeedback?' stroke-dasharray="9 7"':"";return``}).join(` -`),K=f.nodes.map((E)=>{let O=E.data?.exportLabel||{},G=String(O.status||"pending").toLowerCase(),H=G==="succeeded"?"#4eb7a8":G==="running"?"#d7a13a":G==="failed"?"#cf6a54":"#81939f",Z=E.position.x,V=E.position.y,L=Bl.map((M)=>{let N=Xq(E,M.id);if(M.side==="top"||M.side==="bottom")return``;return``}).join(` +`)),U=A.reduce((G,W)=>G.concat(...W),[]);return[A,U]}return[[],[]]},[f]);return a.useEffect(()=>{let F=u?.target??AZ,A=u?.actInsideInputWithModifier??!0;if(f!==null){let U=(K)=>{if(l.current=K.ctrlKey||K.metaKey||K.shiftKey||K.altKey,(!l.current||l.current&&!A)&&EF(K))return!1;let H=WZ(K.code,J);if($.current.add(K[H]),UZ(j,$.current,!1)){let O=K.composedPath?.()?.[0]||K.target,z=O?.nodeName==="BUTTON"||O?.nodeName==="A";if(u.preventDefault!==!1&&(l.current||!z))K.preventDefault();y(!0)}},G=(K)=>{let E=WZ(K.code,J);if(UZ(j,$.current,!0))y(!1),$.current.clear();else $.current.delete(K[E]);if(K.key==="Meta")$.current.clear();l.current=!1},W=()=>{$.current.clear(),y(!1)};return F?.addEventListener("keydown",U),F?.addEventListener("keyup",G),window.addEventListener("blur",W),window.addEventListener("contextmenu",W),()=>{F?.removeEventListener("keydown",U),F?.removeEventListener("keyup",G),window.removeEventListener("blur",W),window.removeEventListener("contextmenu",W)}}},[f,y]),_}function UZ(f,u,_){return f.filter((y)=>_||y.length===u.size).some((y)=>y.every((l)=>u.has(l)))}function WZ(f,u){return u.includes(f)?"code":"key"}var ID=()=>{let f=z0();return a.useMemo(()=>{return{zoomIn:(u)=>{let{panZoom:_}=f.getState();return _?_.scaleBy(1.2,u):Promise.resolve(!1)},zoomOut:(u)=>{let{panZoom:_}=f.getState();return _?_.scaleBy(0.8333333333333334,u):Promise.resolve(!1)},zoomTo:(u,_)=>{let{panZoom:y}=f.getState();return y?y.scaleTo(u,_):Promise.resolve(!1)},getZoom:()=>f.getState().transform[2],setViewport:async(u,_)=>{let{transform:[y,l,$],panZoom:j}=f.getState();if(!j)return Promise.resolve(!1);return await j.setViewport({x:u.x??y,y:u.y??l,zoom:u.zoom??$},_),Promise.resolve(!0)},getViewport:()=>{let[u,_,y]=f.getState().transform;return{x:u,y:_,zoom:y}},setCenter:async(u,_,y)=>{return f.getState().setCenter(u,_,y)},fitBounds:async(u,_)=>{let{width:y,height:l,minZoom:$,maxZoom:j,panZoom:J}=f.getState(),F=z6(u,y,l,$,j,_?.padding??0.1);if(!J)return Promise.resolve(!1);return await J.setViewport(F,{duration:_?.duration,ease:_?.ease,interpolate:_?.interpolate}),Promise.resolve(!0)},screenToFlowPosition:(u,_={})=>{let{transform:y,snapGrid:l,snapToGrid:$,domNode:j}=f.getState();if(!j)return u;let{x:J,y:F}=j.getBoundingClientRect(),A={x:u.x-J,y:u.y-F},U=_.snapGrid??l,G=_.snapToGrid??$;return j3(A,y,G,U)},flowToScreenPosition:(u)=>{let{transform:_,domNode:y}=f.getState();if(!y)return u;let{x:l,y:$}=y.getBoundingClientRect(),j=W6(u,_);return{x:j.x+l,y:j.y+$}}}},[])};function SZ(f,u){let _=[],y=new Map,l=[];for(let $ of f)if($.type==="add"){l.push($);continue}else if($.type==="remove"||$.type==="replace")y.set($.id,[$]);else{let j=y.get($.id);if(j)j.push($);else y.set($.id,[$])}for(let $ of u){let j=y.get($.id);if(!j){_.push($);continue}if(j[0].type==="remove")continue;if(j[0].type==="replace"){_.push({...j[0].item});continue}let J={...$};for(let F of j)cD(F,J);_.push(J)}if(l.length)l.forEach(($)=>{if($.index!==void 0)_.splice($.index,0,{...$.item});else _.push({...$.item})});return _}function cD(f,u){switch(f.type){case"select":{u.selected=f.selected;break}case"position":{if(typeof f.position<"u")u.position=f.position;if(typeof f.dragging<"u")u.dragging=f.dragging;break}case"dimensions":{if(typeof f.dimensions<"u"){if(u.measured={...f.dimensions},f.setAttributes){if(f.setAttributes===!0||f.setAttributes==="width")u.width=f.dimensions.width;if(f.setAttributes===!0||f.setAttributes==="height")u.height=f.dimensions.height}}if(typeof f.resizing==="boolean")u.resizing=f.resizing;break}}}function pD(f,u){return SZ(f,u)}function kD(f,u){return SZ(f,u)}function my(f,u){return{id:f,type:"select",selected:u}}function Q3(f,u=new Set,_=!1){let y=[];for(let[l,$]of f){let j=u.has(l);if(!($.selected===void 0&&!j)&&$.selected!==j){if(_)$.selected=j;y.push(my($.id,j))}}return y}function GZ({items:f=[],lookup:u}){let _=[],y=new Map(f.map((l)=>[l.id,l]));for(let[l,$]of f.entries()){let j=u.get($.id),J=j?.internals?.userNode??j;if(J!==void 0&&J!==$)_.push({id:$.id,item:$,type:"replace"});if(J===void 0)_.push({item:$,type:"add",index:l})}for(let[l]of u)if(y.get(l)===void 0)_.push({id:l,type:"remove"});return _}function zZ(f){return{id:f.id,type:"remove"}}var KZ=(f)=>qK(f),mD=(f)=>JF(f);function CZ(f){return a.forwardRef(f)}function ZZ(f){let[u,_]=a.useState(BigInt(0)),[y]=a.useState(()=>iD(()=>_((l)=>l+BigInt(1))));return MF(()=>{let l=y.get();if(l.length)f(l),y.reset()},[u]),y}function iD(f){let u=[];return{get:()=>u,reset:()=>{u=[]},push:(_)=>{u.push(_),f()}}}var RZ=a.createContext(null);function gD({children:f}){let u=z0(),_=a.useCallback((J)=>{let{nodes:F=[],setNodes:A,hasDefaultNodes:U,onNodesChange:G,nodeLookup:W,fitViewQueued:K,onNodesChangeMiddlewareMap:E}=u.getState(),H=F;for(let z of J)H=typeof z==="function"?z(H):z;let O=GZ({items:H,lookup:W});for(let z of E.values())O=z(O);if(U)A(H);if(O.length>0)G?.(O);else if(K)window.requestAnimationFrame(()=>{let{fitViewQueued:z,nodes:q,setNodes:Z}=u.getState();if(z)Z(q)})},[]),y=ZZ(_),l=a.useCallback((J)=>{let{edges:F=[],setEdges:A,hasDefaultEdges:U,onEdgesChange:G,edgeLookup:W}=u.getState(),K=F;for(let E of J)K=typeof E==="function"?E(K):E;if(U)A(K);else if(G)G(GZ({items:K,lookup:W}))},[]),$=ZZ(l),j=a.useMemo(()=>({nodeQueue:y,edgeQueue:$}),[]);return o.jsx(RZ.Provider,{value:j,children:f})}function nD(){let f=a.useContext(RZ);if(!f)throw Error("useBatchContext must be used within a BatchProvider");return f}var tD=(f)=>!!f.panZoom;function SF(){let f=ID(),u=z0(),_=nD(),y=kf(tD),l=a.useMemo(()=>{let $=(G)=>u.getState().nodeLookup.get(G),j=(G)=>{_.nodeQueue.push(G)},J=(G)=>{_.edgeQueue.push(G)},F=(G)=>{let{nodeLookup:W,nodeOrigin:K}=u.getState(),E=KZ(G)?G:W.get(G.id),H=E.parentId?KF(E.position,E.measured,E.parentId,W,K):E.position,O={...E,position:H,width:E.measured?.width??E.width,height:E.measured?.height??E.height};return ky(O)},A=(G,W,K={replace:!1})=>{j((E)=>E.map((H)=>{if(H.id===G){let O=typeof W==="function"?W(H):W;return K.replace&&KZ(O)?O:{...H,...O}}return H}))},U=(G,W,K={replace:!1})=>{J((E)=>E.map((H)=>{if(H.id===G){let O=typeof W==="function"?W(H):W;return K.replace&&mD(O)?O:{...H,...O}}return H}))};return{getNodes:()=>u.getState().nodes.map((G)=>({...G})),getNode:(G)=>$(G)?.internals.userNode,getInternalNode:$,getEdges:()=>{let{edges:G=[]}=u.getState();return G.map((W)=>({...W}))},getEdge:(G)=>u.getState().edgeLookup.get(G),setNodes:j,setEdges:J,addNodes:(G)=>{let W=Array.isArray(G)?G:[G];_.nodeQueue.push((K)=>[...K,...W])},addEdges:(G)=>{let W=Array.isArray(G)?G:[G];_.edgeQueue.push((K)=>[...K,...W])},toObject:()=>{let{nodes:G=[],edges:W=[],transform:K}=u.getState(),[E,H,O]=K;return{nodes:G.map((z)=>({...z})),edges:W.map((z)=>({...z})),viewport:{x:E,y:H,zoom:O}}},deleteElements:async({nodes:G=[],edges:W=[]})=>{let{nodes:K,edges:E,onNodesDelete:H,onEdgesDelete:O,triggerNodeChanges:z,triggerEdgeChanges:q,onDelete:Z,onBeforeDelete:V}=u.getState(),{nodes:L,edges:r}=await VK({nodesToRemove:G,edgesToRemove:W,nodes:K,edges:E,onBeforeDelete:V}),N=r.length>0,D=L.length>0;if(N){let x=r.map(zZ);O?.(r),q(x)}if(D){let x=L.map(zZ);H?.(L),z(x)}if(D||N)Z?.({nodes:L,edges:r});return{deletedNodes:L,deletedEdges:r}},getIntersectingNodes:(G,W=!0,K)=>{let E=WF(G),H=E?G:F(G),O=K!==void 0;if(!H)return[];return(K||u.getState().nodes).filter((z)=>{let q=u.getState().nodeLookup.get(z.id);if(q&&!E&&(z.id===G.id||!q.internals.positionAbsolute))return!1;let Z=ky(O?z:q),V=l3(Z,H);return W&&V>0||V>=Z.width*Z.height||V>=H.width*H.height})},isNodeIntersecting:(G,W,K=!0)=>{let H=WF(G)?G:F(G);if(!H)return!1;let O=l3(H,W);return K&&O>0||O>=W.width*W.height||O>=H.width*H.height},updateNode:A,updateNodeData:(G,W,K={replace:!1})=>{A(G,(E)=>{let H=typeof W==="function"?W(E):W;return K.replace?{...E,data:H}:{...E,data:{...E.data,...H}}},K)},updateEdge:U,updateEdgeData:(G,W,K={replace:!1})=>{U(G,(E)=>{let H=typeof W==="function"?W(E):W;return K.replace?{...E,data:H}:{...E,data:{...E.data,...H}}},K)},getNodesBounds:(G)=>{let{nodeLookup:W,nodeOrigin:K}=u.getState();return QF(G,{nodeLookup:W,nodeOrigin:K})},getHandleConnections:({type:G,id:W,nodeId:K})=>Array.from(u.getState().connectionLookup.get(`${K}-${G}${W?`-${W}`:""}`)?.values()??[]),getNodeConnections:({type:G,handleId:W,nodeId:K})=>Array.from(u.getState().connectionLookup.get(`${K}${G?W?`-${G}-${W}`:`-${G}`:""}`)?.values()??[]),fitView:async(G)=>{let W=u.getState().fitViewResolver??NK();return u.setState({fitViewQueued:!0,fitViewOptions:G,fitViewResolver:W}),_.nodeQueue.push((K)=>[...K]),W.promise}}},[]);return a.useMemo(()=>{return{...l,...f,viewportInitialized:y}},[y])}var qZ=(f)=>f.selected,sD=typeof window<"u"?window:void 0;function oD({deleteKeyCode:f,multiSelectionKeyCode:u}){let _=z0(),{deleteElements:y}=SF(),l=Z6(f,{actInsideInputWithModifier:!1}),$=Z6(u,{target:sD});a.useEffect(()=>{if(l){let{edges:j,nodes:J}=_.getState();y({nodes:J.filter(qZ),edges:j.filter(qZ)}),_.setState({nodesSelectionActive:!1})}},[l]),a.useEffect(()=>{_.setState({multiSelectionActive:$})},[$])}function aD(f){let u=z0();a.useEffect(()=>{let _=()=>{if(!f.current||!(f.current.checkVisibility?.()??!0))return!1;let y=L5(f.current);if(y.height===0||y.width===0)u.getState().onError?.("004",Iu.error004());u.setState({width:y.width||500,height:y.height||500})};if(f.current){_(),window.addEventListener("resize",_);let y=new ResizeObserver(()=>_());return y.observe(f.current),()=>{if(window.removeEventListener("resize",_),y&&f.current)y.unobserve(f.current)}}},[])}var h5={position:"absolute",width:"100%",height:"100%",top:0,left:0},dD=(f)=>({userSelectionActive:f.userSelectionActive,lib:f.lib,connectionInProgress:f.connection.inProgress});function eD({onPaneContextMenu:f,zoomOnScroll:u=!0,zoomOnPinch:_=!0,panOnScroll:y=!1,panOnScrollSpeed:l=0.5,panOnScrollMode:$=l_.Free,zoomOnDoubleClick:j=!0,panOnDrag:J=!0,defaultViewport:F,translateExtent:A,minZoom:U,maxZoom:G,zoomActivationKeyCode:W,preventScrolling:K=!0,children:E,noWheelClassName:H,noPanClassName:O,onViewportChange:z,isControlledViewport:q,paneClickDistance:Z,selectionOnDrag:V}){let L=z0(),r=a.useRef(null),{userSelectionActive:N,lib:D,connectionInProgress:x}=kf(dD,W0),c=Z6(W),v=a.useRef();aD(r);let C=a.useCallback((S)=>{if(z?.({x:S[0],y:S[1],zoom:S[2]}),!q)L.setState({transform:S})},[z,q]);return a.useEffect(()=>{if(r.current){v.current=kK({domNode:r.current,minZoom:U,maxZoom:G,translateExtent:A,viewport:F,onDraggingChange:(M)=>L.setState((w)=>w.paneDragging===M?w:{paneDragging:M}),onPanZoomStart:(M,w)=>{let{onViewportChangeStart:Y,onMoveStart:R}=L.getState();R?.(M,w),Y?.(w)},onPanZoom:(M,w)=>{let{onViewportChange:Y,onMove:R}=L.getState();R?.(M,w),Y?.(w)},onPanZoomEnd:(M,w)=>{let{onViewportChangeEnd:Y,onMoveEnd:R}=L.getState();R?.(M,w),Y?.(w)}});let{x:S,y:B,zoom:P}=v.current.getViewport();return L.setState({panZoom:v.current,transform:[S,B,P],domNode:r.current.closest(".react-flow")}),()=>{v.current?.destroy()}}},[]),a.useEffect(()=>{v.current?.update({onPaneContextMenu:f,zoomOnScroll:u,zoomOnPinch:_,panOnScroll:y,panOnScrollSpeed:l,panOnScrollMode:$,zoomOnDoubleClick:j,panOnDrag:J,zoomActivationKeyPressed:c,preventScrolling:K,noPanClassName:O,userSelectionActive:N,noWheelClassName:H,lib:D,onTransformChange:C,connectionInProgress:x,selectionOnDrag:V,paneClickDistance:Z})},[f,u,_,y,l,$,j,J,c,K,O,N,H,D,C,x,V,Z]),o.jsx("div",{className:"react-flow__renderer",ref:r,style:h5,children:E})}var fw=(f)=>({userSelectionActive:f.userSelectionActive,userSelectionRect:f.userSelectionRect});function uw(){let{userSelectionActive:f,userSelectionRect:u}=kf(fw,W0);if(!(f&&u))return null;return o.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:u.width,height:u.height,transform:`translate(${u.x}px, ${u.y}px)`}})}var TF=(f,u)=>{return(_)=>{if(_.target!==u.current)return;f?.(_)}},_w=(f)=>({userSelectionActive:f.userSelectionActive,elementsSelectable:f.elementsSelectable,connectionInProgress:f.connection.inProgress,dragging:f.paneDragging});function yw({isSelecting:f,selectionKeyPressed:u,selectionMode:_=cy.Full,panOnDrag:y,paneClickDistance:l,selectionOnDrag:$,onSelectionStart:j,onSelectionEnd:J,onPaneClick:F,onPaneContextMenu:A,onPaneScroll:U,onPaneMouseEnter:G,onPaneMouseMove:W,onPaneMouseLeave:K,children:E}){let H=z0(),{userSelectionActive:O,elementsSelectable:z,dragging:q,connectionInProgress:Z}=kf(_w,W0),V=z&&(f||O),L=a.useRef(null),r=a.useRef(),N=a.useRef(new Set),D=a.useRef(new Set),x=a.useRef(!1),c=(Y)=>{if(x.current||Z){x.current=!1;return}F?.(Y),H.getState().resetSelectedElements(),H.setState({nodesSelectionActive:!1})},v=(Y)=>{if(Array.isArray(y)&&y?.includes(2)){Y.preventDefault();return}A?.(Y)},C=U?(Y)=>U(Y):void 0,S=(Y)=>{if(x.current)Y.stopPropagation(),x.current=!1},B=(Y)=>{let{domNode:R}=H.getState();if(r.current=R?.getBoundingClientRect(),!r.current)return;let k=Y.target===L.current;if(!k&&!!Y.target.closest(".nokey")||!f||!($&&k||u)||Y.button!==0||!Y.isPrimary)return;Y.target?.setPointerCapture?.(Y.pointerId),x.current=!1;let{x:_f,y:s}=_1(Y.nativeEvent,r.current);if(H.setState({userSelectionRect:{width:0,height:0,startX:_f,startY:s,x:_f,y:s}}),!k)Y.stopPropagation(),Y.preventDefault()},P=(Y)=>{let{userSelectionRect:R,transform:k,nodeLookup:p,edgeLookup:n,connectionLookup:_f,triggerNodeChanges:s,triggerEdgeChanges:ff,defaultEdgeOptions:Kf,resetSelectedElements:Gf}=H.getState();if(!r.current||!R)return;let{x:jf,y:Wf}=_1(Y.nativeEvent,r.current),{startX:Of,startY:Zf}=R;if(!x.current){let $f=u?0:l;if(Math.hypot(jf-Of,Wf-Zf)<=$f)return;Gf(),j?.(Y)}x.current=!0;let h={startX:Of,startY:Zf,x:jf$f.id)),D.current=new Set;let lf=Kf?.selectable??!0;for(let $f of N.current){let Af=_f.get($f);if(!Af)continue;for(let{edgeId:Yf}of Af.values()){let xf=n.get(Yf);if(xf&&(xf.selectable??lf))D.current.add(Yf)}}if(!ZF(i,N.current)){let $f=Q3(p,N.current,!0);s($f)}if(!ZF(I,D.current)){let $f=Q3(n,D.current);ff($f)}H.setState({userSelectionRect:h,userSelectionActive:!0,nodesSelectionActive:!1})},M=(Y)=>{if(Y.button!==0)return;if(Y.target?.releasePointerCapture?.(Y.pointerId),!O&&Y.target===L.current&&H.getState().userSelectionRect)c?.(Y);if(H.setState({userSelectionActive:!1,userSelectionRect:null}),x.current)J?.(Y),H.setState({nodesSelectionActive:N.current.size>0})},w=y===!0||Array.isArray(y)&&y.includes(0);return o.jsxs("div",{className:B0(["react-flow__pane",{draggable:w,dragging:q,selection:f}]),onClick:V?void 0:TF(c,L),onContextMenu:TF(v,L),onWheel:TF(C,L),onPointerEnter:V?void 0:G,onPointerMove:V?P:W,onPointerUp:V?M:void 0,onPointerDownCapture:V?B:void 0,onClickCapture:V?S:void 0,onPointerLeave:K,ref:L,style:h5,children:[E,o.jsx(uw,{})]})}function PF({id:f,store:u,unselect:_=!1,nodeRef:y}){let{addSelectedNodes:l,unselectNodesAndEdges:$,multiSelectionActive:j,nodeLookup:J,onError:F}=u.getState(),A=J.get(f);if(!A){F?.("012",Iu.error012(f));return}if(u.setState({nodesSelectionActive:!1}),!A.selected)l([f]);else if(_||A.selected&&j)$({nodes:[A],edges:[]}),requestAnimationFrame(()=>y?.current?.blur())}function xZ({nodeRef:f,disabled:u=!1,noDragClassName:_,handleSelector:y,nodeId:l,isSelectable:$,nodeClickDistance:j}){let J=z0(),[F,A]=a.useState(!1),U=a.useRef();return a.useEffect(()=>{U.current=RK({getStoreItems:()=>J.getState(),onNodeMouseDown:(G)=>{PF({id:G,store:J,nodeRef:f})},onDragStart:()=>{A(!0)},onDragStop:()=>{A(!1)}})},[]),a.useEffect(()=>{if(u||!f.current||!U.current)return;return U.current.update({noDragClassName:_,handleSelector:y,domNode:f.current,isSelectable:$,nodeId:l,nodeClickDistance:j}),()=>{U.current?.destroy()}},[_,y,u,$,f,l,j]),F}var lw=(f)=>(u)=>u.selected&&(u.draggable||f&&typeof u.draggable>"u");function vZ(){let f=z0();return a.useCallback((_)=>{let{nodeExtent:y,snapToGrid:l,snapGrid:$,nodesDraggable:j,onError:J,updateNodePositions:F,nodeLookup:A,nodeOrigin:U}=f.getState(),G=new Map,W=lw(j),K=l?$[0]:5,E=l?$[1]:5,H=_.direction.x*K*_.factor,O=_.direction.y*E*_.factor;for(let[,z]of A){if(!W(z))continue;let q={x:z.internals.positionAbsolute.x+H,y:z.internals.positionAbsolute.y+O};if(l)q=$3(q,$);let{position:Z,positionAbsolute:V}=AF({nodeId:z.id,nextPosition:q,nodeLookup:A,nodeExtent:y,nodeOrigin:U,onError:J});z.position=Z,z.internals.positionAbsolute=V,G.set(z.id,z)}F(G)},[])}var CF=a.createContext(null),$w=CF.Provider;CF.Consumer;var bZ=()=>{return a.useContext(CF)},jw=(f)=>({connectOnClick:f.connectOnClick,noPanClassName:f.noPanClassName,rfId:f.rfId}),Jw=(f,u,_)=>(y)=>{let{connectionClickStartHandle:l,connectionMode:$,connection:j}=y,{fromHandle:J,toHandle:F,isValid:A}=j,U=F?.nodeId===f&&F?.id===u&&F?.type===_;return{connectingFrom:J?.nodeId===f&&J?.id===u&&J?.type===_,connectingTo:U,clickConnecting:l?.nodeId===f&&l?.id===u&&l?.type===_,isPossibleEndHandle:$===g_.Strict?J?.type!==_:f!==J?.nodeId||u!==J?.id,connectionInProcess:!!J,clickConnectionInProcess:!!l,valid:U&&A}};function Fw({type:f="source",position:u=Uf.Top,isValidConnection:_,isConnectable:y=!0,isConnectableStart:l=!0,isConnectableEnd:$=!0,id:j,onConnect:J,children:F,className:A,onMouseDown:U,onTouchStart:G,...W},K){let E=j||null,H=f==="target",O=z0(),z=bZ(),{connectOnClick:q,noPanClassName:Z,rfId:V}=kf(jw,W0),{connectingFrom:L,connectingTo:r,clickConnecting:N,isPossibleEndHandle:D,connectionInProcess:x,clickConnectionInProcess:c,valid:v}=kf(Jw(z,E,f),W0);if(!z)O.getState().onError?.("010",Iu.error010());let C=(P)=>{let{defaultEdgeOptions:M,onConnect:w,hasDefaultEdges:Y}=O.getState(),R={...M,...P};if(Y){let{edges:k,setEdges:p}=O.getState();p(OF(R,k))}w?.(R),J?.(R)},S=(P)=>{if(!z)return;let M=HF(P.nativeEvent);if(l&&(M&&P.button===0||!M)){let w=O.getState();M5.onPointerDown(P.nativeEvent,{handleDomNode:P.currentTarget,autoPanOnConnect:w.autoPanOnConnect,connectionMode:w.connectionMode,connectionRadius:w.connectionRadius,domNode:w.domNode,nodeLookup:w.nodeLookup,lib:w.lib,isTarget:H,handleId:E,nodeId:z,flowId:w.rfId,panBy:w.panBy,cancelConnection:w.cancelConnection,onConnectStart:w.onConnectStart,onConnectEnd:(...Y)=>O.getState().onConnectEnd?.(...Y),updateConnection:w.updateConnection,onConnect:C,isValidConnection:_||((...Y)=>O.getState().isValidConnection?.(...Y)??!0),getTransform:()=>O.getState().transform,getFromHandle:()=>O.getState().connection.fromHandle,autoPanSpeed:w.autoPanSpeed,dragThreshold:w.connectionDragThreshold})}if(M)U?.(P);else G?.(P)},B=(P)=>{let{onClickConnectStart:M,onClickConnectEnd:w,connectionClickStartHandle:Y,connectionMode:R,isValidConnection:k,lib:p,rfId:n,nodeLookup:_f,connection:s}=O.getState();if(!z||!Y&&!l)return;if(!Y){M?.(P.nativeEvent,{nodeId:z,handleId:E,handleType:f}),O.setState({connectionClickStartHandle:{nodeId:z,type:f,id:E}});return}let ff=qF(P.target),Kf=_||k,{connection:Gf,isValid:jf}=M5.isValid(P.nativeEvent,{handle:{nodeId:z,id:E,type:f},connectionMode:R,fromNodeId:Y.nodeId,fromHandleId:Y.id||null,fromType:Y.type,isValidConnection:Kf,flowId:n,doc:ff,lib:p,nodeLookup:_f});if(jf&&Gf)C(Gf);let Wf=structuredClone(s);delete Wf.inProgress,Wf.toPosition=Wf.toHandle?Wf.toHandle.position:null,w?.(P,Wf),O.setState({connectionClickStartHandle:null})};return o.jsx("div",{"data-handleid":E,"data-nodeid":z,"data-handlepos":u,"data-id":`${V}-${z}-${E}-${f}`,className:B0(["react-flow__handle",`react-flow__handle-${u}`,"nodrag",Z,A,{source:!H,target:H,connectable:y,connectablestart:l,connectableend:$,clickconnecting:N,connectingfrom:L,connectingto:r,valid:v,connectionindicator:y&&(!x||D)&&(x||c?$:l)}]),onMouseDown:S,onTouchStart:S,onClick:q?B:void 0,ref:K,...W,children:F})}var iy=a.memo(CZ(Fw));function Qw({data:f,isConnectable:u,sourcePosition:_=Uf.Bottom}){return o.jsxs(o.Fragment,{children:[f?.label,o.jsx(iy,{type:"source",position:_,isConnectable:u})]})}function Aw({data:f,isConnectable:u,targetPosition:_=Uf.Top,sourcePosition:y=Uf.Bottom}){return o.jsxs(o.Fragment,{children:[o.jsx(iy,{type:"target",position:_,isConnectable:u}),f?.label,o.jsx(iy,{type:"source",position:y,isConnectable:u})]})}function Uw(){return null}function Ww({data:f,isConnectable:u,targetPosition:_=Uf.Top}){return o.jsxs(o.Fragment,{children:[o.jsx(iy,{type:"target",position:_,isConnectable:u}),f?.label]})}var x5={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},EZ={input:Qw,default:Aw,output:Ww,group:Uw};function Gw(f){if(f.internals.handleBounds===void 0)return{width:f.width??f.initialWidth??f.style?.width,height:f.height??f.initialHeight??f.style?.height};return{width:f.width??f.style?.width,height:f.height??f.style?.height}}var zw=(f)=>{let{width:u,height:_,x:y,y:l}=y3(f.nodeLookup,{filter:($)=>!!$.selected});return{width:u1(u)?u:null,height:u1(_)?_:null,userSelectionActive:f.userSelectionActive,transformString:`translate(${f.transform[0]}px,${f.transform[1]}px) scale(${f.transform[2]}) translate(${y}px,${l}px)`}};function Kw({onSelectionContextMenu:f,noPanClassName:u,disableKeyboardA11y:_}){let y=z0(),{width:l,height:$,transformString:j,userSelectionActive:J}=kf(zw,W0),F=vZ(),A=a.useRef(null);a.useEffect(()=>{if(!_)A.current?.focus({preventScroll:!0})},[_]);let U=!J&&l!==null&&$!==null;if(xZ({nodeRef:A,disabled:!U}),!U)return null;let G=f?(K)=>{let E=y.getState().nodes.filter((H)=>H.selected);f(K,E)}:void 0,W=(K)=>{if(Object.prototype.hasOwnProperty.call(x5,K.key))K.preventDefault(),F({direction:x5[K.key],factor:K.shiftKey?4:1})};return o.jsx("div",{className:B0(["react-flow__nodesselection","react-flow__container",u]),style:{transform:j},children:o.jsx("div",{ref:A,className:"react-flow__nodesselection-rect",onContextMenu:G,tabIndex:_?void 0:-1,onKeyDown:_?void 0:W,style:{width:l,height:$}})})}var HZ=typeof window<"u"?window:void 0,Zw=(f)=>{return{nodesSelectionActive:f.nodesSelectionActive,userSelectionActive:f.userSelectionActive}};function hZ({children:f,onPaneClick:u,onPaneMouseEnter:_,onPaneMouseMove:y,onPaneMouseLeave:l,onPaneContextMenu:$,onPaneScroll:j,paneClickDistance:J,deleteKeyCode:F,selectionKeyCode:A,selectionOnDrag:U,selectionMode:G,onSelectionStart:W,onSelectionEnd:K,multiSelectionKeyCode:E,panActivationKeyCode:H,zoomActivationKeyCode:O,elementsSelectable:z,zoomOnScroll:q,zoomOnPinch:Z,panOnScroll:V,panOnScrollSpeed:L,panOnScrollMode:r,zoomOnDoubleClick:N,panOnDrag:D,defaultViewport:x,translateExtent:c,minZoom:v,maxZoom:C,preventScrolling:S,onSelectionContextMenu:B,noWheelClassName:P,noPanClassName:M,disableKeyboardA11y:w,onViewportChange:Y,isControlledViewport:R}){let{nodesSelectionActive:k,userSelectionActive:p}=kf(Zw,W0),n=Z6(A,{target:HZ}),_f=Z6(H,{target:HZ}),s=_f||D,ff=_f||V,Kf=U&&s!==!0,Gf=n||p||Kf;return oD({deleteKeyCode:F,multiSelectionKeyCode:E}),o.jsx(eD,{onPaneContextMenu:$,elementsSelectable:z,zoomOnScroll:q,zoomOnPinch:Z,panOnScroll:ff,panOnScrollSpeed:L,panOnScrollMode:r,zoomOnDoubleClick:N,panOnDrag:!n&&s,defaultViewport:x,translateExtent:c,minZoom:v,maxZoom:C,zoomActivationKeyCode:O,preventScrolling:S,noWheelClassName:P,noPanClassName:M,onViewportChange:Y,isControlledViewport:R,paneClickDistance:J,selectionOnDrag:Kf,children:o.jsxs(yw,{onSelectionStart:W,onSelectionEnd:K,onPaneClick:u,onPaneMouseEnter:_,onPaneMouseMove:y,onPaneMouseLeave:l,onPaneContextMenu:$,onPaneScroll:j,panOnDrag:s,isSelecting:!!Gf,selectionMode:G,selectionKeyPressed:n,paneClickDistance:J,selectionOnDrag:Kf,children:[f,k&&o.jsx(Kw,{onSelectionContextMenu:B,noPanClassName:M,disableKeyboardA11y:w})]})})}hZ.displayName="FlowRenderer";var qw=a.memo(hZ),Ew=(f)=>(u)=>{return f?O5(u.nodeLookup,{x:0,y:0,width:u.width,height:u.height},u.transform,!0).map((_)=>_.id):Array.from(u.nodeLookup.keys())};function Hw(f){return kf(a.useCallback(Ew(f),[f]),W0)}var Vw=(f)=>f.updateNodeInternals;function Ow(){let f=kf(Vw),[u]=a.useState(()=>{if(typeof ResizeObserver>"u")return null;return new ResizeObserver((_)=>{let y=new Map;_.forEach((l)=>{let $=l.target.getAttribute("data-id");y.set($,{id:$,nodeElement:l.target,force:!0})}),f(y)})});return a.useEffect(()=>{return()=>{u?.disconnect()}},[u]),u}function Xw({node:f,nodeType:u,hasDimensions:_,resizeObserver:y}){let l=z0(),$=a.useRef(null),j=a.useRef(null),J=a.useRef(f.sourcePosition),F=a.useRef(f.targetPosition),A=a.useRef(u),U=_&&!!f.internals.handleBounds;return a.useEffect(()=>{if($.current&&!f.hidden&&(!U||j.current!==$.current)){if(j.current)y?.unobserve(j.current);y?.observe($.current),j.current=$.current}},[U,f.hidden]),a.useEffect(()=>{return()=>{if(j.current)y?.unobserve(j.current),j.current=null}},[]),a.useEffect(()=>{if($.current){let G=A.current!==u,W=J.current!==f.sourcePosition,K=F.current!==f.targetPosition;if(G||W||K)A.current=u,J.current=f.sourcePosition,F.current=f.targetPosition,l.getState().updateNodeInternals(new Map([[f.id,{id:f.id,nodeElement:$.current,force:!0}]]))}},[f.id,u,f.sourcePosition,f.targetPosition]),$}function Nw({id:f,onClick:u,onMouseEnter:_,onMouseMove:y,onMouseLeave:l,onContextMenu:$,onDoubleClick:j,nodesDraggable:J,elementsSelectable:F,nodesConnectable:A,nodesFocusable:U,resizeObserver:G,noDragClassName:W,noPanClassName:K,disableKeyboardA11y:E,rfId:H,nodeTypes:O,nodeClickDistance:z,onError:q}){let{node:Z,internals:V,isParent:L}=kf((jf)=>{let Wf=jf.nodeLookup.get(f),Of=jf.parentLookup.has(f);return{node:Wf,internals:Wf.internals,isParent:Of}},W0),r=Z.type||"default",N=O?.[r]||EZ[r];if(N===void 0)q?.("003",Iu.error003(r)),r="default",N=O?.default||EZ.default;let D=!!(Z.draggable||J&&typeof Z.draggable>"u"),x=!!(Z.selectable||F&&typeof Z.selectable>"u"),c=!!(Z.connectable||A&&typeof Z.connectable>"u"),v=!!(Z.focusable||U&&typeof Z.focusable>"u"),C=z0(),S=zF(Z),B=Xw({node:Z,nodeType:r,hasDimensions:S,resizeObserver:G}),P=xZ({nodeRef:B,disabled:Z.hidden||!D,noDragClassName:W,handleSelector:Z.dragHandle,nodeId:f,isSelectable:x,nodeClickDistance:z}),M=vZ();if(Z.hidden)return null;let w=R1(Z),Y=Gw(Z),R=x||D||u||_||y||l,k=_?(jf)=>_(jf,{...V.userNode}):void 0,p=y?(jf)=>y(jf,{...V.userNode}):void 0,n=l?(jf)=>l(jf,{...V.userNode}):void 0,_f=$?(jf)=>$(jf,{...V.userNode}):void 0,s=j?(jf)=>j(jf,{...V.userNode}):void 0,ff=(jf)=>{let{selectNodesOnDrag:Wf,nodeDragThreshold:Of}=C.getState();if(x&&(!Wf||!D||Of>0))PF({id:f,store:C,nodeRef:B});if(u)u(jf,{...V.userNode})},Kf=(jf)=>{if(EF(jf.nativeEvent)||E)return;if(yF.includes(jf.key)&&x){let Wf=jf.key==="Escape";PF({id:f,store:C,unselect:Wf,nodeRef:B})}else if(D&&Z.selected&&Object.prototype.hasOwnProperty.call(x5,jf.key)){jf.preventDefault();let{ariaLabelConfig:Wf}=C.getState();C.setState({ariaLiveMessage:Wf["node.a11yDescription.ariaLiveMessage"]({direction:jf.key.replace("Arrow","").toLowerCase(),x:~~V.positionAbsolute.x,y:~~V.positionAbsolute.y})}),M({direction:x5[jf.key],factor:jf.shiftKey?4:1})}},Gf=()=>{if(E||!B.current?.matches(":focus-visible"))return;let{transform:jf,width:Wf,height:Of,autoPanOnNodeFocus:Zf,setCenter:h}=C.getState();if(!Zf)return;if(!(O5(new Map([[f,Z]]),{x:0,y:0,width:Wf,height:Of},jf,!0).length>0))h(Z.position.x+w.width/2,Z.position.y+w.height/2,{zoom:jf[2]})};return o.jsx("div",{className:B0(["react-flow__node",`react-flow__node-${r}`,{[K]:D},Z.className,{selected:Z.selected,selectable:x,parent:L,draggable:D,dragging:P}]),ref:B,style:{zIndex:V.z,transform:`translate(${V.positionAbsolute.x}px,${V.positionAbsolute.y}px)`,pointerEvents:R?"all":"none",visibility:S?"visible":"hidden",...Z.style,...Y},"data-id":f,"data-testid":`rf__node-${f}`,onMouseEnter:k,onMouseMove:p,onMouseLeave:n,onContextMenu:_f,onClick:ff,onDoubleClick:s,onKeyDown:v?Kf:void 0,tabIndex:v?0:void 0,onFocus:v?Gf:void 0,role:Z.ariaRole??(v?"group":void 0),"aria-roledescription":"node","aria-describedby":E?void 0:`${rZ}-${H}`,"aria-label":Z.ariaLabel,...Z.domAttributes,children:o.jsx($w,{value:f,children:o.jsx(N,{id:f,data:Z.data,type:r,positionAbsoluteX:V.positionAbsolute.x,positionAbsoluteY:V.positionAbsolute.y,selected:Z.selected??!1,selectable:x,draggable:D,deletable:Z.deletable??!0,isConnectable:c,sourcePosition:Z.sourcePosition,targetPosition:Z.targetPosition,dragging:P,dragHandle:Z.dragHandle,zIndex:V.z,parentId:Z.parentId,...w})})})}var Lw=a.memo(Nw),Yw=(f)=>({nodesDraggable:f.nodesDraggable,nodesConnectable:f.nodesConnectable,nodesFocusable:f.nodesFocusable,elementsSelectable:f.elementsSelectable,onError:f.onError});function IZ(f){let{nodesDraggable:u,nodesConnectable:_,nodesFocusable:y,elementsSelectable:l,onError:$}=kf(Yw,W0),j=Hw(f.onlyRenderVisibleElements),J=Ow();return o.jsx("div",{className:"react-flow__nodes",style:h5,children:j.map((F)=>{return o.jsx(Lw,{id:F,nodeTypes:f.nodeTypes,nodeExtent:f.nodeExtent,onClick:f.onNodeClick,onMouseEnter:f.onNodeMouseEnter,onMouseMove:f.onNodeMouseMove,onMouseLeave:f.onNodeMouseLeave,onContextMenu:f.onNodeContextMenu,onDoubleClick:f.onNodeDoubleClick,noDragClassName:f.noDragClassName,noPanClassName:f.noPanClassName,rfId:f.rfId,disableKeyboardA11y:f.disableKeyboardA11y,resizeObserver:J,nodesDraggable:u,nodesConnectable:_,nodesFocusable:y,elementsSelectable:l,nodeClickDistance:f.nodeClickDistance,onError:$},F)})})}IZ.displayName="NodeRenderer";var Bw=a.memo(IZ);function Dw(f){return kf(a.useCallback((_)=>{if(!f)return _.edges.map((l)=>l.id);let y=[];if(_.width&&_.height)for(let l of _.edges){let $=_.nodeLookup.get(l.source),j=_.nodeLookup.get(l.target);if($&&j&&BK({sourceNode:$,targetNode:j,width:_.width,height:_.height,transform:_.transform}))y.push(l.id)}return y},[f]),W0)}var ww=({color:f="none",strokeWidth:u=1})=>{let _={strokeWidth:u,...f&&{stroke:f}};return o.jsx("polyline",{className:"arrow",style:_,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},Tw=({color:f="none",strokeWidth:u=1})=>{let _={strokeWidth:u,...f&&{stroke:f,fill:f}};return o.jsx("polyline",{className:"arrowclosed",style:_,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},VZ={[n_.Arrow]:ww,[n_.ArrowClosed]:Tw};function rw(f){let u=z0();return a.useMemo(()=>{if(!Object.prototype.hasOwnProperty.call(VZ,f))return u.getState().onError?.("009",Iu.error009(f)),null;return VZ[f]},[f])}var Mw=({id:f,type:u,color:_,width:y=12.5,height:l=12.5,markerUnits:$="strokeWidth",strokeWidth:j,orient:J="auto-start-reverse"})=>{let F=rw(u);if(!F)return null;return o.jsx("marker",{className:"react-flow__arrowhead",id:f,markerWidth:`${y}`,markerHeight:`${l}`,viewBox:"-10 -10 20 20",markerUnits:$,orient:J,refX:"0",refY:"0",children:o.jsx(F,{color:_,strokeWidth:j})})},cZ=({defaultColor:f,rfId:u})=>{let _=kf(($)=>$.edges),y=kf(($)=>$.defaultEdgeOptions),l=a.useMemo(()=>{return wK(_,{id:u,defaultColor:f,defaultMarkerStart:y?.markerStart,defaultMarkerEnd:y?.markerEnd})},[_,y,u,f]);if(!l.length)return null;return o.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:o.jsx("defs",{children:l.map(($)=>o.jsx(Mw,{id:$.id,type:$.type,color:$.color,width:$.width,height:$.height,markerUnits:$.markerUnits,strokeWidth:$.strokeWidth,orient:$.orient},$.id))})})};cZ.displayName="MarkerDefinitions";var Pw=a.memo(cZ);function pZ({x:f,y:u,label:_,labelStyle:y,labelShowBg:l=!0,labelBgStyle:$,labelBgPadding:j=[2,4],labelBgBorderRadius:J=2,children:F,className:A,...U}){let[G,W]=a.useState({x:1,y:0,width:0,height:0}),K=B0(["react-flow__edge-textwrapper",A]),E=a.useRef(null);if(a.useEffect(()=>{if(E.current){let H=E.current.getBBox();W({x:H.x,y:H.y,width:H.width,height:H.height})}},[_]),!_)return null;return o.jsxs("g",{transform:`translate(${f-G.width/2} ${u-G.height/2})`,className:K,visibility:G.width?"visible":"hidden",...U,children:[l&&o.jsx("rect",{width:G.width+2*j[0],x:-j[0],y:-j[1],height:G.height+2*j[1],className:"react-flow__edge-textbg",style:$,rx:J,ry:J}),o.jsx("text",{className:"react-flow__edge-text",y:G.height/2,dy:"0.3em",ref:E,style:y,children:_}),F]})}pZ.displayName="EdgeText";var Sw=a.memo(pZ);function A3({path:f,labelX:u,labelY:_,label:y,labelStyle:l,labelShowBg:$,labelBgStyle:j,labelBgPadding:J,labelBgBorderRadius:F,interactionWidth:A=20,...U}){return o.jsxs(o.Fragment,{children:[o.jsx("path",{...U,d:f,fill:"none",className:B0(["react-flow__edge-path",U.className])}),A?o.jsx("path",{d:f,fill:"none",strokeOpacity:0,strokeWidth:A,className:"react-flow__edge-interaction"}):null,y&&u1(u)&&u1(_)?o.jsx(Sw,{x:u,y:_,label:y,labelStyle:l,labelShowBg:$,labelBgStyle:j,labelBgPadding:J,labelBgBorderRadius:F}):null]})}function OZ({pos:f,x1:u,y1:_,x2:y,y2:l}){if(f===Uf.Left||f===Uf.Right)return[0.5*(u+y),_];return[u,0.5*(_+l)]}function kZ({sourceX:f,sourceY:u,sourcePosition:_=Uf.Bottom,targetX:y,targetY:l,targetPosition:$=Uf.Top}){let[j,J]=OZ({pos:_,x1:f,y1:u,x2:y,y2:l}),[F,A]=OZ({pos:$,x1:y,y1:l,x2:f,y2:u}),[U,G,W,K]=Y5({sourceX:f,sourceY:u,targetX:y,targetY:l,sourceControlX:j,sourceControlY:J,targetControlX:F,targetControlY:A});return[`M${f},${u} C${j},${J} ${F},${A} ${y},${l}`,U,G,W,K]}function mZ(f){return a.memo(({id:u,sourceX:_,sourceY:y,targetX:l,targetY:$,sourcePosition:j,targetPosition:J,label:F,labelStyle:A,labelShowBg:U,labelBgStyle:G,labelBgPadding:W,labelBgBorderRadius:K,style:E,markerEnd:H,markerStart:O,interactionWidth:z})=>{let[q,Z,V]=kZ({sourceX:_,sourceY:y,sourcePosition:j,targetX:l,targetY:$,targetPosition:J}),L=f.isInternal?void 0:u;return o.jsx(A3,{id:L,path:q,labelX:Z,labelY:V,label:F,labelStyle:A,labelShowBg:U,labelBgStyle:G,labelBgPadding:W,labelBgBorderRadius:K,style:E,markerEnd:H,markerStart:O,interactionWidth:z})})}var Cw=mZ({isInternal:!1}),iZ=mZ({isInternal:!0});Cw.displayName="SimpleBezierEdge";iZ.displayName="SimpleBezierEdgeInternal";function gZ(f){return a.memo(({id:u,sourceX:_,sourceY:y,targetX:l,targetY:$,label:j,labelStyle:J,labelShowBg:F,labelBgStyle:A,labelBgPadding:U,labelBgBorderRadius:G,style:W,sourcePosition:K=Uf.Bottom,targetPosition:E=Uf.Top,markerEnd:H,markerStart:O,pathOptions:z,interactionWidth:q})=>{let[Z,V,L]=K6({sourceX:_,sourceY:y,sourcePosition:K,targetX:l,targetY:$,targetPosition:E,borderRadius:z?.borderRadius,offset:z?.offset,stepPosition:z?.stepPosition}),r=f.isInternal?void 0:u;return o.jsx(A3,{id:r,path:Z,labelX:V,labelY:L,label:j,labelStyle:J,labelShowBg:F,labelBgStyle:A,labelBgPadding:U,labelBgBorderRadius:G,style:W,markerEnd:H,markerStart:O,interactionWidth:q})})}var nZ=gZ({isInternal:!1}),tZ=gZ({isInternal:!0});nZ.displayName="SmoothStepEdge";tZ.displayName="SmoothStepEdgeInternal";function sZ(f){return a.memo(({id:u,..._})=>{let y=f.isInternal?void 0:u;return o.jsx(nZ,{..._,id:y,pathOptions:a.useMemo(()=>({borderRadius:0,offset:_.pathOptions?.offset}),[_.pathOptions?.offset])})})}var Rw=sZ({isInternal:!1}),oZ=sZ({isInternal:!0});Rw.displayName="StepEdge";oZ.displayName="StepEdgeInternal";function aZ(f){return a.memo(({id:u,sourceX:_,sourceY:y,targetX:l,targetY:$,label:j,labelStyle:J,labelShowBg:F,labelBgStyle:A,labelBgPadding:U,labelBgBorderRadius:G,style:W,markerEnd:K,markerStart:E,interactionWidth:H})=>{let[O,z,q]=D5({sourceX:_,sourceY:y,targetX:l,targetY:$}),Z=f.isInternal?void 0:u;return o.jsx(A3,{id:Z,path:O,labelX:z,labelY:q,label:j,labelStyle:J,labelShowBg:F,labelBgStyle:A,labelBgPadding:U,labelBgBorderRadius:G,style:W,markerEnd:K,markerStart:E,interactionWidth:H})})}var xw=aZ({isInternal:!1}),dZ=aZ({isInternal:!0});xw.displayName="StraightEdge";dZ.displayName="StraightEdgeInternal";function eZ(f){return a.memo(({id:u,sourceX:_,sourceY:y,targetX:l,targetY:$,sourcePosition:j=Uf.Bottom,targetPosition:J=Uf.Top,label:F,labelStyle:A,labelShowBg:U,labelBgStyle:G,labelBgPadding:W,labelBgBorderRadius:K,style:E,markerEnd:H,markerStart:O,pathOptions:z,interactionWidth:q})=>{let[Z,V,L]=B5({sourceX:_,sourceY:y,sourcePosition:j,targetX:l,targetY:$,targetPosition:J,curvature:z?.curvature}),r=f.isInternal?void 0:u;return o.jsx(A3,{id:r,path:Z,labelX:V,labelY:L,label:F,labelStyle:A,labelShowBg:U,labelBgStyle:G,labelBgPadding:W,labelBgBorderRadius:K,style:E,markerEnd:H,markerStart:O,interactionWidth:q})})}var vw=eZ({isInternal:!1}),fq=eZ({isInternal:!0});vw.displayName="BezierEdge";fq.displayName="BezierEdgeInternal";var XZ={default:fq,straight:dZ,step:oZ,smoothstep:tZ,simplebezier:iZ},NZ={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null},bw=(f,u,_)=>{if(_===Uf.Left)return f-u;if(_===Uf.Right)return f+u;return f},hw=(f,u,_)=>{if(_===Uf.Top)return f-u;if(_===Uf.Bottom)return f+u;return f},LZ="react-flow__edgeupdater";function YZ({position:f,centerX:u,centerY:_,radius:y=10,onMouseDown:l,onMouseEnter:$,onMouseOut:j,type:J}){return o.jsx("circle",{onMouseDown:l,onMouseEnter:$,onMouseOut:j,className:B0([LZ,`${LZ}-${J}`]),cx:bw(u,y,f),cy:hw(_,y,f),r:y,stroke:"transparent",fill:"transparent"})}function Iw({isReconnectable:f,reconnectRadius:u,edge:_,sourceX:y,sourceY:l,targetX:$,targetY:j,sourcePosition:J,targetPosition:F,onReconnect:A,onReconnectStart:U,onReconnectEnd:G,setReconnecting:W,setUpdateHover:K}){let E=z0(),H=(V,L)=>{if(V.button!==0)return;let{autoPanOnConnect:r,domNode:N,connectionMode:D,connectionRadius:x,lib:c,onConnectStart:v,cancelConnection:C,nodeLookup:S,rfId:B,panBy:P,updateConnection:M}=E.getState(),w=L.type==="target",Y=(p,n)=>{W(!1),G?.(p,_,L.type,n)},R=(p)=>A?.(_,p),k=(p,n)=>{W(!0),U?.(V,_,L.type),v?.(p,n)};M5.onPointerDown(V.nativeEvent,{autoPanOnConnect:r,connectionMode:D,connectionRadius:x,domNode:N,handleId:L.id,nodeId:L.nodeId,nodeLookup:S,isTarget:w,edgeUpdaterType:L.type,lib:c,flowId:B,cancelConnection:C,panBy:P,isValidConnection:(...p)=>E.getState().isValidConnection?.(...p)??!0,onConnect:R,onConnectStart:k,onConnectEnd:(...p)=>E.getState().onConnectEnd?.(...p),onReconnectEnd:Y,updateConnection:M,getTransform:()=>E.getState().transform,getFromHandle:()=>E.getState().connection.fromHandle,dragThreshold:E.getState().connectionDragThreshold,handleDomNode:V.currentTarget})},O=(V)=>H(V,{nodeId:_.target,id:_.targetHandle??null,type:"target"}),z=(V)=>H(V,{nodeId:_.source,id:_.sourceHandle??null,type:"source"}),q=()=>K(!0),Z=()=>K(!1);return o.jsxs(o.Fragment,{children:[(f===!0||f==="source")&&o.jsx(YZ,{position:J,centerX:y,centerY:l,radius:u,onMouseDown:O,onMouseEnter:q,onMouseOut:Z,type:"source"}),(f===!0||f==="target")&&o.jsx(YZ,{position:F,centerX:$,centerY:j,radius:u,onMouseDown:z,onMouseEnter:q,onMouseOut:Z,type:"target"})]})}function cw({id:f,edgesFocusable:u,edgesReconnectable:_,elementsSelectable:y,onClick:l,onDoubleClick:$,onContextMenu:j,onMouseEnter:J,onMouseMove:F,onMouseLeave:A,reconnectRadius:U,onReconnect:G,onReconnectStart:W,onReconnectEnd:K,rfId:E,edgeTypes:H,noPanClassName:O,onError:z,disableKeyboardA11y:q}){let Z=kf((h)=>h.edgeLookup.get(f)),V=kf((h)=>h.defaultEdgeOptions);Z=V?{...V,...Z}:Z;let L=Z.type||"default",r=H?.[L]||XZ[L];if(r===void 0)z?.("011",Iu.error011(L)),L="default",r=H?.default||XZ.default;let N=!!(Z.focusable||u&&typeof Z.focusable>"u"),D=typeof G<"u"&&(Z.reconnectable||_&&typeof Z.reconnectable>"u"),x=!!(Z.selectable||y&&typeof Z.selectable>"u"),c=a.useRef(null),[v,C]=a.useState(!1),[S,B]=a.useState(!1),P=z0(),{zIndex:M,sourceX:w,sourceY:Y,targetX:R,targetY:k,sourcePosition:p,targetPosition:n}=kf(a.useCallback((h)=>{let i=h.nodeLookup.get(Z.source),I=h.nodeLookup.get(Z.target);if(!i||!I)return{zIndex:Z.zIndex,...NZ};let lf=DK({id:f,sourceNode:i,targetNode:I,sourceHandle:Z.sourceHandle||null,targetHandle:Z.targetHandle||null,connectionMode:h.connectionMode,onError:z});return{zIndex:YK({selected:Z.selected,zIndex:Z.zIndex,sourceNode:i,targetNode:I,elevateOnSelect:h.elevateEdgesOnSelect,zIndexMode:h.zIndexMode}),...lf||NZ}},[Z.source,Z.target,Z.sourceHandle,Z.targetHandle,Z.selected,Z.zIndex]),W0),_f=a.useMemo(()=>Z.markerStart?`url('#${w5(Z.markerStart,E)}')`:void 0,[Z.markerStart,E]),s=a.useMemo(()=>Z.markerEnd?`url('#${w5(Z.markerEnd,E)}')`:void 0,[Z.markerEnd,E]);if(Z.hidden||w===null||Y===null||R===null||k===null)return null;let ff=(h)=>{let{addSelectedEdges:i,unselectNodesAndEdges:I,multiSelectionActive:lf}=P.getState();if(x)if(P.setState({nodesSelectionActive:!1}),Z.selected&&lf)I({nodes:[],edges:[Z]}),c.current?.blur();else i([f]);if(l)l(h,Z)},Kf=$?(h)=>{$(h,{...Z})}:void 0,Gf=j?(h)=>{j(h,{...Z})}:void 0,jf=J?(h)=>{J(h,{...Z})}:void 0,Wf=F?(h)=>{F(h,{...Z})}:void 0,Of=A?(h)=>{A(h,{...Z})}:void 0,Zf=(h)=>{if(!q&&yF.includes(h.key)&&x){let{unselectNodesAndEdges:i,addSelectedEdges:I}=P.getState();if(h.key==="Escape")c.current?.blur(),i({edges:[Z]});else I([f])}};return o.jsx("svg",{style:{zIndex:M},children:o.jsxs("g",{className:B0(["react-flow__edge",`react-flow__edge-${L}`,Z.className,O,{selected:Z.selected,animated:Z.animated,inactive:!x&&!l,updating:v,selectable:x}]),onClick:ff,onDoubleClick:Kf,onContextMenu:Gf,onMouseEnter:jf,onMouseMove:Wf,onMouseLeave:Of,onKeyDown:N?Zf:void 0,tabIndex:N?0:void 0,role:Z.ariaRole??(N?"group":"img"),"aria-roledescription":"edge","data-id":f,"data-testid":`rf__edge-${f}`,"aria-label":Z.ariaLabel===null?void 0:Z.ariaLabel||`Edge from ${Z.source} to ${Z.target}`,"aria-describedby":N?`${MZ}-${E}`:void 0,ref:c,...Z.domAttributes,children:[!S&&o.jsx(r,{id:f,source:Z.source,target:Z.target,type:Z.type,selected:Z.selected,animated:Z.animated,selectable:x,deletable:Z.deletable??!0,label:Z.label,labelStyle:Z.labelStyle,labelShowBg:Z.labelShowBg,labelBgStyle:Z.labelBgStyle,labelBgPadding:Z.labelBgPadding,labelBgBorderRadius:Z.labelBgBorderRadius,sourceX:w,sourceY:Y,targetX:R,targetY:k,sourcePosition:p,targetPosition:n,data:Z.data,style:Z.style,sourceHandleId:Z.sourceHandle,targetHandleId:Z.targetHandle,markerStart:_f,markerEnd:s,pathOptions:"pathOptions"in Z?Z.pathOptions:void 0,interactionWidth:Z.interactionWidth}),D&&o.jsx(Iw,{edge:Z,isReconnectable:D,reconnectRadius:U,onReconnect:G,onReconnectStart:W,onReconnectEnd:K,sourceX:w,sourceY:Y,targetX:R,targetY:k,sourcePosition:p,targetPosition:n,setUpdateHover:C,setReconnecting:B})]})})}var pw=a.memo(cw),kw=(f)=>({edgesFocusable:f.edgesFocusable,edgesReconnectable:f.edgesReconnectable,elementsSelectable:f.elementsSelectable,connectionMode:f.connectionMode,onError:f.onError});function uq({defaultMarkerColor:f,onlyRenderVisibleElements:u,rfId:_,edgeTypes:y,noPanClassName:l,onReconnect:$,onEdgeContextMenu:j,onEdgeMouseEnter:J,onEdgeMouseMove:F,onEdgeMouseLeave:A,onEdgeClick:U,reconnectRadius:G,onEdgeDoubleClick:W,onReconnectStart:K,onReconnectEnd:E,disableKeyboardA11y:H}){let{edgesFocusable:O,edgesReconnectable:z,elementsSelectable:q,onError:Z}=kf(kw,W0),V=Dw(u);return o.jsxs("div",{className:"react-flow__edges",children:[o.jsx(Pw,{defaultColor:f,rfId:_}),V.map((L)=>{return o.jsx(pw,{id:L,edgesFocusable:O,edgesReconnectable:z,elementsSelectable:q,noPanClassName:l,onReconnect:$,onContextMenu:j,onMouseEnter:J,onMouseMove:F,onMouseLeave:A,onClick:U,reconnectRadius:G,onDoubleClick:W,onReconnectStart:K,onReconnectEnd:E,rfId:_,onError:Z,edgeTypes:y,disableKeyboardA11y:H},L)})]})}uq.displayName="EdgeRenderer";var mw=a.memo(uq),iw=(f)=>`translate(${f.transform[0]}px,${f.transform[1]}px) scale(${f.transform[2]})`;function gw({children:f}){let u=kf(iw);return o.jsx("div",{className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:u},children:f})}function nw(f){let u=SF(),_=a.useRef(!1);a.useEffect(()=>{if(!_.current&&u.viewportInitialized&&f)setTimeout(()=>f(u),1),_.current=!0},[f,u.viewportInitialized])}var tw=(f)=>f.panZoom?.syncViewport;function sw(f){let u=kf(tw),_=z0();return a.useEffect(()=>{if(f)u?.(f),_.setState({transform:[f.x,f.y,f.zoom]})},[f,u]),null}function BZ(f){return f.connection.inProgress?{...f.connection,to:j3(f.connection.to,f.transform)}:{...f.connection}}function ow(f){if(f)return(_)=>{let y=BZ(_);return f(y)};return BZ}function aw(f){let u=ow(f);return kf(u,W0)}var dw=(f)=>({nodesConnectable:f.nodesConnectable,isValid:f.connection.isValid,inProgress:f.connection.inProgress,width:f.width,height:f.height});function ew({containerStyle:f,style:u,type:_,component:y}){let{nodesConnectable:l,width:$,height:j,isValid:J,inProgress:F}=kf(dw,W0);if(!($&&l&&F))return null;return o.jsx("svg",{style:f,width:$,height:j,className:"react-flow__connectionline react-flow__container",children:o.jsx("g",{className:B0(["react-flow__connection",jF(J)]),children:o.jsx(_q,{style:u,type:_,CustomComponent:y,isValid:J})})})}var _q=({style:f,type:u=C1.Bezier,CustomComponent:_,isValid:y})=>{let{inProgress:l,from:$,fromNode:j,fromHandle:J,fromPosition:F,to:A,toNode:U,toHandle:G,toPosition:W,pointer:K}=aw();if(!l)return;if(_)return o.jsx(_,{connectionLineType:u,connectionLineStyle:f,fromNode:j,fromHandle:J,fromX:$.x,fromY:$.y,toX:A.x,toY:A.y,fromPosition:F,toPosition:W,connectionStatus:jF(y),toNode:U,toHandle:G,pointer:K});let E="",H={sourceX:$.x,sourceY:$.y,sourcePosition:F,targetX:A.x,targetY:A.y,targetPosition:W};switch(u){case C1.Bezier:[E]=B5(H);break;case C1.SimpleBezier:[E]=kZ(H);break;case C1.Step:[E]=K6({...H,borderRadius:0});break;case C1.SmoothStep:[E]=K6(H);break;default:[E]=D5(H)}return o.jsx("path",{d:E,fill:"none",className:"react-flow__connection-path",style:f})};_q.displayName="ConnectionLine";var fT={};function DZ(f=fT){let u=a.useRef(f),_=z0();a.useEffect(()=>{},[f])}function uT(){let f=z0(),u=a.useRef(!1);a.useEffect(()=>{},[])}function yq({nodeTypes:f,edgeTypes:u,onInit:_,onNodeClick:y,onEdgeClick:l,onNodeDoubleClick:$,onEdgeDoubleClick:j,onNodeMouseEnter:J,onNodeMouseMove:F,onNodeMouseLeave:A,onNodeContextMenu:U,onSelectionContextMenu:G,onSelectionStart:W,onSelectionEnd:K,connectionLineType:E,connectionLineStyle:H,connectionLineComponent:O,connectionLineContainerStyle:z,selectionKeyCode:q,selectionOnDrag:Z,selectionMode:V,multiSelectionKeyCode:L,panActivationKeyCode:r,zoomActivationKeyCode:N,deleteKeyCode:D,onlyRenderVisibleElements:x,elementsSelectable:c,defaultViewport:v,translateExtent:C,minZoom:S,maxZoom:B,preventScrolling:P,defaultMarkerColor:M,zoomOnScroll:w,zoomOnPinch:Y,panOnScroll:R,panOnScrollSpeed:k,panOnScrollMode:p,zoomOnDoubleClick:n,panOnDrag:_f,onPaneClick:s,onPaneMouseEnter:ff,onPaneMouseMove:Kf,onPaneMouseLeave:Gf,onPaneScroll:jf,onPaneContextMenu:Wf,paneClickDistance:Of,nodeClickDistance:Zf,onEdgeContextMenu:h,onEdgeMouseEnter:i,onEdgeMouseMove:I,onEdgeMouseLeave:lf,reconnectRadius:$f,onReconnect:Af,onReconnectStart:Yf,onReconnectEnd:xf,noDragClassName:of,noWheelClassName:F0,noPanClassName:y0,disableKeyboardA11y:T0,nodeExtent:Qu,rfId:X0,viewport:v0,onViewportChange:iu}){return DZ(f),DZ(u),uT(),nw(_),sw(v0),o.jsx(qw,{onPaneClick:s,onPaneMouseEnter:ff,onPaneMouseMove:Kf,onPaneMouseLeave:Gf,onPaneContextMenu:Wf,onPaneScroll:jf,paneClickDistance:Of,deleteKeyCode:D,selectionKeyCode:q,selectionOnDrag:Z,selectionMode:V,onSelectionStart:W,onSelectionEnd:K,multiSelectionKeyCode:L,panActivationKeyCode:r,zoomActivationKeyCode:N,elementsSelectable:c,zoomOnScroll:w,zoomOnPinch:Y,zoomOnDoubleClick:n,panOnScroll:R,panOnScrollSpeed:k,panOnScrollMode:p,panOnDrag:_f,defaultViewport:v,translateExtent:C,minZoom:S,maxZoom:B,onSelectionContextMenu:G,preventScrolling:P,noDragClassName:of,noWheelClassName:F0,noPanClassName:y0,disableKeyboardA11y:T0,onViewportChange:iu,isControlledViewport:!!v0,children:o.jsxs(gw,{children:[o.jsx(mw,{edgeTypes:u,onEdgeClick:l,onEdgeDoubleClick:j,onReconnect:Af,onReconnectStart:Yf,onReconnectEnd:xf,onlyRenderVisibleElements:x,onEdgeContextMenu:h,onEdgeMouseEnter:i,onEdgeMouseMove:I,onEdgeMouseLeave:lf,reconnectRadius:$f,defaultMarkerColor:M,noPanClassName:y0,disableKeyboardA11y:T0,rfId:X0}),o.jsx(ew,{style:H,type:E,component:O,containerStyle:z}),o.jsx("div",{className:"react-flow__edgelabel-renderer"}),o.jsx(Bw,{nodeTypes:f,onNodeClick:y,onNodeDoubleClick:$,onNodeMouseEnter:J,onNodeMouseMove:F,onNodeMouseLeave:A,onNodeContextMenu:U,nodeClickDistance:Zf,onlyRenderVisibleElements:x,noPanClassName:y0,noDragClassName:of,disableKeyboardA11y:T0,nodeExtent:Qu,rfId:X0}),o.jsx("div",{className:"react-flow__viewport-portal"})]})})}yq.displayName="GraphView";var _T=a.memo(yq),wZ=({nodes:f,edges:u,defaultNodes:_,defaultEdges:y,width:l,height:$,fitView:j,fitViewOptions:J,minZoom:F=0.5,maxZoom:A=2,nodeOrigin:U,nodeExtent:G,zIndexMode:W="basic"}={})=>{let K=new Map,E=new Map,H=new Map,O=new Map,z=y??u??[],q=_??f??[],Z=U??[0,0],V=G??_3;BF(H,O,z);let{nodesInitialized:L}=T5(q,K,E,{nodeOrigin:Z,nodeExtent:V,zIndexMode:W}),r=[0,0,1];if(j&&l&&$){let N=y3(K,{filter:(v)=>!!((v.width||v.initialWidth)&&(v.height||v.initialHeight))}),{x:D,y:x,zoom:c}=z6(N,l,$,F,A,J?.padding??0.1);r=[D,x,c]}return{rfId:"1",width:l??0,height:$??0,transform:r,nodes:q,nodesInitialized:L,nodeLookup:K,parentLookup:E,edges:z,edgeLookup:O,connectionLookup:H,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:_!==void 0,hasDefaultEdges:y!==void 0,panZoom:null,minZoom:F,maxZoom:A,translateExtent:_3,nodeExtent:V,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:g_.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:Z,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:j??!1,fitViewOptions:J,fitViewResolver:null,connection:{...$F},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:GF,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:lF,zIndexMode:W,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},yT=({nodes:f,edges:u,defaultNodes:_,defaultEdges:y,width:l,height:$,fitView:j,fitViewOptions:J,minZoom:F,maxZoom:A,nodeOrigin:U,nodeExtent:G,zIndexMode:W})=>$Z((K,E)=>{async function H(){let{nodeLookup:O,panZoom:z,fitViewOptions:q,fitViewResolver:Z,width:V,height:L,minZoom:r,maxZoom:N}=E();if(!z)return;await HK({nodes:O,width:V,height:L,panZoom:z,minZoom:r,maxZoom:N},q),Z?.resolve(!0),K({fitViewResolver:null})}return{...wZ({nodes:f,edges:u,width:l,height:$,fitView:j,fitViewOptions:J,minZoom:F,maxZoom:A,nodeOrigin:U,nodeExtent:G,defaultNodes:_,defaultEdges:y,zIndexMode:W}),setNodes:(O)=>{let{nodeLookup:z,parentLookup:q,nodeOrigin:Z,elevateNodesOnSelect:V,fitViewQueued:L,zIndexMode:r,nodesSelectionActive:N}=E(),{nodesInitialized:D,hasSelectedNodes:x}=T5(O,z,q,{nodeOrigin:Z,nodeExtent:G,elevateNodesOnSelect:V,checkEquality:!0,zIndexMode:r}),c=N&&x;if(L&&D)H(),K({nodes:O,nodesInitialized:D,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:c});else K({nodes:O,nodesInitialized:D,nodesSelectionActive:c})},setEdges:(O)=>{let{connectionLookup:z,edgeLookup:q}=E();BF(z,q,O),K({edges:O})},setDefaultNodesAndEdges:(O,z)=>{if(O){let{setNodes:q}=E();q(O),K({hasDefaultNodes:!0})}if(z){let{setEdges:q}=E();q(z),K({hasDefaultEdges:!0})}},updateNodeInternals:(O)=>{let{triggerNodeChanges:z,nodeLookup:q,parentLookup:Z,domNode:V,nodeOrigin:L,nodeExtent:r,debug:N,fitViewQueued:D,zIndexMode:x}=E(),{changes:c,updatedInternals:v}=PK(O,q,Z,V,L,r,x);if(!v)return;if(rK(q,Z,{nodeOrigin:L,nodeExtent:r,zIndexMode:x}),D)H(),K({fitViewQueued:!1,fitViewOptions:void 0});else K({});if(c?.length>0){if(N)console.log("React Flow: trigger node changes",c);z?.(c)}},updateNodePositions:(O,z=!1)=>{let q=[],Z=[],{nodeLookup:V,triggerNodeChanges:L,connection:r,updateConnection:N,onNodesChangeMiddlewareMap:D}=E();for(let[x,c]of O){let v=V.get(x),C=!!(v?.expandParent&&v?.parentId&&c?.position),S={id:x,type:"position",position:C?{x:Math.max(0,c.position.x),y:Math.max(0,c.position.y)}:c.position,dragging:z};if(v&&r.inProgress&&r.fromNode.id===v.id){let B=t_(v,r.fromHandle,Uf.Left,!0);N({...r,from:B})}if(C&&v.parentId)q.push({id:x,parentId:v.parentId,rect:{...c.internals.positionAbsolute,width:c.measured.width??0,height:c.measured.height??0}});Z.push(S)}if(q.length>0){let{parentLookup:x,nodeOrigin:c}=E(),v=r5(q,V,x,c);Z.push(...v)}for(let x of D.values())Z=x(Z);L(Z)},triggerNodeChanges:(O)=>{let{onNodesChange:z,setNodes:q,nodes:Z,hasDefaultNodes:V,debug:L}=E();if(O?.length){if(V){let r=pD(O,Z);q(r)}if(L)console.log("React Flow: trigger node changes",O);z?.(O)}},triggerEdgeChanges:(O)=>{let{onEdgesChange:z,setEdges:q,edges:Z,hasDefaultEdges:V,debug:L}=E();if(O?.length){if(V){let r=kD(O,Z);q(r)}if(L)console.log("React Flow: trigger edge changes",O);z?.(O)}},addSelectedNodes:(O)=>{let{multiSelectionActive:z,edgeLookup:q,nodeLookup:Z,triggerNodeChanges:V,triggerEdgeChanges:L}=E();if(z){let r=O.map((N)=>my(N,!0));V(r);return}V(Q3(Z,new Set([...O]),!0)),L(Q3(q))},addSelectedEdges:(O)=>{let{multiSelectionActive:z,edgeLookup:q,nodeLookup:Z,triggerNodeChanges:V,triggerEdgeChanges:L}=E();if(z){let r=O.map((N)=>my(N,!0));L(r);return}L(Q3(q,new Set([...O]))),V(Q3(Z,new Set,!0))},unselectNodesAndEdges:({nodes:O,edges:z}={})=>{let{edges:q,nodes:Z,nodeLookup:V,triggerNodeChanges:L,triggerEdgeChanges:r}=E(),N=O?O:Z,D=z?z:q,x=[];for(let v of N){if(!v.selected)continue;let C=V.get(v.id);if(C)C.selected=!1;x.push(my(v.id,!1))}let c=[];for(let v of D){if(!v.selected)continue;c.push(my(v.id,!1))}L(x),r(c)},setMinZoom:(O)=>{let{panZoom:z,maxZoom:q}=E();z?.setScaleExtent([O,q]),K({minZoom:O})},setMaxZoom:(O)=>{let{panZoom:z,minZoom:q}=E();z?.setScaleExtent([q,O]),K({maxZoom:O})},setTranslateExtent:(O)=>{E().panZoom?.setTranslateExtent(O),K({translateExtent:O})},resetSelectedElements:()=>{let{edges:O,nodes:z,triggerNodeChanges:q,triggerEdgeChanges:Z,elementsSelectable:V}=E();if(!V)return;let L=z.reduce((N,D)=>D.selected?[...N,my(D.id,!1)]:N,[]),r=O.reduce((N,D)=>D.selected?[...N,my(D.id,!1)]:N,[]);q(L),Z(r)},setNodeExtent:(O)=>{let{nodes:z,nodeLookup:q,parentLookup:Z,nodeOrigin:V,elevateNodesOnSelect:L,nodeExtent:r,zIndexMode:N}=E();if(O[0][0]===r[0][0]&&O[0][1]===r[0][1]&&O[1][0]===r[1][0]&&O[1][1]===r[1][1])return;T5(z,q,Z,{nodeOrigin:V,nodeExtent:O,elevateNodesOnSelect:L,checkEquality:!1,zIndexMode:N}),K({nodeExtent:O})},panBy:(O)=>{let{transform:z,width:q,height:Z,panZoom:V,translateExtent:L}=E();return SK({delta:O,panZoom:V,transform:z,translateExtent:L,width:q,height:Z})},setCenter:async(O,z,q)=>{let{width:Z,height:V,maxZoom:L,panZoom:r}=E();if(!r)return Promise.resolve(!1);let N=typeof q?.zoom<"u"?q.zoom:L;return await r.setViewport({x:Z/2-O*N,y:V/2-z*N,zoom:N},{duration:q?.duration,ease:q?.ease,interpolate:q?.interpolate}),Promise.resolve(!0)},cancelConnection:()=>{K({connection:{...$F}})},updateConnection:(O)=>{K({connection:O})},reset:()=>K({...wZ()})}},Object.is);function lT({initialNodes:f,initialEdges:u,defaultNodes:_,defaultEdges:y,initialWidth:l,initialHeight:$,initialMinZoom:j,initialMaxZoom:J,initialFitViewOptions:F,fitView:A,nodeOrigin:U,nodeExtent:G,zIndexMode:W,children:K}){let[E]=a.useState(()=>yT({nodes:f,edges:u,defaultNodes:_,defaultEdges:y,width:l,height:$,fitView:A,minZoom:j,maxZoom:J,fitViewOptions:F,nodeOrigin:U,nodeExtent:G,zIndexMode:W}));return o.jsx(XD,{value:E,children:o.jsx(gD,{children:K})})}function $T({children:f,nodes:u,edges:_,defaultNodes:y,defaultEdges:l,width:$,height:j,fitView:J,fitViewOptions:F,minZoom:A,maxZoom:U,nodeOrigin:G,nodeExtent:W,zIndexMode:K}){if(a.useContext(v5))return o.jsx(o.Fragment,{children:f});return o.jsx(lT,{initialNodes:u,initialEdges:_,defaultNodes:y,defaultEdges:l,initialWidth:$,initialHeight:j,fitView:J,initialFitViewOptions:F,initialMinZoom:A,initialMaxZoom:U,nodeOrigin:G,nodeExtent:W,zIndexMode:K,children:f})}var jT={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function JT({nodes:f,edges:u,defaultNodes:_,defaultEdges:y,className:l,nodeTypes:$,edgeTypes:j,onNodeClick:J,onEdgeClick:F,onInit:A,onMove:U,onMoveStart:G,onMoveEnd:W,onConnect:K,onConnectStart:E,onConnectEnd:H,onClickConnectStart:O,onClickConnectEnd:z,onNodeMouseEnter:q,onNodeMouseMove:Z,onNodeMouseLeave:V,onNodeContextMenu:L,onNodeDoubleClick:r,onNodeDragStart:N,onNodeDrag:D,onNodeDragStop:x,onNodesDelete:c,onEdgesDelete:v,onDelete:C,onSelectionChange:S,onSelectionDragStart:B,onSelectionDrag:P,onSelectionDragStop:M,onSelectionContextMenu:w,onSelectionStart:Y,onSelectionEnd:R,onBeforeDelete:k,connectionMode:p,connectionLineType:n=C1.Bezier,connectionLineStyle:_f,connectionLineComponent:s,connectionLineContainerStyle:ff,deleteKeyCode:Kf="Backspace",selectionKeyCode:Gf="Shift",selectionOnDrag:jf=!1,selectionMode:Wf=cy.Full,panActivationKeyCode:Of="Space",multiSelectionKeyCode:Zf=J3()?"Meta":"Control",zoomActivationKeyCode:h=J3()?"Meta":"Control",snapToGrid:i,snapGrid:I,onlyRenderVisibleElements:lf=!1,selectNodesOnDrag:$f,nodesDraggable:Af,autoPanOnNodeFocus:Yf,nodesConnectable:xf,nodesFocusable:of,nodeOrigin:F0=PZ,edgesFocusable:y0,edgesReconnectable:T0,elementsSelectable:Qu=!0,defaultViewport:X0=RD,minZoom:v0=0.5,maxZoom:iu=2,translateExtent:K0=_3,preventScrolling:Au=!0,nodeExtent:uf,defaultMarkerColor:vf="#b1b1b7",zoomOnScroll:o0=!0,zoomOnPinch:Bf=!0,panOnScroll:b0=!1,panOnScrollSpeed:i0=0.5,panOnScrollMode:a0=l_.Free,zoomOnDoubleClick:nf=!0,panOnDrag:d0=!0,onPaneClick:Hu,onPaneMouseEnter:oy,onPaneMouseMove:J_,onPaneMouseLeave:ay,onPaneScroll:t,onPaneContextMenu:Hf,paneClickDistance:Df=1,nodeClickDistance:If=0,children:Rf,onReconnect:Q0,onReconnectStart:af,onReconnectEnd:h0,onEdgeContextMenu:e0,onEdgeDoubleClick:S6,onEdgeMouseEnter:dy,onEdgeMouseMove:ey,onEdgeMouseLeave:$y,reconnectRadius:F_=10,onNodesChange:C6,onEdgesChange:W2,noDragClassName:G2="nodrag",noWheelClassName:Q_="nowheel",noPanClassName:jy="nopan",fitView:V3,fitViewOptions:R6,connectOnClick:O3,attributionPosition:X3,proOptions:j1,defaultEdgeOptions:Jy,elevateNodesOnSelect:x6=!0,elevateEdgesOnSelect:z2=!1,disableKeyboardA11y:N3=!1,autoPanOnConnect:L3,autoPanOnNodeDrag:K2,autoPanSpeed:Z2,connectionRadius:I1,isValidConnection:v6,onError:N1,style:fl,id:b6,nodeDragThreshold:q2,connectionDragThreshold:E2,viewport:EQ,onViewportChange:gu,width:h6,height:H2,colorMode:Mu="light",debug:Y3,onScroll:ul,ariaLabelConfig:B3,zIndexMode:I6="basic",...V2},O2){let D3=b6||"1",X2=hD(Mu),N2=a.useCallback((c6)=>{c6.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),ul?.(c6)},[ul]);return o.jsx("div",{"data-testid":"rf__wrapper",...V2,onScroll:N2,style:{...fl,...jT},ref:O2,className:B0(["react-flow",l,X2]),id:b6,role:"application",children:o.jsxs($T,{nodes:f,edges:u,width:h6,height:H2,fitView:V3,fitViewOptions:R6,minZoom:v0,maxZoom:iu,nodeOrigin:F0,nodeExtent:uf,zIndexMode:I6,children:[o.jsx(bD,{nodes:f,edges:u,defaultNodes:_,defaultEdges:y,onConnect:K,onConnectStart:E,onConnectEnd:H,onClickConnectStart:O,onClickConnectEnd:z,nodesDraggable:Af,autoPanOnNodeFocus:Yf,nodesConnectable:xf,nodesFocusable:of,edgesFocusable:y0,edgesReconnectable:T0,elementsSelectable:Qu,elevateNodesOnSelect:x6,elevateEdgesOnSelect:z2,minZoom:v0,maxZoom:iu,nodeExtent:uf,onNodesChange:C6,onEdgesChange:W2,snapToGrid:i,snapGrid:I,connectionMode:p,translateExtent:K0,connectOnClick:O3,defaultEdgeOptions:Jy,fitView:V3,fitViewOptions:R6,onNodesDelete:c,onEdgesDelete:v,onDelete:C,onNodeDragStart:N,onNodeDrag:D,onNodeDragStop:x,onSelectionDrag:P,onSelectionDragStart:B,onSelectionDragStop:M,onMove:U,onMoveStart:G,onMoveEnd:W,noPanClassName:jy,nodeOrigin:F0,rfId:D3,autoPanOnConnect:L3,autoPanOnNodeDrag:K2,autoPanSpeed:Z2,onError:N1,connectionRadius:I1,isValidConnection:v6,selectNodesOnDrag:$f,nodeDragThreshold:q2,connectionDragThreshold:E2,onBeforeDelete:k,debug:Y3,ariaLabelConfig:B3,zIndexMode:I6}),o.jsx(_T,{onInit:A,onNodeClick:J,onEdgeClick:F,onNodeMouseEnter:q,onNodeMouseMove:Z,onNodeMouseLeave:V,onNodeContextMenu:L,onNodeDoubleClick:r,nodeTypes:$,edgeTypes:j,connectionLineType:n,connectionLineStyle:_f,connectionLineComponent:s,connectionLineContainerStyle:ff,selectionKeyCode:Gf,selectionOnDrag:jf,selectionMode:Wf,deleteKeyCode:Kf,multiSelectionKeyCode:Zf,panActivationKeyCode:Of,zoomActivationKeyCode:h,onlyRenderVisibleElements:lf,defaultViewport:X0,translateExtent:K0,minZoom:v0,maxZoom:iu,preventScrolling:Au,zoomOnScroll:o0,zoomOnPinch:Bf,zoomOnDoubleClick:nf,panOnScroll:b0,panOnScrollSpeed:i0,panOnScrollMode:a0,panOnDrag:d0,onPaneClick:Hu,onPaneMouseEnter:oy,onPaneMouseMove:J_,onPaneMouseLeave:ay,onPaneScroll:t,onPaneContextMenu:Hf,paneClickDistance:Df,nodeClickDistance:If,onSelectionContextMenu:w,onSelectionStart:Y,onSelectionEnd:R,onReconnect:Q0,onReconnectStart:af,onReconnectEnd:h0,onEdgeContextMenu:e0,onEdgeDoubleClick:S6,onEdgeMouseEnter:dy,onEdgeMouseMove:ey,onEdgeMouseLeave:$y,reconnectRadius:F_,defaultMarkerColor:vf,noDragClassName:G2,noWheelClassName:Q_,noPanClassName:jy,rfId:D3,disableKeyboardA11y:N3,nodeExtent:uf,viewport:EQ,onViewportChange:gu}),o.jsx(CD,{onSelectionChange:S}),Rf,o.jsx(TD,{proOptions:j1,position:X3}),o.jsx(wD,{rfId:D3,disableKeyboardA11y:N3})]})})}var lq=CZ(JT);var yh=Iu.error014();function FT({dimensions:f,lineWidth:u,variant:_,className:y}){return o.jsx("path",{strokeWidth:u,d:`M${f[0]/2} 0 V${f[1]} M0 ${f[1]/2} H${f[0]}`,className:B0(["react-flow__background-pattern",_,y])})}function QT({radius:f,className:u}){return o.jsx("circle",{cx:f,cy:f,r:f,className:B0(["react-flow__background-pattern","dots",u])})}var o_;(function(f){f.Lines="lines",f.Dots="dots",f.Cross="cross"})(o_||(o_={}));var AT={[o_.Dots]:1,[o_.Lines]:1,[o_.Cross]:6},UT=(f)=>({transform:f.transform,patternId:`pattern-${f.rfId}`});function $q({id:f,variant:u=o_.Dots,gap:_=20,size:y,lineWidth:l=1,offset:$=0,color:j,bgColor:J,style:F,className:A,patternClassName:U}){let G=a.useRef(null),{transform:W,patternId:K}=kf(UT,W0),E=y||AT[u],H=u===o_.Dots,O=u===o_.Cross,z=Array.isArray(_)?_:[_,_],q=[z[0]*W[2]||1,z[1]*W[2]||1],Z=E*W[2],V=Array.isArray($)?$:[$,$],L=O?[Z,Z]:q,r=[V[0]*W[2]||1+L[0]/2,V[1]*W[2]||1+L[1]/2],N=`${K}${f?f:""}`;return o.jsxs("svg",{className:B0(["react-flow__background",A]),style:{...F,...h5,"--xy-background-color-props":J,"--xy-background-pattern-color-props":j},ref:G,"data-testid":"rf__background",children:[o.jsx("pattern",{id:N,x:W[0]%q[0],y:W[1]%q[1],width:q[0],height:q[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${r[0]},-${r[1]})`,children:H?o.jsx(QT,{radius:Z/2,className:U}):o.jsx(FT,{dimensions:L,lineWidth:l,variant:u,className:U})}),o.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${N})`})]})}$q.displayName="Background";var jq=a.memo($q);function WT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:o.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function GT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:o.jsx("path",{d:"M0 0h32v4.2H0z"})})}function zT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:o.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 KT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:o.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 ZT(){return o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:o.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 R5({children:f,className:u,..._}){return o.jsx("button",{type:"button",className:B0(["react-flow__controls-button",u]),..._,children:f})}var qT=(f)=>({isInteractive:f.nodesDraggable||f.nodesConnectable||f.elementsSelectable,minZoomReached:f.transform[2]<=f.minZoom,maxZoomReached:f.transform[2]>=f.maxZoom,ariaLabelConfig:f.ariaLabelConfig});function Jq({style:f,showZoom:u=!0,showFitView:_=!0,showInteractive:y=!0,fitViewOptions:l,onZoomIn:$,onZoomOut:j,onFitView:J,onInteractiveChange:F,className:A,children:U,position:G="bottom-left",orientation:W="vertical","aria-label":K}){let E=z0(),{isInteractive:H,minZoomReached:O,maxZoomReached:z,ariaLabelConfig:q}=kf(qT,W0),{zoomIn:Z,zoomOut:V,fitView:L}=SF(),r=()=>{Z(),$?.()},N=()=>{V(),j?.()},D=()=>{L(l),J?.()},x=()=>{E.setState({nodesDraggable:!H,nodesConnectable:!H,elementsSelectable:!H}),F?.(!H)};return o.jsxs(b5,{className:B0(["react-flow__controls",W==="horizontal"?"horizontal":"vertical",A]),position:G,style:f,"data-testid":"rf__controls","aria-label":K??q["controls.ariaLabel"],children:[u&&o.jsxs(o.Fragment,{children:[o.jsx(R5,{onClick:r,className:"react-flow__controls-zoomin",title:q["controls.zoomIn.ariaLabel"],"aria-label":q["controls.zoomIn.ariaLabel"],disabled:z,children:o.jsx(WT,{})}),o.jsx(R5,{onClick:N,className:"react-flow__controls-zoomout",title:q["controls.zoomOut.ariaLabel"],"aria-label":q["controls.zoomOut.ariaLabel"],disabled:O,children:o.jsx(GT,{})})]}),_&&o.jsx(R5,{className:"react-flow__controls-fitview",onClick:D,title:q["controls.fitView.ariaLabel"],"aria-label":q["controls.fitView.ariaLabel"],children:o.jsx(zT,{})}),y&&o.jsx(R5,{className:"react-flow__controls-interactive",onClick:x,title:q["controls.interactive.ariaLabel"],"aria-label":q["controls.interactive.ariaLabel"],children:H?o.jsx(ZT,{}):o.jsx(KT,{})}),U]})}Jq.displayName="Controls";var Fq=a.memo(Jq);function ET({id:f,x:u,y:_,width:y,height:l,style:$,color:j,strokeColor:J,strokeWidth:F,className:A,borderRadius:U,shapeRendering:G,selected:W,onClick:K}){let{background:E,backgroundColor:H}=$||{},O=j||E||H;return o.jsx("rect",{className:B0(["react-flow__minimap-node",{selected:W},A]),x:u,y:_,rx:U,ry:U,width:y,height:l,style:{fill:O,stroke:J,strokeWidth:F},shapeRendering:G,onClick:K?(z)=>K(z,f):void 0})}var HT=a.memo(ET),VT=(f)=>f.nodes.map((u)=>u.id),rF=(f)=>f instanceof Function?f:()=>f;function OT({nodeStrokeColor:f,nodeColor:u,nodeClassName:_="",nodeBorderRadius:y=5,nodeStrokeWidth:l,nodeComponent:$=HT,onClick:j}){let J=kf(VT,W0),F=rF(u),A=rF(f),U=rF(_),G=typeof window>"u"||!!window.chrome?"crispEdges":"geometricPrecision";return o.jsx(o.Fragment,{children:J.map((W)=>o.jsx(NT,{id:W,nodeColorFunc:F,nodeStrokeColorFunc:A,nodeClassNameFunc:U,nodeBorderRadius:y,nodeStrokeWidth:l,NodeComponent:$,onClick:j,shapeRendering:G},W))})}function XT({id:f,nodeColorFunc:u,nodeStrokeColorFunc:_,nodeClassNameFunc:y,nodeBorderRadius:l,nodeStrokeWidth:$,shapeRendering:j,NodeComponent:J,onClick:F}){let{node:A,x:U,y:G,width:W,height:K}=kf((E)=>{let H=E.nodeLookup.get(f);if(!H)return{node:void 0,x:0,y:0,width:0,height:0};let O=H.internals.userNode,{x:z,y:q}=H.internals.positionAbsolute,{width:Z,height:V}=R1(O);return{node:O,x:z,y:q,width:Z,height:V}},W0);if(!A||A.hidden||!zF(A))return null;return o.jsx(J,{x:U,y:G,width:W,height:K,style:A.style,selected:!!A.selected,className:y(A),color:u(A),borderRadius:l,strokeColor:_(A),strokeWidth:$,shapeRendering:j,onClick:F,id:A.id})}var NT=a.memo(XT),LT=a.memo(OT),YT=200,BT=150,DT=(f)=>!f.hidden,wT=(f)=>{let u={x:-f.transform[0]/f.transform[2],y:-f.transform[1]/f.transform[2],width:f.width/f.transform[2],height:f.height/f.transform[2]};return{viewBB:u,boundingRect:f.nodeLookup.size>0?UF(y3(f.nodeLookup,{filter:DT}),u):u,rfId:f.rfId,panZoom:f.panZoom,translateExtent:f.translateExtent,flowWidth:f.width,flowHeight:f.height,ariaLabelConfig:f.ariaLabelConfig}},TT="react-flow__minimap-desc";function Qq({style:f,className:u,nodeStrokeColor:_,nodeColor:y,nodeClassName:l="",nodeBorderRadius:$=5,nodeStrokeWidth:j,nodeComponent:J,bgColor:F,maskColor:A,maskStrokeColor:U,maskStrokeWidth:G,position:W="bottom-right",onClick:K,onNodeClick:E,pannable:H=!1,zoomable:O=!1,ariaLabel:z,inversePan:q,zoomStep:Z=1,offsetScale:V=5}){let L=z0(),r=a.useRef(null),{boundingRect:N,viewBB:D,rfId:x,panZoom:c,translateExtent:v,flowWidth:C,flowHeight:S,ariaLabelConfig:B}=kf(wT,W0),P=f?.width??YT,M=f?.height??BT,w=N.width/P,Y=N.height/M,R=Math.max(w,Y),k=R*P,p=R*M,n=V*R,_f=N.x-(k-N.width)/2-n,s=N.y-(p-N.height)/2-n,ff=k+n*2,Kf=p+n*2,Gf=`${TT}-${x}`,jf=a.useRef(0),Wf=a.useRef();jf.current=R,a.useEffect(()=>{if(r.current&&c)return Wf.current=IK({domNode:r.current,panZoom:c,getTransform:()=>L.getState().transform,getViewScale:()=>jf.current}),()=>{Wf.current?.destroy()}},[c]),a.useEffect(()=>{Wf.current?.update({translateExtent:v,width:C,height:S,inversePan:q,pannable:H,zoomStep:Z,zoomable:O})},[H,O,q,Z,v,C,S]);let Of=K?(i)=>{let[I,lf]=Wf.current?.pointer(i)||[0,0];K(i,{x:I,y:lf})}:void 0,Zf=E?a.useCallback((i,I)=>{let lf=L.getState().nodeLookup.get(I).internals.userNode;E(i,lf)},[]):void 0,h=z??B["minimap.ariaLabel"];return o.jsx(b5,{position:W,style:{...f,"--xy-minimap-background-color-props":typeof F==="string"?F:void 0,"--xy-minimap-mask-background-color-props":typeof A==="string"?A:void 0,"--xy-minimap-mask-stroke-color-props":typeof U==="string"?U:void 0,"--xy-minimap-mask-stroke-width-props":typeof G==="number"?G*R:void 0,"--xy-minimap-node-background-color-props":typeof y==="string"?y:void 0,"--xy-minimap-node-stroke-color-props":typeof _==="string"?_:void 0,"--xy-minimap-node-stroke-width-props":typeof j==="number"?j:void 0},className:B0(["react-flow__minimap",u]),"data-testid":"rf__minimap",children:o.jsxs("svg",{width:P,height:M,viewBox:`${_f} ${s} ${ff} ${Kf}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":Gf,ref:r,onClick:Of,children:[h&&o.jsx("title",{id:Gf,children:h}),o.jsx(LT,{onClick:Zf,nodeColor:y,nodeStrokeColor:_,nodeBorderRadius:$,nodeClassName:l,nodeStrokeWidth:j,nodeComponent:J}),o.jsx("path",{className:"react-flow__minimap-mask",d:`M${_f-n},${s-n}h${ff+n*2}v${Kf+n*2}h${-ff-n*2}z + M${D.x},${D.y}h${D.width}v${D.height}h${-D.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}Qq.displayName="MiniMap";var lh=a.memo(Qq),rT=(f)=>(u)=>f?`${Math.max(1/u.transform[2],1)}`:void 0,MT={[s_.Line]:"right",[s_.Handle]:"bottom-right"};function PT({nodeId:f,position:u,variant:_=s_.Handle,className:y,style:l=void 0,children:$,color:j,minWidth:J=10,minHeight:F=10,maxWidth:A=Number.MAX_VALUE,maxHeight:U=Number.MAX_VALUE,keepAspectRatio:G=!1,resizeDirection:W,autoScale:K=!0,shouldResize:E,onResizeStart:H,onResize:O,onResizeEnd:z}){let q=bZ(),Z=typeof f==="string"?f:q,V=z0(),L=a.useRef(null),r=_===s_.Handle,N=kf(a.useCallback(rT(r&&K),[r,K]),W0),D=a.useRef(null),x=u??MT[_];a.useEffect(()=>{if(!L.current||!Z)return;if(!D.current)D.current=iK({domNode:L.current,nodeId:Z,getStoreItems:()=>{let{nodeLookup:v,transform:C,snapGrid:S,snapToGrid:B,nodeOrigin:P,domNode:M}=V.getState();return{nodeLookup:v,transform:C,snapGrid:S,snapToGrid:B,nodeOrigin:P,paneDomNode:M}},onChange:(v,C)=>{let{triggerNodeChanges:S,nodeLookup:B,parentLookup:P,nodeOrigin:M}=V.getState(),w=[],Y={x:v.x,y:v.y},R=B.get(Z);if(R&&R.expandParent&&R.parentId){let k=R.origin??M,p=v.width??R.measured.width??0,n=v.height??R.measured.height??0,_f={id:R.id,parentId:R.parentId,rect:{width:p,height:n,...KF({x:v.x??R.position.x,y:v.y??R.position.y},{width:p,height:n},R.parentId,B,k)}},s=r5([_f],B,P,M);w.push(...s),Y.x=v.x?Math.max(k[0]*p,v.x):void 0,Y.y=v.y?Math.max(k[1]*n,v.y):void 0}if(Y.x!==void 0&&Y.y!==void 0){let k={id:Z,type:"position",position:{...Y}};w.push(k)}if(v.width!==void 0&&v.height!==void 0){let p={id:Z,type:"dimensions",resizing:!0,setAttributes:!W?!0:W==="horizontal"?"width":"height",dimensions:{width:v.width,height:v.height}};w.push(p)}for(let k of C){let p={...k,type:"position"};w.push(p)}S(w)},onEnd:({width:v,height:C})=>{let S={id:Z,type:"dimensions",resizing:!1,dimensions:{width:v,height:C}};V.getState().triggerNodeChanges([S])}});return D.current.update({controlPosition:x,boundaries:{minWidth:J,minHeight:F,maxWidth:A,maxHeight:U},keepAspectRatio:G,resizeDirection:W,onResizeStart:H,onResize:O,onResizeEnd:z,shouldResize:E}),()=>{D.current?.destroy()}},[x,J,F,A,U,G,H,O,z,E]);let c=x.split("-");return o.jsx("div",{className:B0(["react-flow__resize-control","nodrag",...c,_,y]),ref:L,style:{...l,scale:N,...j&&{[r?"backgroundColor":"borderColor"]:j}},children:$})}var $h=a.memo(PT);var X=fy.default.createElement,{useEffect:b1}=fy.default,wu=fy.default.useState,e_=fy.default.useRef,N6=[{id:"in-left",side:"left",position:Uf.Left,style:{top:"50%"}},{id:"in-top-left",side:"top",slot:"left",slotIndex:-1,position:Uf.Top,style:{left:"28%"}},{id:"in-top-mid",side:"top",slot:"mid",slotIndex:0,position:Uf.Top,style:{left:"50%"}},{id:"in-top-right",side:"top",slot:"right",slotIndex:1,position:Uf.Top,style:{left:"72%"}},{id:"in-bottom-left",side:"bottom",slot:"left",slotIndex:-1,position:Uf.Bottom,style:{left:"28%"}},{id:"in-bottom-mid",side:"bottom",slot:"mid",slotIndex:0,position:Uf.Bottom,style:{left:"50%"}},{id:"in-bottom-right",side:"bottom",slot:"right",slotIndex:1,position:Uf.Bottom,style:{left:"72%"}}],H6=[{id:"out-right",position:Uf.Right,style:{top:"50%"}}],Aq=["#4eb7a8","#d7a13a","#69aee8","#e0835f","#b7d86b","#d98bd2","#5fc6bf"],U3=236,W3=88,Uq=15000,ST=10,RF=96,x1=72,xF=64,Wq=12;function I5(){return typeof document>"u"||document.visibilityState!=="hidden"}function Gq(f,u){let _=Number.parseFloat(String(f||""));return Number.isFinite(_)?_/100:u}function CT(f,u,_){let y=String(f.side||"");if(y!=="top"&&y!=="bottom")return 0;let l=Number(f.slotIndex||0),$=y==="top"?"in-top-mid":"in-bottom-mid",j=u.get(f.id)||0,J=u.get($)||0;if(l===0)return J===0?-26:28+j*74;let F=_===0?Math.abs(l)*2:Math.sign(_)===Math.sign(l)?-3:3;if(J>0&&j===0)return-14+F;return 8+j*74+F}function c5(f){let u=f.filter(($,j)=>{let J=f[j-1];return!J||Math.abs(J.x-$.x)>0.5||Math.abs(J.y-$.y)>0.5});if(u.length<2)return"";let _=`M ${u[0].x},${u[0].y}`,y=u[0];for(let $=1;$0.5||Math.abs(W.y-y.y)>0.5)_+=` L ${W.x},${W.y}`;_+=` Q ${J.x},${J.y} ${K.x},${K.y}`,y=K}let l=u[u.length-1];return`${_} L ${l.x},${l.y}`}function Cq(f,u,_,y,l,$,j=""){let J=_>=f,F=Math.max(1,Math.abs(_-f)),A=Math.abs(y-u),U=Math.max(34,Math.min(118,F*0.26)),G=Math.min(280,Math.abs($));if(J&&l===Uf.Left&&G<4&&A<28&&F<420)return`M ${f},${u} C ${f+U},${u} ${_-U},${y} ${_},${y}`;if(J&&l===Uf.Left&&(j==="direct-forward-left"||F<=260&&A<=210)){let z=Math.max(42,Math.min(140,F*0.48)),q=Math.max(-28,Math.min(28,$*0.18));return`M ${f},${u} C ${f+z},${u+q} ${_-z},${y} ${_},${y}`}if(J){let z=f+U;if(l===Uf.Top||l===Uf.Bottom){let V=l===Uf.Top?-1:1,L=y+V*(54+G*0.42);return c5([{x:f,y:u},{x:z,y:u},{x:z+Math.min(120,F*0.18),y:L},{x:_,y:L},{x:_,y:y+V*34},{x:_,y}])}let q=_-U,Z=(u+y)/2+$;return c5([{x:f,y:u},{x:z,y:u},{x:z+Math.min(110,F*0.16),y:Z},{x:q-Math.min(90,F*0.12),y:Z},{x:q,y},{x:_,y}])}let E=l===Uf.Bottom?1:l===Uf.Top?-1:$>=0?1:-1,H=Math.max(f,_)+92+Math.min(180,G*0.52),O=E<0?Math.min(u,y)-84-G*0.62:Math.max(u,y)+84+G*0.62;if(l===Uf.Top||l===Uf.Bottom)return c5([{x:f,y:u},{x:f+U,y:u},{x:H,y:O},{x:_,y:O},{x:_,y:y+E*38},{x:_,y}]);return c5([{x:f,y:u},{x:f+U,y:u},{x:H,y:O},{x:_-U,y:O},{x:_-U,y},{x:_,y}])}function RT({data:f}){return X("div",{className:"pipeline-flow-node-body"},N6.map((u)=>X(iy,{key:u.id,id:u.id,type:"target",position:u.position,isConnectable:!1,className:`pipeline-flow-handle input ${u.side} slot-${u.slot||"mid"}`,style:u.style})),H6.map((u)=>X(iy,{key:u.id,id:u.id,type:"source",position:u.position,isConnectable:!1,className:"pipeline-flow-handle output right",style:u.style})),f?.label)}function xT({id:f,sourceX:u,sourceY:_,targetX:y,targetY:l,targetPosition:$,markerEnd:j,markerStart:J,style:F,data:A}){let U=Number(A?.laneOffset||0),G=Cq(u,_,y,l,$,U,String(A?.routeMode||""));return X(A3,{id:f,path:G,markerEnd:j,markerStart:J,style:F,interactionWidth:28})}var vT={pipelineCurve:xT},bT={pipelineNode:RT};function i5(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return L0(u)}function l1(f){let u=Number(f);if(!Number.isFinite(u)||u<0)return"--";let _=Math.round(u/1000);if(_<60)return`${_}s`;if(_<3600)return`${Math.floor(_/60)}m ${_%60}s`;return`${Math.floor(_/3600)}h ${Math.floor(_%3600/60)}m`}function vF(f){let u=Number(f);if(!Number.isFinite(u))return"--";return u.toLocaleString("zh-CN")}function zq(f){let u=Number(f);if(!Number.isFinite(u))return"--";return`${Math.round(Math.max(0,Math.min(1,u))*100)}%`}function Xf(f){return typeof f==="object"&&f!==null&&!Array.isArray(f)}function Vf(f){return Array.isArray(f)?f:[]}function Cf(f){if(!f)return null;let u=new Date(f);return Number.isNaN(u.getTime())?null:u.getTime()}function L6(f){return Number.isFinite(Number(f))?new Date(Number(f)).toISOString():""}function D6(...f){for(let u of f){let _=Cf(u);if(_!==null)return new Date(_).toISOString()}return""}function aF(...f){let u=f.map(Cf).filter((_)=>_!==null);return u.length>0?new Date(Math.max(...u)).toISOString():""}function dF(f){return["succeeded","failed","skipped","cancelled","canceled","completed"].includes(String(f||"").toLowerCase())}function Rq(f){let u=bq(f).toLowerCase();return["running","active","in-progress","in_progress"].includes(u)}function Kq(f,u="status"){return f.reduce((_,y)=>{let l=String(y?.[u]||"unknown").toLowerCase();return _[l]=(_[l]||0)+1,_},{})}function xq(f){if(!f||typeof f!=="string")return null;try{let u=JSON.parse(f);return Xf(u)?u:null}catch{return null}}function bF(f){let u=f.map(xq).filter(($)=>Boolean($)),_=u.flatMap(($)=>[$.timestamp,$.createdAt,$.updatedAt]).filter(Boolean),y=aF(..._),l=Array.from(new Set(u.map(($)=>String($.event||$.action||$.type||"")).filter(Boolean))).slice(0,3);return{total:f.length,parsed:u.length,lastAt:y,eventKinds:l}}function g5(f){if(f===null||f===void 0)return"--";if(typeof f==="boolean")return f?"是":"否";if(typeof f==="number")return String(f);if(typeof f==="string")return f.length>80?`${f.slice(0,77)}...`:f;if(Array.isArray(f))return`${f.length} 项`;if(typeof f==="object")return`${Object.keys(f).length} 字段`;return String(f)}function vq(f,u=280){if(f===null||f===void 0)return"";let y=(typeof f==="string"?f:String(f)).replace(/\r\n/gu,` +`).trim();return y.length>u?`${y.slice(0,Math.max(0,u-1))}...`:y}function bq(f){if(typeof f==="string")return f;if(Xf(f))return String(f.status||f.state||f.phase||"unknown");return"unknown"}function hT(f){return f.filter((u)=>u&&u.value!==void 0&&u.value!==null&&String(u.value)!=="")}function mF({items:f}){let u=hT(Vf(f));return X("div",{className:"pipeline-kv-grid"},u.map((_)=>X("span",{key:_.label},X("b",null,_.label),X("span",null,_.value))))}function eF({items:f}){let u=Vf(f).map((_)=>String(_||"")).filter(Boolean);if(u.length===0)return null;return X("div",{className:"pipeline-chip-row"},u.map((_,y)=>X("span",{key:`${y}-${_}`},_)))}function iF(f,u){let _=String(u?.procedureRunId||""),y=Vf(f?.procedureRuns);return y.find((l)=>String($1(l))===_)||y.at(-1)||null}function IT(f,u){let _=String(u||"");if(!_)return null;return Vf(f?.procedureRuns).find((y)=>$1(y)===_)||null}function hF(f){return Vf(f?.attempts).length}function Zq(f){return Vf(f?.attempts).reduce((u,_)=>u+e5(_).length,0)}function e5(f){return Vf(f?.opencodeMessages?.steps).filter(Xf)}function hq(f){let u=String(f?.status||"").toLowerCase();if(["error","failed","failure"].includes(u))return"failed";if(["completed","succeeded","success"].includes(u))return"succeeded";if(["running","started","in_progress"].includes(u))return"running";return"unknown"}function cT(f,u){let _=gF(f.map(($)=>$?.agent)).slice(0,3),y=gF(f.map(($)=>$?.model)).slice(0,3),l=u.length<=2?u.map(($)=>`session ${$}`):[`sessions ${u.length}`,...u.slice(0,2).map(($)=>`session ${$}`)];return[..._.map(($)=>`agent ${$}`),...y.map(($)=>`model ${$}`),...l]}function V6(f,u=0){return String(f?.messageId||f?.index||"")||`step-${u}`}function pT({steps:f,sessionIds:u,sessionFacts:_,matchedStepKey:y}){let l=Vf(f),$=l.findIndex((O,z)=>V6(O,z)===y),j=$>=0?l[$]:null,J=l.flatMap((O)=>[Cf(O?.createdAt),Cf(O?.completedAt)]).filter((O)=>O!==null),F=J.length>0?Math.min(...J):null,A=J.length>0?Math.max(...J):null,U=F!==null&&A!==null?Math.max(0,A-F):null,G=l.reduce((O,z)=>O+Vf(z?.parts).filter((q)=>String(q?.type||"").toLowerCase()==="tool").length,0),W=l.reduce((O,z)=>O+Vf(z?.parts).filter((q)=>["text","reasoning"].includes(String(q?.type||"").toLowerCase())).length,0),K=l.reduce((O,z)=>O+Vf(z?.parts).filter((q)=>String(q?.type||"").toLowerCase()==="tool"&&hq(q)==="failed").length,0),E=[`${l.length} steps`,`${u.length} sessions`,`${W} messages`,`${G} tools`,U!==null?`duration ${l1(U)}`:"",K>0?`${K} failed tools`:""].filter(Boolean),H=j?[`Step ${j?.index??$+1}`,String(j?.role||"role --"),j?.model?`model ${j.model}`:"",j?.finish?`finish ${j.finish}`:"",j?.durationMs!==void 0&&j?.durationMs!==null?`duration ${l1(j.durationMs)}`:""].filter(Boolean):[];return X("section",{className:"pipeline-trace-timeline","data-testid":"pipeline-step-timeline"},X("div",{className:"pipeline-trace-head"},X("div",null,X("b",null,"OpenCode Trace"),X("span",null,"Trace 使用 Codex Queue 统一样式展示完整 agent loop;Pipeline 旧 step/message/tool 卡片样式已废弃。")),X("div",{className:"pipeline-trace-session-head","data-testid":"pipeline-step-timeline-session"},X("span",null,E.join(" / ")||"Trace"),_.length>0?X(eF,{items:_}):null)),j?X("div",{className:"pipeline-trace-focus","data-testid":"pipeline-trace-matched-step"},X("span",{className:"codex-output-channel"},"Matched"),X("strong",null,`Gantt selection -> ${H.join(" / ")}`),X("time",null,`${i5(j?.createdAt)} -> ${i5(j?.completedAt)}`)):null,X(E4,{port:rG,input:l,className:"codex-transcript pipeline-trace",testId:"pipeline-opencode-step-trace",emptyText:"暂无 OpenCode Trace 输出",keepRecentToolCalls:3}))}function O6(f){return Vf(f).flatMap((u)=>{if(Xf(u))return[u];let _=xq(u);return _?[_]:[]})}function V1(f){return String(f?.event||f?.action||f?.requestedAction||f?.type||"").toLowerCase()}function gy(f){return D6(f?.timestamp,f?.createdAt,f?.updatedAt,f?.startedAt,f?.finishedAt)}function kT(f){return Cf(gy(f))}function f2(f){return String(f?.attempt||f?.id||"")}function gF(f){let u=new Set,_=[];for(let y of f){let l=String(y||"");if(!l||u.has(l))continue;u.add(l),_.push(l)}return _}function qq(f){switch(String(f||"").toLowerCase()){case"monitor":return"monitor";case"webui":return"webui";case"cli":return"cli";case"system":return"runner";default:return String(f||"--")}}function ny(f){return String(f?.requestedAction||f?.action||"").toLowerCase()}function X6(f){switch(ny(f)){case"guide":return"引导";case"modify":return"修改";case"approve":return"审核通过";case"restart":return"重启";case"redo":return"重做";default:return String(f?.requestedAction||f?.action||"控制")}}function Eq(f){switch(V1(f)){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`${X6(f)} 已发起`;case"control-command-applied":return`${X6(f)} 已生效`;case"control-command-ignored":return`${X6(f)} 已忽略`;default:return String(f?.event||f?.action||f?.requestedAction||"event")}}function Hq(f){return vq(f?.promptPreview||f?.reasonPreview||f?.prompt||f?.reason||"",240)}function mT(f){let u=String(f?.prompt||""),_=String(f?.reason||f?.restartReason||""),y=u?"":String(f?.promptPreview||""),l=_?"":String(f?.reasonPreview||"");return[u||y?{label:u?"prompt":"prompt preview",value:u||y}:null,_||l?{label:_?"reason":"reason preview",value:_||l}:null,Vf(f?.resetNodeIds).length>0?{label:"reset nodes",value:Vf(f.resetNodeIds).join(", ")}:null,Vf(f?.runningResetNodeIds).length>0?{label:"interrupted running nodes",value:Vf(f.runningResetNodeIds).join(", ")}:null,Vf(f?.interruptedProcedureRunIds).length>0?{label:"interrupted procedures",value:Vf(f.interruptedProcedureRunIds).join(", ")}:null,f?.interruptedProcedureRunId?{label:"interrupted procedure",value:String(f.interruptedProcedureRunId)}:null].filter(Boolean)}function IF(f){let u=e5(f),_=u.map((F)=>Cf(F?.createdAt)).filter((F)=>F!==null),y=u.map((F)=>Cf(F?.completedAt)??Cf(F?.createdAt)).filter((F)=>F!==null),l=O6(f?.controlEventRecords).map((F)=>kT(F)).filter((F)=>F!==null),$=Vf(f?.assistantOutputs).map((F)=>Cf(F?.updatedAt)).filter((F)=>F!==null),j=_[0]??l[0]??$[0]??null,J=y.at(-1)??l.at(-1)??$.at(-1)??j;return{startMs:j,endMs:J}}function iT(f,u,_,y,l=""){let $=Vf(f?.procedureRuns).filter((J)=>u2(J,u)===_);if($.length===0)return null;if(l){let J=$.find((F)=>$1(F)===l);if(J)return J}if(y===null)return $.at(-1)||null;let j=$.find((J)=>{let F=Cf(p5(J,f)),A=Cf(k5(J,f))??F;return F!==null&&A!==null&&y>=F-1000&&y<=A+1000});if(j)return j;return $.slice().sort((J,F)=>{let A=Cf(p5(J,f))??y,U=Cf(k5(J,f))??A,G=Cf(p5(F,f))??y,W=Cf(k5(F,f))??G,K=Math.min(Math.abs(A-y),Math.abs(U-y)),E=Math.min(Math.abs(G-y),Math.abs(W-y));return K-E})[0]||null}function Iq(f,u){let _=Vf(f?.attempts).filter(Xf);if(_.length===0)return null;let y=String(u?.attempt||"");if(y){let j=_.find((J)=>f2(J)===y);if(j)return j}let l=Number.isFinite(Number(u?.ms))?Number(u.ms):null;if(l===null)return _.at(-1)||null;let $=_.find((j)=>{let J=IF(j);return Number.isFinite(J.startMs)&&Number.isFinite(J.endMs)&&l>=Number(J.startMs)-1000&&l<=Number(J.endMs)+1000});if($)return $;return _.slice().sort((j,J)=>{let F=IF(j),A=IF(J),U=Math.min(Math.abs(Number(F.startMs??l)-l),Math.abs(Number(F.endMs??l)-l)),G=Math.min(Math.abs(Number(A.startMs??l)-l),Math.abs(Number(A.endMs??l)-l));return U-G})[0]||_.at(-1)||null}function cq(f,u){let _=e5(f);if(_.length===0)return{step:null,stepIndex:-1,stepKey:""};if(u===null){let $=_[0];return{step:$,stepIndex:0,stepKey:V6($,0)}}for(let $=0;$<_.length;$+=1){let j=_[$],J=Cf(j?.createdAt)??Cf(j?.completedAt),F=Cf(j?.completedAt)??J;if(J!==null&&F!==null&&u>=J-1000&&u<=F+1000)return{step:j,stepIndex:$,stepKey:V6(j,$)}}let y=_.findIndex(($)=>{let j=Cf($?.createdAt)??Cf($?.completedAt);return j!==null&&j>=u});if(y>=0){let $=_[y];return{step:$,stepIndex:y,stepKey:V6($,y)}}let l=Math.max(0,_.length-1);return{step:_[l],stepIndex:l,stepKey:V6(_[l],l)}}function gT(f,u){let _=String(u?.runId||f?.runId||"");if(String(u?.mode||"")==="interval"){let A=u?.interval||{},U=iF(f,A)||A.raw||{};return{mode:"interval",runId:_,interval:A,marker:null,nodeId:String(A?.nodeId||u2(U,_)||""),procedure:U,attempt:null,matchedStep:null,matchedStepIndex:-1,matchedStepKey:""}}let y=Xf(u?.marker)?u.marker:{},l=Number.isFinite(Number(y?.ms))?Number(y.ms):null,$=String(y?.nodeId||""),j=$?iT(f,_,$,l,String(y?.procedureRunId||"")):null,J=j?Iq(j,y):null,F=J?cq(J,l):{step:null,stepIndex:-1,stepKey:""};return{mode:"event",runId:_,interval:null,marker:y,nodeId:$,procedure:j,attempt:J,matchedStep:F.step,matchedStepIndex:F.stepIndex,matchedStepKey:F.stepKey}}function nT({procedure:f,matchedStepKey:u="",matchedAttemptId:_=""}){let y=Vf(f?.attempts);if(y.length===0)return X(pu,{title:"暂无 attempt 详情",text:"当前 procedure 还没有可展示的 attempt / OpenCode Trace;若刚点击甘特线,请等待 node 详情抓取完成。"});return y.map((l,$)=>{let j=l?.opencodeMessages||{},J=e5(l),F=Vf(j.sessionIds).map((W)=>String(W)).filter(Boolean),A=cT(J,F),U=f2(l)||`attempt-${$+1}`,G=J.reduce((W,K)=>W+Vf(K?.parts).filter((E)=>String(E?.type||"").toLowerCase()==="tool"&&hq(E)==="failed").length,0);return X("article",{key:U,className:`pipeline-attempt-card ${_===U?"matched":""}`},X("div",{className:"pipeline-attempt-head"},X("div",null,X("strong",null,U),X("span",null,j.source||"opencode")),X("div",{className:"pipeline-attempt-badges"},X("span",null,`${J.length} steps`),X("span",null,`${j.toolCallCount??"--"} tools`),G>0?X("span",{className:"danger"},`${G} failed`):null)),X(mF,{items:[{label:"messages",value:j.messageCount??"--"},{label:"steps",value:j.stepCount??J.length},{label:"tools",value:j.toolCallCount??"--"},{label:"updated",value:zf(j.updatedAt)},{label:"sessions",value:F.join(", ")||"--"}]}),J.length===0?X("p",{className:"muted paragraph"},"当前 attempt 尚未返回 OpenCode Trace;请确认 D601 pipeline-control 已重建并重新抓取。"):X(pT,{steps:J,sessionIds:F,sessionFacts:A,matchedStepKey:u}))})}function cF(f,u){return`${f}::${u}`}function n5(f,u,_){if(!Xf(f))return null;return String(f.runId||"")===u&&String(f.nodeId||"")===_?f:null}function tT(f,u){let _=Xf(f)?f:{};if(!Xf(u))return _;let y=Vf(u.attempts),l=Vf(_.attempts);return{..._,...u,attempts:y.length>0?y:l}}function sT(f,u,_,y){if(!n5(u,_,y))return f;let l=Vf(u.procedureRuns),$=Xf(f)?f:{};return{...$,...u,controlCommands:Vf(u.controlCommands).length>0?u.controlCommands:$.controlCommands,controlEvents:Vf(u.controlEvents).length>0?u.controlEvents:$.controlEvents,procedureRuns:l.length>0?l:$.procedureRuns}}function oT({selection:f,runDetails:u,nodeDetails:_,nodeDetailsState:y,onRaw:l,onCollapse:$}){if(!f?.mode)return X("aside",{className:"pipeline-gantt-detail-panel empty","data-testid":"pipeline-gantt-detail-panel"},X("div",{className:"pipeline-gantt-detail-head"},X("div",null,X("span",{className:"panel-eyebrow"},"Gantt Detail"),X("h3",null,"未选择元素")),X("button",{type:"button",className:"ghost-btn mini",onClick:$,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起")),X(pu,{title:"选择一条执行线或一个控制点",text:"点击甘特图中的 node 执行线、prompt 点或控制点,在这里查看结构化过程和 OpenCode step。"}));let j=String(f?.runId||""),J=String(f?.interval?.nodeId||f?.marker?.nodeId||""),F=u?.runId===j?u.details:null,A=n5(_,j,J),U=String(y?.runId||"")===j&&String(y?.nodeId||"")===J,G=sT(F,A,j,J),W=(String(u?.runId||"")!==j||Boolean(u?.loading))&&!G,K=String(u?.runId||"")===j?String(u?.error||""):"",E=U?String(y?.error||""):"",H=G?gT(G,f):null,O=H?.interval||f?.interval||null,z=H?.marker||f?.marker||null,q=String(O?.procedureRunId||z?.procedureRunId||""),Z=A?IT(A,q)||iF(A,O||{procedureRunId:q}):null,V=H?.procedure||(G?iF(G,O||{procedureRunId:q}):null)||O?.raw||{};if(Z&&(hF(V)===0||Zq(Z)>=Zq(V)))V=tT(V,Z);let L=H?.attempt||null,r=String(H?.matchedStepKey||"");if(!L&&z&&hF(V)>0)L=Iq(V,z),r=String(cq(L,Number.isFinite(Number(z?.ms))?Number(z.ms):null).stepKey||"");let N=f2(L),D=hF(V)>0,x=U&&Boolean(y?.loading)&&!D,c=Boolean(W||x),v=[D?"":K,E].filter(Boolean).join(" / "),C=U&&y?.fetchedAt?y.fetchedAt:u?.fetchedAt,S=bq(V?.status||O?.status||z?.status||z?.event),B=f?.mode==="event"?z?.label||Eq(z?.raw||z)||"event":H?.nodeId||O?.nodeId||"node",P=z?mT(z?.raw||z):[],M=z?[V1(z?.raw||z)?`event ${V1(z?.raw||z)}`:"",z?.promptEvent?`prompt ${z.promptEvent}`:"",z?.action?`action ${z.action}`:"",z?.sourceKind?`source ${qq(z.sourceKind)}`:"",z?.sourceNodeId?`from ${z.sourceNodeId}`:"",z?.targetNodeId?`to ${z.targetNodeId}`:"",z?.snapReason?`draw ${z.snapReason}`:""].filter(Boolean):[];return X("aside",{className:"pipeline-gantt-detail-panel","data-testid":"pipeline-gantt-detail-panel"},X("div",{className:"pipeline-gantt-detail-head"},X("div",null,X("span",{className:"panel-eyebrow"},f?.mode==="event"?"Gantt Event Detail":"Gantt Line Detail"),X("h3",null,B)),X("div",{className:"pipeline-gantt-detail-head-actions"},X(uy,{status:S},S),X("button",{type:"button",className:"ghost-btn mini",onClick:$,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起"))),z?X("article",{className:"pipeline-event-card"},X("div",{className:"pipeline-event-card-head"},X("strong",null,z?.label||Eq(z?.raw||z)),X(eF,{items:M})),X(mF,{items:[{label:"event time",value:zf(z?.timestampIso||z?.timestamp||"--")},z?.snapped?{label:"drawn time",value:zf(z?.renderedTimestampIso||z?.ms)}:null,{label:"node",value:z?.nodeId||"--"},{label:"procedure",value:z?.procedureRunId||$1(V)||"--"},{label:"attempt",value:z?.attempt||N||"--"},{label:"source kind",value:z?.sourceKind?qq(z.sourceKind):"--"},{label:"source node",value:z?.sourceNodeId||"--"},{label:"target node",value:z?.targetNodeId||"--"},{label:"command",value:z?.commandId||z?.eventId||"--"},z?.snapReason?{label:"placement",value:z.snapReason}:null]}),P.length>0?X("div",{className:"pipeline-event-blocks"},P.map((w,Y)=>X("section",{key:`${w.label}-${Y}`,className:"pipeline-event-text-block"},X("b",null,w.label),X("p",null,w.value)))):null,Hq(z?.raw||z)?X("p",{className:"pipeline-text-preview"},Hq(z?.raw||z)):null):null,X(mF,{items:[{label:"epoch",value:j||O?.runId||"--"},{label:"node",value:H?.nodeId||O?.nodeId||z?.nodeId||"--"},{label:"procedure",value:O?.procedureRunId||z?.procedureRunId||$1(V)||"--"},{label:"started",value:zf(O?.startedAt||V?.startedAt)},{label:"finished",value:zf(O?.finishedAt||V?.finishedAt)},{label:"duration",value:l1(O?.durationMs||V?.durationMs)},{label:"fetched",value:C?L0(C):"--"},H?.matchedStep?{label:"matched step",value:`Step ${H.matchedStep.index??H.matchedStepIndex+1}`}:null]}),c?X("div",{className:"form-success"},x?"正在抓取该 node 的 attempt / Trace...":"正在抓取 epoch 执行过程..."):null,X(H0,{error:v}),X("div",{className:"pipeline-gantt-detail-actions"},X(O1,{title:`Procedure ${O?.procedureRunId||z?.procedureRunId||H?.nodeId||"node"}`,data:V,onOpen:l,testId:"raw-pipeline-gantt-procedure"}),z?X(O1,{title:`Pipeline event ${z?.id||z?.commandId||z?.eventId||H?.nodeId||"event"}`,data:z?.raw||z,onOpen:l,testId:"raw-pipeline-gantt-event"}):null,G?X(O1,{title:`Pipeline run ${j||"--"}`,data:G,onOpen:l,testId:"raw-pipeline-gantt-node-details"}):null),!c&&!$1(V)&&!z?X(pu,{title:"暂无过程详情",text:"当前选择还没有可匹配的 procedure 运行记录。"}):null,!c&&$1(V)?X(nT,{procedure:V,matchedStepKey:r,matchedAttemptId:N}):null)}function aT({value:f}){let _=String(f||"--").split(/([_-])/u);return X(fy.default.Fragment,null,_.map((y,l)=>y==="-"||y==="_"?X(fy.default.Fragment,{key:l},y,X("wbr",null)):X(fy.default.Fragment,{key:l},y)))}async function a_(f,u={}){return wf(f,{invalidJsonPrefix:"Pipeline 返回了无效 JSON",...u})}function uy({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return X("span",{className:`status-badge ${_}`},u||f||"unknown")}function Eu({label:f,value:u,hint:_,tone:y}){return X("article",{className:`metric-card ${y||""}`},X("div",{className:"metric-label"},f),X("div",{className:"metric-value"},u),X("div",{className:"metric-hint"},_))}function v1({title:f,eyebrow:u,actions:_,children:y,className:l}){return X("section",{className:`panel ${l||""}`},X("div",{className:"panel-head"},X("div",null,u?X("p",{className:"panel-eyebrow"},u):null,X("h2",null,f)),_?X("div",{className:"panel-actions"},_):null),X("div",{className:"panel-body"},y))}function O1({title:f,data:u,onOpen:_,testId:y}){return X("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function y1({title:f,subtitle:u,facts:_,data:y,onRaw:l,testId:$}){let j=Vf(_).map((J)=>String(J||"")).filter(Boolean);return X("article",{className:"pipeline-evidence-row"},X("div",{className:"pipeline-evidence-main"},X("strong",null,f),u?X("span",null,u):null),X("div",{className:"pipeline-evidence-facts"},j.map((J,F)=>X("span",{key:`${F}-${J.slice(0,16)}`},J))),y!==void 0?X(O1,{title:f,data:y,onOpen:l,testId:$}):null)}function pu({title:f,text:u}){return X("div",{className:"empty-state"},X("strong",null,f),X("span",null,u))}function dT(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function eT(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function fr(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function ur(f){return{components:Array.isArray(f?.registry?.components)?f.registry.components:[],pipelines:Array.isArray(f?.pipelines)?f.pipelines:[],runs:Array.isArray(f?.runs)?f.runs:[]}}function Vq(f,u,_){let y=f?._unidesk?.arrayLimits?.[u],l=Number(y?.originalLength);return Number.isFinite(l)?l:_}function pq(f){if(!f||typeof f!=="object"||Array.isArray(f))return"--";return`${f.componentClass||"--"}/${f.id||"--"}`}function t5(f){if(!f||typeof f!=="object"||Array.isArray(f))return"";let u=String(f.componentClass||"").trim(),_=String(f.id||"").trim();return u&&_?`${u}/${_}`:""}function fQ(f){return f?.config&&typeof f.config==="object"&&!Array.isArray(f.config)?f.config:{}}function kq(f){let u=fQ(f),_=Array.isArray(u.nodes)?u.nodes:Array.isArray(f?.nodes)?f.nodes:[],y=new Map;for(let j of _){let J=String(j?.id||j?.nodeId||"");if(J)y.set(J,{...j,id:J})}let l=uQ(f),$=(j)=>{if(j&&!y.has(j))y.set(j,{id:j})};for(let j of _Q(f))Y6(j).forEach($);for(let j of l)$(String(j?.from||j?.source||"")),$(String(j?.to||j?.target||""));return Array.from(y.values())}function uQ(f){let u=fQ(f);return Array.isArray(u.edges)?u.edges:Array.isArray(f?.edges)?f.edges:[]}function _Q(f){let u=fQ(f);return Array.isArray(u.topologicalBatches)?u.topologicalBatches:Array.isArray(f?.topologicalBatches)?f.topologicalBatches:[]}function _r(f){let u=new Map;for(let _ of f){let y=t5(_);if(y)u.set(y,_);let l=Array.isArray(_?.refs)?_.refs:[];for(let $ of l){let j=t5($);if(j)u.set(j,_)}}return u}function Oq(f,u){let _=u.get(t5(f?.componentRef));if(_)return _;let y=t5({componentClass:f?.kind,id:f?.id});return y?u.get(y)||null:null}function Xq(f,u){let _=mq(f,u);return String(_?.status||"pending")}function mq(f,u){return(Array.isArray(f?.nodes)?f.nodes:[]).find((y)=>y?.nodeId===u||y?.id===u)||null}function yr(f){return f.reduce((u,_)=>{let y=String(_?.status||"unknown").toLowerCase();return u[y]=(u[y]||0)+1,u},{})}function lr(f){if(Array.isArray(f?.scorers))return f.scorers.filter(Xf);if(Array.isArray(f?.summary?.scorers))return f.summary.scorers.filter(Xf);if(Array.isArray(f?.artifact?.summary?.scorers))return f.artifact.summary.scorers.filter(Xf);return[]}function $r(f){if(Xf(f?.run))return f.run;if(Xf(f?.runSummary))return f.runSummary;return null}function jr(f,u){if(!Xf(f)&&!Xf(u))return null;if(!Xf(f))return u;if(!Xf(u))return f;return{...f,...u,request:Xf(f.request)||Xf(u.request)?{...Xf(f.request)?f.request:{},...Xf(u.request)?u.request:{}}:u.request??f.request,artifact:Xf(f.artifact)||Xf(u.artifact)?{...Xf(f.artifact)?f.artifact:{},...Xf(u.artifact)?u.artifact:{}}:u.artifact??f.artifact,summary:Xf(f.summary)||Xf(u.summary)?{...Xf(f.summary)?f.summary:{},...Xf(u.summary)?u.summary:{}}:u.summary??f.summary}}function s5(f){let u=lr(f),_=u.find((U)=>Xf(U?.score))||u[0]||null,y=Xf(_?.score)?_.score:{},l=Number(y.passed),$=Number(y.total),j=Number(y.ratio),J=Number.isFinite(j)?j:Number.isFinite(l)&&Number.isFinite($)&&$>0?l/$:null,F=J===null?null:Math.round(Math.max(0,Math.min(100,J<=1?J*100:J))),A=String(y.text||(Number.isFinite(l)&&Number.isFinite($)?`${l}/${$}`:""));return{scorer:_,scorers:u,score:y,passed:Number.isFinite(l)?l:null,total:Number.isFinite($)?$:null,percent:F,text:A}}function nF(f){let u=s5(f);return u.text||(u.scorers.length>0?String(u.scorer?.status||"pending"):"--")}function yQ(f){let u=s5(f);if(u.total>0&&u.passed===u.total)return"succeeded";if(u.total>0&&u.passed>0)return"running";if(u.scorers.length>0)return"failed";return"pending"}function Jr(f){return Array.isArray(f?.items)?f.items.filter(Xf):[]}function Fr({run:f}){let u=nF(f);return X("span",{className:`pipeline-score-badge ${yQ(f)}`},`score ${u}`)}function Qr({run:f,onRaw:u}){let y=s5(f).scorers;if(!f)return X(pu,{title:"暂无评分",text:"选择一个 epoch 后会显示 scorer 结果。"});if(y.length===0)return X("div",{className:"pipeline-score-empty"},X("strong",null,"评分器等待中"),X("span",null,"DAG 完成后,Pipeline control backend 会把 scorer summary 追加到 run artifact,并通过 UniDesk 显示。"));return X("div",{className:"pipeline-score-board","data-testid":"pipeline-score-board"},y.map((l,$)=>{let j=s5({scorers:[l]}),J=Jr(l),F=j.percent??0;return X("article",{key:`${l.scorerId||l.component||$}`,className:`pipeline-score-card ${yQ({scorers:[l]})}`},X("div",{className:"pipeline-score-head"},X("div",null,X("span",null,l.scorerId||l.component||"scorer"),X("strong",null,j.text||l.status||"--")),X(uy,{status:l.status||"unknown"},l.status||"unknown")),X("div",{className:"pipeline-score-meter","aria-label":`score ${F}%`},X("span",{style:{width:`${F}%`}})),X("div",{className:"pipeline-score-facts"},X("span",null,`${F}%`),X("span",null,l.component||"--"),X("span",null,l.applicationCheckoutRef||"--")),J.length>0?X("div",{className:"pipeline-score-items"},J.map((A)=>X("span",{key:`${A.id||A.filter}`,className:`pipeline-score-item ${String(A.status||"").toLowerCase()}`,title:`${A.filter||"--"} / ran=${A.ran??"?"}`},X("b",null,A.id||"--"),X("small",null,A.status||"--")))):X("p",{className:"muted paragraph"},"当前 scorer 尚未返回 item 级结果。"),l.error?X("p",{className:"pipeline-score-error"},vq(l.error,360)):null,X("div",{className:"panel-actions inline-actions"},X(O1,{title:`Scorer ${l.scorerId||$}`,data:l,onOpen:u,testId:"raw-pipeline-score"})))}))}function Ar(f){let u=f.reduce((_,y)=>{let l=String(y?.componentClass||"unknown");return _[l]=(_[l]||0)+1,_},{});return Object.entries(u).map(([_,y])=>({name:_,count:Number(y)})).sort((_,y)=>y.count-_.count||_.name.localeCompare(y.name))}function Y6(f){if(Array.isArray(f))return f.map((u)=>typeof u==="string"?u:String(u?.id||u?.nodeId||"")).filter(Boolean);if(Array.isArray(f?.nodes))return Y6(f.nodes);if(Array.isArray(f?.nodeIds))return Y6(f.nodeIds);return[]}function Ur(f){return Xf(f?.instanceInputs?.monitor)?f.instanceInputs.monitor:{}}function iq(f,u){if(String(f?.kind||"").toLowerCase()!=="procedure")return!1;let _=Ur(f);if(f?.instanceInputs?.monitorMode===!0||_.enabled===!0)return!0;let y=pq(f?.componentRef);return String(u?.id||u?.config?.id||y||"").toLowerCase().includes("monitor")}function Wr(f){return f.filter((u)=>iq(u)).map((u)=>String(u?.id||"")).filter(Boolean)}function Gr(f,u){if(u.length===0)return f;let _=new Set(u),y=u.filter((l)=>f.includes(l));if(y.length===0)return f;return[...y,...f.filter((l)=>!_.has(l))]}function zr(f,u){if(u.length===0)return f;let _=new Set(u),y=u.filter(($)=>f.some((j)=>j.includes($)));if(y.length===0)return f;let l=f.map(($)=>$.filter((j)=>!_.has(j))).filter(($)=>$.length>0);return[y,...l]}function Kr(f,u,_){let l=_Q(f).map(Y6).filter((W)=>W.length>0);if(l.length>0)return l;let $=u.map((W)=>String(W?.id||"")).filter(Boolean),j=new Set($),J=new Map($.map((W)=>[W,0])),F=new Map($.map((W)=>[W,[]]));for(let W of _){let K=String(W?.from||W?.source||""),E=String(W?.to||W?.target||"");if(!j.has(K)||!j.has(E))continue;F.get(K)?.push(E),J.set(E,(J.get(E)||0)+1)}let A=new Map,U=$.filter((W)=>(J.get(W)||0)===0);for(let W of U)A.set(W,0);while(U.length>0){let W=U.shift(),K=(A.get(W)||0)+1;for(let E of F.get(W)||[])if(J.set(E,Math.max(0,(J.get(E)||0)-1)),A.set(E,Math.max(A.get(E)||0,K)),(J.get(E)||0)===0)U.push(E)}$.forEach((W)=>{if(!A.has(W))A.set(W,0)});let G=Math.max(0,...Array.from(A.values()));return Array.from({length:G+1},(W,K)=>$.filter((E)=>A.get(E)===K)).filter((W)=>W.length>0)}function Zr(f,u,_){let l=_Q(f).map(Y6).filter((J)=>J.length>0),$=l.length>0?l.flatMap((J)=>J):(()=>{let J=u.map((H)=>String(H?.id||"")).filter(Boolean),F=new Set(J),A=_.filter((H)=>String(H?.edgeType||"").toLowerCase()!=="rework"),U=new Map(J.map((H)=>[H,0])),G=new Map(J.map((H)=>[H,[]]));for(let H of A){let O=String(H?.from||H?.source||""),z=String(H?.to||H?.target||"");if(!F.has(O)||!F.has(z))continue;G.get(O)?.push(z),U.set(z,(U.get(z)||0)+1)}let W=new Map,K=J.filter((H)=>(U.get(H)||0)===0);for(let H of K)W.set(H,0);while(K.length>0){let H=K.shift(),O=(W.get(H)||0)+1;for(let z of G.get(H)||[])if(U.set(z,Math.max(0,(U.get(z)||0)-1)),W.set(z,Math.max(W.get(z)||0,O)),(U.get(z)||0)===0)K.push(z)}J.forEach((H)=>{if(!W.has(H))W.set(H,0)});let E=Math.max(0,...Array.from(W.values()));return Array.from({length:E+1},(H,O)=>J.filter((z)=>W.get(z)===O)).flatMap((H)=>H)})(),j=new Set($);for(let J of u){let F=String(J?.id||"");if(!F||j.has(F))continue;$.push(F),j.add(F)}return Gr($,Wr(u))}function q6(f){return`${f.source}->${f.target}-${f.index}`}function Nq(f,u,_){let y=kq(f),l=uQ(f),$=_r(_),j=new Map(y.map((S)=>[String(S?.id||""),S])),J=y.filter((S)=>iq(S,Oq(S,$))).map((S)=>String(S?.id||"")).filter(Boolean),F=zr(Kr(f,y,l),J),A=[],U=new Map,G=330,W=122;F.forEach((S,B)=>{let P=S.length*122;S.forEach((M,w)=>{let Y=j.get(M)||{id:M},R=Oq(Y,$),k=Xq(u,M).toLowerCase(),p=String(Y.kind||R?.componentClass||"node").toLowerCase(),n=pq(Y.componentRef||R),_f=String(R?.config?.version||R?.version||""),s=String(R?.config?.description||R?.description||""),ff=w*122-Math.floor(P/2);U.set(M,{column:B,row:w,y:ff}),A.push({id:M,type:"pipelineNode",position:{x:B*330,y:ff},data:{exportLabel:{id:M,kind:p,componentRef:n,componentVersion:_f,componentDescription:s,status:k},label:X("div",{className:"flow-node-label"},X("strong",null,M),X("span",null,p),X("code",{title:s||n},_f?`${n}@${_f}`:n),X(uy,{status:k},k))},className:`pipeline-flow-node ${p} ${k}`})})});let K=l.flatMap((S,B)=>{let P=String(S?.from||S?.source||""),M=String(S?.to||S?.target||"");if(!j.has(P)||!j.has(M))return[];return[{source:P,target:M,index:B,condition:S?.condition,edgeType:S?.edgeType}]}),E=K.reduce((S,B)=>S.set(B.source,(S.get(B.source)||0)+1),new Map),H=K.reduce((S,B)=>S.set(B.target,(S.get(B.target)||0)+1),new Map),O=K.reduce((S,B)=>{let P=`${B.source}->${B.target}`;return S.set(P,(S.get(P)||0)+1)},new Map),z=new Map,q=new Map,Z=new Map,V=new Map,L=new Map,r=new Map,N=K.reduce((S,B)=>{let P=U.get(B.source),M=U.get(B.target),w=(M?.column||0)-(P?.column||0);if(w<=0||String(B.edgeType||"").toLowerCase()==="rework"||w!==1)return S;let R=`${B.source}->column:${M?.column??""}`,k=S.get(R)||[];return k.push(B),S.set(R,k),S},new Map);for(let S of N.values()){if(S.length<2)continue;S.slice().sort((B,P)=>{let M=U.get(B.target),w=U.get(P.target);return(M?.y||0)-(w?.y||0)||B.index-P.index}).forEach((B,P,M)=>{r.set(q6(B),{slot:P-(M.length-1)/2,count:M.length})})}[...K].sort((S,B)=>{let P=U.get(S.source),M=U.get(S.target),w=U.get(B.source),Y=U.get(B.target),R=Math.abs((M?.column||0)-(P?.column||0))*330+Math.abs((M?.y||0)-(P?.y||0)),k=Math.abs((Y?.column||0)-(w?.column||0))*330+Math.abs((Y?.y||0)-(w?.y||0));return R-k||S.index-B.index}).forEach((S)=>{let B=U.get(S.source)||{column:0,row:0,y:0},P=U.get(S.target)||{column:0,row:0,y:0},M=P.column-B.column,w=Math.max(0,M),Y=M<=0||String(S.edgeType||"").toLowerCase()==="rework",R=B.y-P.y,k=H.get(S.target)||1,p=r.has(q6(S)),n=!Y&&w<=1&&(p||k===1),_f=L.get(S.target)||new Map;L.set(S.target,_f);let s=N6.slice().sort((ff,Kf)=>{let Gf=(Zf)=>{let h=String(Zf.side),i=0;if(Y){if(h==="left")i+=86;if(h==="top")i+=P.y<=0?-22:12;if(h==="bottom")i+=P.y>=0?-22:12;if(Math.abs(P.y)<12&&h!=="left")i+=S.index%2===0?h==="top"?-6:6:h==="bottom"?-6:6;return i}if(n){if(h==="left")i-=p?72:44;if(h!=="left")i+=p?72:44;return i+Math.abs(R)*0.02}if(h==="left")i+=w<=1?0:24;if(h==="top")i+=R<-36?-18:42;if(h==="bottom")i+=R>36?-18:42;if(w<=1&&Math.abs(R)<=82&&h!=="left")i+=38;if(w>1&&h!=="left")i-=10;return i},jf=B.y-P.y,Wf=jf!==0?jf:S.index%2===0?-1:1,Of=(Zf)=>{let h=_f.get(Zf.id)||0;return Gf(Zf)+h*64+CT(Zf,_f,Wf)};return Of(ff)-Of(Kf)||String(ff.id).localeCompare(String(Kf.id))})[0];_f.set(s.id,(_f.get(s.id)||0)+1),V.set(q6(S),s)});let x=K.map((S)=>{let B=Xq(u,S.target).toLowerCase(),P=`${S.source}->${S.target}`,M=z.get(S.source)||0,w=q.get(S.target)||0,Y=Z.get(P)||0;z.set(S.source,M+1),q.set(S.target,w+1),Z.set(P,Y+1);let R=M-((E.get(S.source)||1)-1)/2,k=w-((H.get(S.target)||1)-1)/2,p=Y-((O.get(P)||1)-1)/2,n=U.get(S.source),_f=U.get(S.target),s=(_f?.column||0)-(n?.column||0),ff=Math.max(1,Math.abs(s)),Kf=s<=0||String(S.edgeType||"").toLowerCase()==="rework",Gf=Math.abs((_f?.y||0)-(n?.y||0)),jf=r.get(q6(S)),Wf=!Kf&&s===1&&(H.get(S.target)||0)>1,Of=jf?jf.slot:p*2+R+k*0.45,Zf=Of===0?S.index%2===0?-1:1:Math.sign(Of),h=V.get(q6(S))||N6[1],i=h.side==="top"?-1:h.side==="bottom"?1:Zf,I=Kf||ff>1||Gf>96||Math.abs(Of)>0.2||h.side!=="left",lf=Kf?118+ff*18:22+ff*16,$f=h.side==="left"?0:28,Af=I?Math.max(-280,Math.min(280,i*Math.min(180,lf+$f+Gf*0.22)+Of*28)):0,Yf=Math.max(0,Math.min(H6.length-1,Math.round(R+(H6.length-1)/2))),xf=H6[Yf]||H6[1],of=B==="succeeded"?"var(--accent-2)":B==="running"?"var(--accent)":B==="failed"?"var(--danger)":"rgba(129, 147, 159, 0.78)",F0=n?.column||0,y0=_f?.column||0,T0=Af===0?0:Math.sign(Af),Qu=Kf?`feedback:${F0}->${y0}:${T0}`:jf?`fanout:${F0}->${y0}:${S.source}`:Wf?`fanin:${F0}->${y0}:${S.target}`:h.side!=="left"||ff>1?`corridor:${F0}->${y0}:${h.side}:${T0}:${Math.round(Math.abs(Af)/56)}`:"";return{id:`${S.source}->${S.target}-${S.index}`,source:S.source,target:S.target,sourceHandle:xf.id,targetHandle:h.id,type:"pipelineCurve",zIndex:12,animated:B==="running",data:{baseEdgeColor:of,laneOffset:Af,routeMode:jf&&h.side==="left"?"direct-forward-left":"",targetSide:h.side,isFeedback:Kf,overlapGroup:Qu},targetStatus:B}}),c=x.reduce((S,B)=>{let P=String(B.data?.overlapGroup||"");return P?S.set(P,(S.get(P)||0)+1):S},new Map),v=new Map,C=x.map((S)=>{let B=String(S.targetStatus||"pending"),P={...S};delete P.targetStatus;let M=String(S.data?.overlapGroup||""),w=M?c.get(M)||0:0,Y=w>1?v.get(M)||0:-1;if(w>1)v.set(M,Y+1);let R=Y>=0?Aq[Y%Aq.length]:String(S.data.baseEdgeColor),k={stroke:R};if(S.data.isFeedback)k.strokeDasharray="9 7";return{...P,data:{...S.data,edgeColor:R,overlapSlot:Y,overlapCount:w},style:k,markerEnd:{type:n_.ArrowClosed,color:R},className:`pipeline-flow-edge ${B} ${S.data.isFeedback?"feedback":""} ${Y>=0?"overlap-colored":""}`}});return{nodes:A,edges:C}}function Tu(f){return String(f??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function Lq(f){let u=String(f||"");if(u.includes("--accent-2"))return"#4eb7a8";if(u.includes("--accent"))return"#d7a13a";if(u.includes("--danger"))return"#cf6a54";return u.startsWith("#")?u:"#81939f"}function o5(f){return`arrow-${f.replace(/[^a-zA-Z0-9_-]+/g,"")}`}function gq(f,u="pipeline"){return String(f||u).replace(/[^a-zA-Z0-9_-]+/g,"-").replace(/^-|-$/g,"")||u}function Yq(f,u){let _=f.position.x,y=f.position.y,l=N6.find(($)=>$.id===u);if(l?.side==="top")return{x:_+U3*Gq(l.style?.left,0.5),y,position:Uf.Top};if(l?.side==="bottom")return{x:_+U3*Gq(l.style?.left,0.5),y:y+W3,position:Uf.Bottom};return{x:_,y:y+W3/2,position:Uf.Left}}function qr(f){return{x:f.position.x+U3,y:f.position.y+W3/2}}function Er(f,u){let _=Math.min(...f.nodes.map((H)=>H.position.x),0)-220,y=Math.min(...f.nodes.map((H)=>H.position.y),0)-220,l=Math.max(...f.nodes.map((H)=>H.position.x+U3),1)+220,$=Math.max(...f.nodes.map((H)=>H.position.y+W3),1)+220,j=Math.ceil(l-_),J=Math.ceil($-y),F=new Map(f.nodes.map((H)=>[H.id,H])),A=f.edges.map((H)=>Lq(H.data?.edgeColor||H.style?.stroke)),G=Array.from(new Set(["#4eb7a8","#d7a13a","#cf6a54","#81939f",...A])).map((H)=>``).join(""),W=f.edges.flatMap((H)=>{let O=F.get(H.source),z=F.get(H.target);if(!O||!z)return[];let q=qr(O),Z=Yq(z,String(H.targetHandle||"in-left")),V=Cq(q.x,q.y,Z.x,Z.y,Z.position,Number(H.data?.laneOffset||0),String(H.data?.routeMode||"")),L=Lq(H.data?.edgeColor||H.style?.stroke),r=H.data?.isFeedback?' stroke-dasharray="9 7"':"";return``}).join(` +`),K=f.nodes.map((H)=>{let O=H.data?.exportLabel||{},z=String(O.status||"pending").toLowerCase(),q=z==="succeeded"?"#4eb7a8":z==="running"?"#d7a13a":z==="failed"?"#cf6a54":"#81939f",Z=H.position.x,V=H.position.y,L=N6.map((r)=>{let N=Yq(H,r.id);if(r.side==="top"||r.side==="bottom")return``;return``}).join(` `);return` - + ${L} - - ${wu(O.id||E.id)} - ${wu(O.kind||"node")} - ${wu(O.componentRef||"--")} - ${wu(G)} + + ${Tu(O.id||H.id)} + ${Tu(O.kind||"node")} + ${Tu(O.componentRef||"--")} + ${Tu(z)} `}).join(` `);return{svg:` - ${z} + ${G} - ${wu(u)} + ${Tu(u)} ${K}${W} - `,width:j,height:J}}function qM(f){let u=String(f||"").toLowerCase();if(u==="succeeded"||u==="completed")return"#4eb7a8";if(u==="failed")return"#cf6a54";if(rq(u))return"#69aee8";return"#d7a13a"}function HM(f){let u=String(f?.kind||""),_=String(f?.tone||f?.status||"").toLowerCase();if(u==="prompt"&&_==="initial")return"#d7a13a";if(u==="prompt"&&_==="monitor")return"#69aee8";if(u==="prompt")return"#4eb7a8";if(_==="modify")return"#e0b95a";if(_==="approve"||_==="guide"||_==="monitor")return"#4eb7a8";if(_==="restart"||_==="redo")return"#d7a13a";if(_==="ignored")return"#81939f";if(_==="webui")return"#69aee8";if(_==="cli")return"#d7a13a";return"#a7bac5"}function Nq(f){let u=String(f?.sourceKind||"").toLowerCase(),_=String(f?.action||"").toLowerCase(),y=String(f?.status||"").toLowerCase();if(_==="observe"||y==="observation"||u==="monitor")return"#4eb7a8";if(u==="webui")return"#69aee8";if(u==="cli")return"#d7a13a";if(y.includes("ignored"))return"#81939f";return"#8aa0ad"}function EM(f,u,_){let y=HM(f),$=String(f?.kind||"");if($==="control-source")return``;if($==="control-target"){let j=String(f?.tone||"").toLowerCase()==="approve"?"rgba(78,183,168,0.22)":"#081118";return``}return``}function VM(f){let u=Ef(f.visibleNodeIds).map((Y)=>String(Y||"")).filter(Boolean),_=Ef(f.intervals).filter(Nf),y=Ef(f.markers).filter(Nf),$=Ef(f.arrows).filter(Nf),l=Ef(f.ticks).filter(Nf),j=Nf(f.bounds)?f.bounds:{},J=Nf(f.backendLayout)?f.backendLayout:null,F=Math.max(240,Math.round(Number(f.chartHeight||360))),A=Math.max(h1,108),U=128,z=24,W=58,K=56,q=128+Math.max(1,u.length)*A,E=Math.max(760,q+48),O=114+F+24,G=24,H=58,Z=114,V=(Y)=>152+Y*A,L=(Y)=>V(Y)+A/2,M=Ef(f.meta).map((Y)=>String(Y||"")).filter(Boolean).slice(0,4).join(" · "),N=new Map(y.map((Y)=>[String(Y.id||""),Y])),x=Array.from(new Set(["#4eb7a8","#69aee8","#d7a13a","#cf6a54","#8aa0ad",...$.map(Nq)])).map((Y)=>``).join(""),c=l.map((Y)=>{let R=114+aq(Y,j,F,J);return` - - ${wu(z0(Y.ms))} - +${wu($1(Number(Y.offsetMs??Number(Y.ms)-Number(j.startMs))))} + `,width:j,height:J}}function Hr(f){let u=String(f||"").toLowerCase();if(u==="succeeded"||u==="completed")return"#4eb7a8";if(u==="failed")return"#cf6a54";if(Rq(u))return"#69aee8";return"#d7a13a"}function Vr(f){let u=String(f?.kind||""),_=String(f?.tone||f?.status||"").toLowerCase();if(u==="prompt"&&_==="initial")return"#d7a13a";if(u==="prompt"&&_==="monitor")return"#69aee8";if(u==="prompt")return"#4eb7a8";if(_==="modify")return"#e0b95a";if(_==="approve"||_==="guide"||_==="monitor")return"#4eb7a8";if(_==="restart"||_==="redo")return"#d7a13a";if(_==="ignored")return"#81939f";if(_==="webui")return"#69aee8";if(_==="cli")return"#d7a13a";return"#a7bac5"}function Bq(f){let u=String(f?.sourceKind||"").toLowerCase(),_=String(f?.action||"").toLowerCase(),y=String(f?.status||"").toLowerCase();if(_==="observe"||y==="observation"||u==="monitor")return"#4eb7a8";if(u==="webui")return"#69aee8";if(u==="cli")return"#d7a13a";if(y.includes("ignored"))return"#81939f";return"#8aa0ad"}function Or(f,u,_){let y=Vr(f),l=String(f?.kind||"");if(l==="control-source")return``;if(l==="control-target"){let j=String(f?.tone||"").toLowerCase()==="approve"?"rgba(78,183,168,0.22)":"#081118";return``}return``}function Xr(f){let u=Vf(f.visibleNodeIds).map((Y)=>String(Y||"")).filter(Boolean),_=Vf(f.intervals).filter(Xf),y=Vf(f.markers).filter(Xf),l=Vf(f.arrows).filter(Xf),$=Vf(f.ticks).filter(Xf),j=Xf(f.bounds)?f.bounds:{},J=Xf(f.backendLayout)?f.backendLayout:null,F=Math.max(240,Math.round(Number(f.chartHeight||360))),A=Math.max(x1,108),U=128,G=24,W=58,K=56,E=128+Math.max(1,u.length)*A,H=Math.max(760,E+48),O=114+F+24,z=24,q=58,Z=114,V=(Y)=>152+Y*A,L=(Y)=>V(Y)+A/2,r=Vf(f.meta).map((Y)=>String(Y||"")).filter(Boolean).slice(0,4).join(" · "),N=new Map(y.map((Y)=>[String(Y.id||""),Y])),x=Array.from(new Set(["#4eb7a8","#69aee8","#d7a13a","#cf6a54","#8aa0ad",...l.map(Bq)])).map((Y)=>``).join(""),c=$.map((Y)=>{let R=114+fE(Y,j,F,J);return` + + ${Tu(zf(Y.ms))} + +${Tu(l1(Number(Y.offsetMs??Number(Y.ms)-Number(j.startMs))))} `}).join(` -`),v=['','TIME',...u.map((Y,R)=>{let m=V(R),p=Y.length>18?`${Y.slice(0,16)}…`:Y;return` - - ${wu(p)} - node ${R+1} +`),v=['','TIME',...u.map((Y,R)=>{let k=V(R),p=Y.length>18?`${Y.slice(0,16)}…`:Y;return` + + ${Tu(p)} + node ${R+1} `})].join(` `),C=u.map((Y,R)=>{return``}).join(` -`),P=_.map((Y)=>{let R=u.indexOf(String(Y.nodeId||""));if(R<0)return"";let m=114+f2(Y,j,F,J),p=Math.max(2,oq(Y,j,F,J)),n=qM(Y.status),_f=L(R)-3.5,t=Y.live?``:"",ff=p>=28?`${wu(String(Y.status||"working"))} - ${wu($1(Y.durationMs))}`:"";return` - - ${t} +`),S=_.map((Y)=>{let R=u.indexOf(String(Y.nodeId||""));if(R<0)return"";let k=114+d5(Y,j,F,J),p=Math.max(2,eq(Y,j,F,J)),n=Hr(Y.status),_f=L(R)-3.5,s=Y.live?``:"",ff=p>=28?`${Tu(String(Y.status||"working"))} + ${Tu(l1(Y.durationMs))}`:"";return` + + ${s} ${ff} `}).join(` -`),w=y.map((Y)=>{let R=u.indexOf(String(Y.nodeId||""));if(R<0)return"";let m=114+Iu(Y,j,F,J);return EM(Y,L(R),m)}).join(` -`),r=$.map((Y)=>{let R=N.get(String(Y.targetMarkerId||""));if(!R)return"";let m=N.get(String(Y.sourceMarkerId||"")),p=String(m?.nodeId||Y.sourceNodeId||""),n=String(R.nodeId||Y.targetNodeId||""),_f=u.indexOf(p),t=u.indexOf(n);if(_f<0||t<0)return"";let ff=L(_f)-24-128,Gf=L(t)-24-128,zf=z$(J)?E0(Y.sourceY??Y.y1)??(m?Iu(m,j,F,J):Iu(R,j,F,J)):m?Iu(m,j,F,J):Iu(R,j,F,J),jf=z$(J)?E0(Y.targetY??Y.y2)??Iu(R,j,F,J):Iu(R,j,F,J),Wf=Nq(Y),Vf=String(Y.action||"").toLowerCase()==="observe"?"3 4":"6 5",Zf=wu(dq(ff,zf,Gf,jf));return` - `}).join(` -`),S=u.length===0?'No visible Gantt nodes':"";return{svg:` +`),B=y.map((Y)=>{let R=u.indexOf(String(Y.nodeId||""));if(R<0)return"";let k=114+cu(Y,j,F,J);return Or(Y,L(R),k)}).join(` +`),P=l.map((Y)=>{let R=N.get(String(Y.targetMarkerId||""));if(!R)return"";let k=N.get(String(Y.sourceMarkerId||"")),p=String(k?.nodeId||Y.sourceNodeId||""),n=String(R.nodeId||Y.targetNodeId||""),_f=u.indexOf(p),s=u.indexOf(n);if(_f<0||s<0)return"";let ff=L(_f)-24-128,Kf=L(s)-24-128,Gf=G3(J)?V0(Y.sourceY??Y.y1)??(k?cu(k,j,F,J):cu(R,j,F,J)):k?cu(k,j,F,J):cu(R,j,F,J),jf=G3(J)?V0(Y.targetY??Y.y2)??cu(R,j,F,J):cu(R,j,F,J),Wf=Bq(Y),Of=String(Y.action||"").toLowerCase()==="observe"?"3 4":"6 5",Zf=Tu(uE(ff,Gf,Kf,jf));return` + `}).join(` +`),M=u.length===0?'No visible Gantt nodes':"";return{svg:` ${x} - - ${wu(f.title||"Pipeline Epoch Gantt")} - ${wu(M)} + + ${Tu(f.title||"Pipeline Epoch Gantt")} + ${Tu(r)} ${v} ${C} ${c} - ${P} - ${r} - ${w} ${S} - `,width:E,height:O}}function e5(f,u){let _=URL.createObjectURL(f),y=document.createElement("a");y.href=_,y.download=u,y.click(),setTimeout(()=>URL.revokeObjectURL(_),1000)}async function kq(f,u){let _=mq(u,"pipeline"),{svg:y,width:$,height:l}=ZM(f,u),j=new Blob([y],{type:"image/svg+xml;charset=utf-8"}),J=URL.createObjectURL(j);try{let F=new Image;await new Promise((W,K)=>{F.onload=()=>W(),F.onerror=()=>K(Error("svg image load failed")),F.src=J});let A=document.createElement("canvas");A.width=$,A.height=l;let U=A.getContext("2d");if(!U)throw Error("canvas unavailable");U.drawImage(F,0,0);let z=await new Promise((W)=>A.toBlob(W,"image/png"));if(!z)throw Error("png export failed");e5(z,`${_}.png`)}catch{e5(j,`${_}.svg`)}finally{URL.revokeObjectURL(J)}}async function OM(f){let u=mq(String(f?.title||"pipeline-gantt"),"pipeline-gantt"),{svg:_,width:y,height:$}=VM(f),l=new Blob([_],{type:"image/svg+xml;charset=utf-8"}),j=URL.createObjectURL(l);try{let J=new Image;await new Promise((z,W)=>{J.onload=()=>z(),J.onerror=()=>W(Error("gantt svg image load failed")),J.src=j});let F=document.createElement("canvas");F.width=y,F.height=$;let A=F.getContext("2d");if(!A)throw Error("canvas unavailable");A.drawImage(J,0,0);let U=await new Promise((z)=>F.toBlob(z,"image/png"));if(!U)throw Error("gantt png export failed");e5(U,`${u}.png`)}catch{e5(l,`${u}.svg`)}finally{URL.revokeObjectURL(j)}}async function XM(f){for(let u of f){if(u.flow.nodes.length===0)continue;await kq(u.flow,u.title),await new Promise((_)=>setTimeout(_,750))}}function Lq(f,u){return f.find((_)=>String(_?.pipelineId||"")===u)||null}function Yq(f){return Pf(f?.startedAt)??Pf(f?.artifact?.startedAt)??Pf(f?.request?.createdAt)??Pf(f?.updatedAt)??0}function NM(f,u){return f.filter((_)=>String(_?.pipelineId||"")===u).slice().sort((_,y)=>Yq(_)-Yq(y)||String(_?.runId||"").localeCompare(String(y?.runId||"")))}function gF(f,u){let _=String(u?.runId||""),y=f.findIndex((j)=>String(j?.runId||"")===_),$=y>=0?y+1:f.length,l=String(u?.status||"--");return`Epoch ${$} / ${_||"--"} / ${l}`}function l1(f){return String(f?.procedureRunId||f?.runId||"")}function $2(f,u){let _=String(f?.nodeId||f?.request?.nodeId||"");if(_)return _;let y=l1(f),$=`${u}__`;if(y.startsWith($))return y.slice($.length).replace(/__\d+$/u,"");return""}function k5(f,u){let _=Nf(f?.artifact)?f.artifact:{},y=Nf(f?.request)?f.request:{};return Ml(f?.startedAt,_.startedAt,y.createdAt,y.startedAt,f?.createdAt,f?.updatedAt,u?.startedAt,u?.request?.createdAt)}function i5(f,u){let _=String(f?.status?.status||f?.artifact?.status||f?.status||"").toLowerCase(),y=Nf(f?.artifact)?f.artifact:{},$=oF(_);return Ml(f?.finishedAt,y.finishedAt,f?.completedAt,$?f?.updatedAt:void 0,$?y.updatedAt:void 0,$?u?.updatedAt:void 0)}function iq(f,u,_=Date.now()){let y=String(f?.runId||""),$=new Set(u.map((l)=>String(l?.id||"")).filter(Boolean));return Ef(f?.procedureRuns).flatMap((l)=>{let j=$2(l,y);if(!j)return[];let J=String(l?.status?.status||l?.artifact?.status||l?.status||"unknown").toLowerCase(),F=k5(l,f),A=Pf(F);if(A===null)return[];let U=i5(l,f),z=Pf(U)??(oF(J)?Pf(l?.updatedAt)??A+1000:_),W=Math.max(A+1000,z);return[{nodeId:j,knownNode:$.has(j),procedureRunId:l1(l),status:J,startMs:A,endMs:W,startedAt:wl(A),finishedAt:wl(W),durationMs:W-A,runId:y,raw:l}]}).sort((l,j)=>l.startMs-j.startMs||l.endMs-j.endMs||l.nodeId.localeCompare(j.nodeId))}function LM(f,u,_=[]){let y=u.map((U)=>Number(U.startMs)).filter(Number.isFinite),$=u.map((U)=>Number(U.endMs)).filter(Number.isFinite);for(let U of _){let z=E0(U?.eventMs??U?.ms);if(z!==null)y.push(z),$.push(z)}let l=Pf(f?.startedAt)??Pf(f?.artifact?.startedAt)??Pf(f?.request?.createdAt),j=Pf(f?.finishedAt)??Pf(f?.artifact?.finishedAt)??Pf(f?.updatedAt);if(l!==null)y.push(l);if(j!==null)$.push(j);let J=Date.now(),F=y.length>0?Math.min(...y):J-60000,A=Math.max(F+60000,$.length>0?Math.max(...$):J);return{startMs:F,endMs:A,durationMs:A-F}}var g5=12,gq=20,nF=100,YM=!1;function _y(f){let u=Number(f);if(!Number.isFinite(u))return 0;return Math.max(0,Math.min(100,Math.round(u*100)/100))}function BM(f){let u=Math.max(g5,Number(f||g5)),_=Math.log(u/g5)/Math.log(gq);return _y(_*100)}var Tl=BM(nF);function _Q(f){let u=_y(f)/100,_=g5*Math.pow(gq,u),y=u<0.24?"全局":u<0.64?"均衡":"细节";return{value:_y(u*100),pxPerMinute:_,label:y}}function IF(f){let u=Math.round(Number(f));return Math.abs(u-nF)<=1?nF:u}function wM(f,u=Tl){let _=Math.max(1,Number(f.durationMs||0)/60000),y=_Q(u);return Math.round(Math.max(360,Math.min(7200,_*Number(y.pxPerMinute||48))))}function DM(f,u=7){let _=Math.max(1,Number(f.endMs||0)-Number(f.startMs||0));return Array.from({length:u},(y,$)=>{let l=u===1?0:$/(u-1);return{ms:Number(f.startMs)+_*l,percent:l*100}})}function TM(f,u){let _=Math.max(1,Number(u.endMs)-Number(u.startMs));return Math.max(0,Math.min(100,(f-Number(u.startMs))/_*100))}function E0(f){let u=Number(f);return Number.isFinite(u)?u:null}function yQ(f){return rq(f?.status)&&!oF(f?.status)}function nq(f,u,_,y){let $=Math.max(1,_-u),l=Math.max(0,Math.min(1,(f-u)/$));return Number((l*y).toFixed(3))}function Bq(f,u){if(!u)return null;let _=E0(u?.startMs),y=E0(u?.endMs),$=E0(u?.chartHeight);if(_===null||y===null||$===null)return null;return nq(f,_,y,$)}function tq(f,u){let _=E0(f?.rawStartMs??f?.startMs)??E0(f?.startMs)??u,y=E0(f?.endMs)??_+1000;if(!yQ(f))return Math.max(_+1000,y);return Math.max(_+1000,y,u)}function MM(f,u,_,y){let $=E0(f?.startMs)??y-60000,l=E0(f?.endMs)??y,j=_.reduce((q,E)=>Math.max(q,tq(E,y)),l),J=Math.max($+60000,l,j),F=Math.max(1,J-$),A={startMs:$,endMs:J,durationMs:F},U=wM(A,u),z=_Q(u),W=Math.max(5,Math.min(18,Math.round(U/150))),K=DM(A,W).map((q)=>{let E=Number(q.ms),O=nq(E,$,J,U);return{...q,y:O,timestamp:wl(E),offsetMs:E-$}});return{source:"frontend-y",startMs:$,endMs:J,durationMs:F,chartHeight:U,scale:_y(u),normalizedScale:Number((_y(u)/100).toFixed(3)),pxPerMinute:Number(Number(z.pxPerMinute||0).toFixed(3)),ticks:K}}function SM(f,u,_){if(!yQ(f))return f;let y=E0(f?.rawStartMs??f?.startMs)??E0(f?.startMs)??_,$=tq(f,_),l=Bq(y,u),j=Bq($,u),J=E0(l??f?.y1??f?.startY)??0,F=E0(j??f?.y2??f?.endY)??J+10,A=Math.max(24,F-J);return{...f,live:!0,startMs:y,endMs:$,durationMs:Math.max(1000,$-y),finishedAt:wl($),y1:J,y2:F,startY:J,endY:F,height:A}}function $Q(f,u,_){return TM(f,u)/100*_}function z$(f){return Boolean(f&&String(f?.source||"")!=="frontend-y")}function sq(f,u,_,y,$){if(z$(y))for(let j of $){let J=E0(f?.[j]);if(J!==null)return J}let l=E0(f?.ms??f?.eventMs??f?.startMs);return $Q(l??Number(u.startMs),u,_)}function f2(f,u,_,y){return sq(f,u,_,y,["y1","startY"])}function tF(f,u,_,y){if(z$(y)){let l=E0(f?.y2??f?.endY);if(l!==null)return l}let $=E0(f?.endMs)??Number(u.endMs);return $Q($,u,_)}function oq(f,u,_,y){if(z$(y)){let l=E0(f?.height);if(l!==null)return Math.max(1,l)}let $=f?.live?24:10;return Math.max($,tF(f,u,_,y)-f2(f,u,_,y))}function Iu(f,u,_,y){return sq(f,u,_,y,["y","timeAxisY"])}function aq(f,u,_,y){if(z$(y)||String(y?.source||"")==="frontend-y"){let j=E0(f?.y);if(j!==null)return j}let $=E0(f?.percent);if($!==null)return $/100*_;let l=E0(f?.ms)??Number(u.startMs);return $Q(l,u,_)}function rM(f){let u=String(f?.promptEvent||f?.raw?.promptEvent||f?.event||"").toLowerCase();if(!["node-long-running-observation","node-finished"].includes(u))return"";let _=String(f?.sourceNodeId||f?.raw?.sourceNodeId||f?.raw?.detail?.nodeId||""),y=String(f?.nodeId||f?.targetNodeId||"");return _&&_!==y?_:""}function PM(f,u){let _=new Set(u.map(($)=>[String($.sourceNodeId||""),String($.targetNodeId||""),String($.targetMarkerId||""),String($.action||"")].join(":"))),y=[...u];for(let $ of f){let l=rM($),j=String($?.nodeId||""),J=String($?.id||"");if(!l||!j||!J)continue;let F=[l,j,J,"observe"].join(":");if(_.has(F))continue;_.add(F),y.push({id:`observation-arrow:${J}:${l}:${j}`,commandId:String($?.commandId||$?.eventId||J),sourceNodeId:l,targetNodeId:j,sourceMarkerId:"",targetMarkerId:J,sourceKind:"monitor",action:"observe",status:"observation"})}return{markers:f,arrows:y}}function wq(f,u=""){let _=O1(f)||u,y=String(f?.promptEvent||"");if(_==="initial-prompt-delivered")return"initial";if(y==="node-finished"||y==="node-long-running-observation"||y.startsWith("monitor-"))return"monitor";if(_==="monitor-prompt-delivered"||String(f?.sourceKind||"").toLowerCase()==="monitor"||u==="monitor-prompt-queued")return"monitor";return"append"}function CM(f){return Ef(f?.tags||f?.raw?.tags).map((u)=>String(u||"")).filter(Boolean)}function Dq(f,u=""){let _=O1(f)||u,y=String(f?.promptEvent||"");if(_==="initial-prompt-delivered")return"初始 prompt";if(y==="node-long-running-observation")return"长任务观察";if(y==="node-finished")return CM(f).includes("monitor.audit")?"节点完成 / OA 审核":"节点完成";if(y==="monitor-interval")return"旧版轮询";if(y==="monitor-start")return"Monitor start";if(y==="monitor-stop")return"Monitor stop";if(_==="monitor-prompt-delivered"||u==="monitor-prompt-queued")return"Monitor prompt";if(_==="append-prompt-queued")return"追加 prompt 已排队";return"追加 prompt"}function Tq(f){let u=O1(f);if(u==="control-command-applied")return 3;if(u==="control-command-ignored")return 2;if(u==="control-command-queued")return 1;return 0}function Mq(f,u){let _=String(f?.commandId||"");if(_)return`command:${_}`;return["fallback",oy(f)||Ml(f?.createdAt,f?.timestamp)||`index-${u}`,String(f?.sourceKind||""),String(f?.sourceNodeId||""),String(f?.targetNodeId||""),ay(f)].join(":")}function RM(f){return kF([f?.targetNodeId,...Ef(f?.resetNodeIds)])}function xM(f,u){let _=Yl(f),y=O1(f),$=String(f?.targetNodeId||""),l=Boolean($)&&u!==$;if(y==="control-command-applied")return l?`${_} 波及`:`${_} 生效`;if(y==="control-command-ignored")return`${_} 忽略`;if(y==="control-command-queued")return`${_} 已发起`;return l?`${_} 波及`:_}function vM(f){if(O1(f)==="control-command-ignored")return"ignored";let _=ay(f);if(_==="restart"||_==="redo")return"restart";if(_==="modify")return"modify";if(_==="approve")return"approve";if(_==="guide")return"guide";return"pending"}function bM(f){let u=String(f?.sourceKind||"").toLowerCase();if(u==="monitor")return"monitor";if(u==="webui")return"webui";if(u==="cli")return"cli";return"system"}function hM(f,u,_,y){let $=f.filter((A)=>String(A.nodeId||"")===u).sort((A,U)=>Number(A.startMs)-Number(U.startMs)),l=$.find((A)=>_>=Number(A.startMs)-1000&&_<=Number(A.endMs)+1000);if(l)return{ms:_,onInterval:!0,snapReason:"inside-interval",procedureRunId:String(l.procedureRunId||"")};let j=ay(y),J=$.slice().reverse().find((A)=>Number(A.endMs)<=_+1000);if(J&&j==="approve")return{ms:Number(J.endMs),onInterval:!0,snapReason:"previous-interval-end",procedureRunId:String(J.procedureRunId||"")};let F=$.find((A)=>Number(A.startMs)>=_-1000);if(F&&["guide","modify","restart","redo"].includes(j))return{ms:Number(F.startMs),onInterval:!0,snapReason:"next-interval-start",procedureRunId:String(F.procedureRunId||"")};return{ms:_,onInterval:!1,snapReason:"event-time",procedureRunId:String(y?.procedureRunId||"")}}function dq(f,u,_,y){let $=Math.hypot(_-f,y-u),l=$>Qq?Qq:0,j=l>0?_-(_-f)/$*l:_,J=l>0?y-(y-u)/$*l:y,F=j-f,A=Math.max(16,Math.min(42,Math.abs(F)*0.45+12)),U=F===0?1:Math.sign(F);return`M ${f},${u} C ${f+U*A},${u} ${j-U*A},${J} ${j},${J}`}function IM(f,u){let _=String(f?.runId||u?.runId||""),y=iq({...Nf(u)?u:{},...Nf(f)?f:{},runId:_,procedureRuns:Ef(f?.procedureRuns).length>0?f.procedureRuns:u?.procedureRuns},[]),$=[],l=[],j=[],J=new Set,F=new Map,A=(W,K)=>{if(!W.nodeId||!Number.isFinite(Number(W.ms)))return;if(J.has(W.id))return;J.add(W.id),K.push(W)};for(let W of Ef(f?.procedureRuns)){let K=$2(W,_),q=l1(W);if(!K)continue;for(let E of Ef(W?.attempts)){let O=y2(E),G=new Set,H=new Set;for(let V of Ll(E?.controlEventRecords)){let L=O1(V);if(!["initial-prompt-delivered","append-prompt-delivered","monitor-prompt-delivered"].includes(L))continue;let M=oy(V),N=Pf(M);if(N===null)continue;let D=String(V?.eventId||"");if(D)G.add(D);H.add(`${L}:${M}:${String(V?.sourceKind||"")}:${String(V?.promptPreview||"")}`),A({id:`prompt:${D||`${q}:${O}:${L}:${N}`}`,runId:_,nodeId:K,procedureRunId:q,attempt:O,kind:"prompt",tone:wq(V,L),status:"delivered",label:Dq(V,L),ms:N,timestampIso:M,sourceKind:String(V?.sourceKind||""),sourceNodeId:String(V?.sourceNodeId||""),targetNodeId:K,action:"",eventId:D,commandId:String(V?.commandId||""),raw:V},$)}let Z=[{records:Ll(E?.controlPromptRecords),fallbackKind:"append-prompt-queued"},{records:Ll(E?.monitorPromptRecords),fallbackKind:"monitor-prompt-queued"}];for(let V of Z)for(let L of V.records){let M=oy(L),N=Pf(M);if(N===null)continue;let D=String(L?.eventId||"");if(D&&G.has(D))continue;let c=`${V.fallbackKind==="monitor-prompt-queued"?"monitor-prompt-delivered":"append-prompt-delivered"}:${M}:${String(L?.sourceKind||"")}:${String(L?.promptPreview||"")}`;if(H.has(c))continue;A({id:`prompt-fallback:${D||`${q}:${O}:${V.fallbackKind}:${N}`}`,runId:_,nodeId:K,procedureRunId:q,attempt:O,kind:"prompt",tone:wq(L,V.fallbackKind),status:"queued",label:Dq(L,V.fallbackKind),ms:N,timestampIso:M,sourceKind:String(L?.sourceKind||""),sourceNodeId:String(L?.sourceNodeId||""),targetNodeId:K,action:"",eventId:D,commandId:String(L?.commandId||""),raw:L},$)}}}let U=new Map;Ll(f?.controlEvents).forEach((W,K)=>{let q=Mq(W,K),E=U.get(q)||{key:q,events:[],commands:[]};E.events.push(W),U.set(q,E)}),Ef(f?.controlCommands).filter(Nf).forEach((W,K)=>{let q=Mq(W,K),E=U.get(q)||{key:q,events:[],commands:[]};E.commands.push(W),U.set(q,E)});for(let W of U.values()){let K=Ef(W.events).slice().sort((C,P)=>Tq(P)-Tq(C)),q=Ef(W.commands),E=Ef(W.events).find((C)=>O1(C)==="control-command-queued")||q[0]||null,O=K[0]||q[0]||E;if(!E&&!O)continue;let G=String(E?.sourceNodeId||O?.sourceNodeId||""),H=String(E?.sourceKind||O?.sourceKind||""),Z=oy(E)||oy(O)||Ml(E?.createdAt,O?.createdAt),V=Pf(Z),L=String(O?.commandId||E?.commandId||W.key),M=(O1(O)||"control-command-queued").replace(/^control-command-/u,""),N="";if(G&&V!==null)N=`control-source:${L}:${G}`,F.set(L,N),A({id:N,runId:_,nodeId:G,procedureRunId:String(E?.procedureRunId||O?.procedureRunId||""),attempt:"",kind:"control-source",tone:bM(E||O),status:M,label:`${Yl(E||O)} 发起`,ms:V,timestampIso:Z,action:ay(E||O),sourceKind:H,sourceNodeId:G,targetNodeId:String(O?.targetNodeId||E?.targetNodeId||""),commandId:L,raw:E||O},l);let D=O||E,x=oy(D)||Z,c=Pf(x);if(c===null)continue;let v=RM(D);for(let C of v){let P=hM(y,C,c,D),w=`control-target:${L}:${C}`;if(A({id:w,runId:_,nodeId:C,procedureRunId:P.procedureRunId,attempt:"",kind:"control-target",tone:vM(D),status:M,label:xM(D,C),ms:P.ms,eventMs:c,onInterval:P.onInterval,snapReason:P.snapReason,snapped:Number(P.ms)!==c,timestampIso:x,renderedTimestampIso:wl(Number(P.ms)),action:ay(D),sourceKind:H,sourceNodeId:G,targetNodeId:C,commandId:L,raw:D},l),N&&G&&G!==C)j.push({id:`control-arrow:${L}:${G}:${C}`,commandId:L,sourceNodeId:G,targetNodeId:C,sourceMarkerId:N,targetMarkerId:w,sourceKind:H,action:ay(D),status:M})}}let z=[...$,...l].sort((W,K)=>Number(W.ms)-Number(K.ms)||String(W.nodeId).localeCompare(String(K.nodeId))||String(W.id).localeCompare(String(K.id)));return{...PM(z,j),sourceMarkerByCommand:F}}function cM({details:f,selectedNodeId:u,selectedNodeRuntime:_,control:y,onRaw:$}){if(!f)return X("span",{className:"muted"},"点击“抓取过程”读取 node 运行材料;主界面只显示结构化摘要,完整内容需点开原始 JSON。");let l=Ef(f.procedureRuns),j=l.at(-1)||{},J=Ef(j.attempts),F=J.at(-1)||{},A=Ef(j.workerLogTail),U=Ef(F.controlEventsTail),z=Ef(F.controlPromptsTail),W=Ef(F.monitorPromptsTail),K=xF(U),q=xF(z),E=xF(W),O=F.opencodeMessages||{};return X("div",{className:"pipeline-evidence-list compact"},X(y1,{title:"Node runtime",subtitle:u||"--",facts:[`status ${_?.status||"pending"}`,`attempts ${_?.attempts??J.length}`,`procedure ${_?.currentProcedureRunId||l1(j)||"--"}`,y.fetchedAt?`fetched ${u2(y.fetchedAt)}`:"not fetched"],data:f.node||f,onRaw:$,testId:"raw-pipeline-node-runtime"}),X(y1,{title:"Procedure runs",subtitle:`${l.length} groups`,facts:[`latest ${j.status?.status||j.status||"--"}`,`steps ${Ef(j.recentSteps).length}`,`duration ${$1(Pf(j.finishedAt)&&Pf(j.startedAt)?Number(Pf(j.finishedAt))-Number(Pf(j.startedAt)):j.durationMs)}`],data:l,onRaw:$,testId:"raw-pipeline-node-procedures"}),X(y1,{title:"OpenCode messages",subtitle:String(O.exists?"available":"not indexed"),facts:[`messages ${t5(O.messageCount)}`,`size ${t5(O.size)}`,`updated ${z0(O.updatedAt)}`],data:O,onRaw:$,testId:"raw-pipeline-node-messages"}),X(y1,{title:"Control prompts",subtitle:"manual / monitor append queues",facts:[`manual tail ${q.total}`,`monitor tail ${E.total}`,`last ${z0(sF(q.lastAt,E.lastAt))}`],data:{controlPromptsTail:z,monitorPromptsTail:W},onRaw:$,testId:"raw-pipeline-node-prompts"}),X(y1,{title:"Control events",subtitle:K.eventKinds.length>0?K.eventKinds.join(", "):"event tail",facts:[`tail ${K.total}`,`parsed ${K.parsed}`,`last ${z0(K.lastAt)}`],data:U,onRaw:$,testId:"raw-pipeline-node-events"}),X(y1,{title:"Worker log",subtitle:"tail is hidden on main canvas",facts:[`tail ${A.length} lines`,"raw only via button",`procedure ${l1(j)||"--"}`],data:A,onRaw:$,testId:"raw-pipeline-node-worker-log"}))}function pM({activeRun:f,onRaw:u}){if(!f)return X(cu,{title:"暂无运行材料",text:"没有 Pipeline epoch 时不会展示运行材料索引。"});let _=Ef(f.nodes),y=Ef(f.procedureRuns),$=Ef(f.submissions),l=Ef(f.workerLogTail),j=Wq(_),J=Wq(y),F=y.filter((U)=>String(U?.status||"").toLowerCase()==="failed"),A=sF(...y.flatMap((U)=>[U.updatedAt,U.finishedAt,U.startedAt]));return X("div",{className:"pipeline-evidence-list"},X(y1,{title:"Epoch overview",subtitle:f.runId||"--",facts:[`pipeline ${f.pipelineId||"--"}`,`status ${f.status||"--"}`,`started ${z0(f.startedAt)}`,`updated ${z0(f.updatedAt)}`],data:f,onRaw:u,testId:"raw-pipeline-run"}),X(y1,{title:"Node states",subtitle:`${_.length} nodes`,facts:[`running ${j.running||0}`,`succeeded ${j.succeeded||0}`,`failed ${j.failed||0}`,`pending ${j.pending||0}`],data:_,onRaw:u,testId:"raw-pipeline-run-nodes"}),X(y1,{title:"Procedure run index",subtitle:`${y.length} procedure records`,facts:[`succeeded ${J.succeeded||0}`,`failed ${J.failed||0}`,`latest ${z0(A)}`,`errors ${F.length}`],data:y,onRaw:u,testId:"raw-pipeline-run-procedures"}),X(y1,{title:"OA submissions",subtitle:`${$.length} submission files`,facts:[`records ${$.length}`,`task ${t5(f.task)}`,"raw grouped by run"],data:$,onRaw:u,testId:"raw-pipeline-run-submissions"}),X(y1,{title:"Worker log tail",subtitle:"hidden from main interface",facts:[`tail ${l.length} lines`,"display raw only after click",`updated ${z0(f.updatedAt)}`],data:l,onRaw:u,testId:"raw-pipeline-run-worker-log"}))}function mM({diagnostics:f,onRaw:u}){let _=Ef(f?.runs).filter(Nf),y=Ef(f?.forbiddenResiduals),$=Nf(f?.guarantees)?f.guarantees:{},l=f?.hasNeutralNodeFinishedEvidence===!0&&f?.hasNoAuditPolicyEvidence===!0&&f?.hasAuditPolicyEvidence===!0,j=f?.ok===!0&&l&&y.length===0,J=_[0]||null,F=[{label:"中性完成事实",ok:$.neutralNodeFinished===!0,hint:"node-finished 不携带流程策略"},{label:"Config 策略判定",ok:$.auditPolicyFromConfig===!0,hint:"OA backend 读取当前 epoch 配置"},{label:"控制命令来自 OA",ok:$.runnerConsumesControlCommandsFromOaEvents===!0,hint:"runner 只消费 OA control.command"},{label:"无独立审核事件",ok:$.noIndependentAuditRequestEvent===!0,hint:"审核由 node-finished + policy 派生"},{label:"无批次门禁",ok:$.noBatchFinishedControlGate===!0,hint:"下游启动由每个 node 完成驱动"}];return X("div",{className:"pipeline-oa-panel","data-testid":"pipeline-oa-event-flow-panel"},X("div",{className:"metric-grid compact"},X(Hu,{label:"OA Flow",value:j?"100%":"--",hint:String(f?.mode||"waiting diagnostics"),tone:j?"ok":"warn"}),X(Hu,{label:"禁止残留",value:y.length,hint:y.length===0?"source scan clean":"needs cleanup",tone:y.length===0?"ok":"warn"}),X(Hu,{label:"No-audit",value:f?.hasNoAuditPolicyEvidence?"OK":"--",hint:"OA 下游策略证据",tone:f?.hasNoAuditPolicyEvidence?"ok":"warn"}),X(Hu,{label:"Monitor 审核",value:f?.hasAuditPolicyEvidence?"OK":"--",hint:"OA 控制事件闭环",tone:f?.hasAuditPolicyEvidence?"ok":"warn"})),X("div",{className:"pipeline-oa-guarantees"},F.map((A)=>X("article",{key:A.label,className:`pipeline-oa-guarantee ${A.ok?"ok":"warn"}`},X(uy,{status:A.ok?"online":"warn"},A.ok?"OK":"MISS"),X("div",null,X("strong",null,A.label),X("span",null,A.hint))))),X("div",{className:"pipeline-evidence-list compact"},_.slice(0,6).map((A)=>X(y1,{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:u,testId:`raw-pipeline-oa-run-${String(A.runId||"run").replace(/[^a-zA-Z0-9_.-]+/g,"-")}`}))),J?X("p",{className:"muted paragraph"},`最新证据 ${J.runId}: ${J.nodeFinishedCount||0} 个 node-finished,${J.controlAppliedCount||0} 个控制结果。`):X(cu,{title:"暂无 OA 事件流证据",text:"等待 Pipeline backend 暴露 diagnostics。"}),f?X("div",{className:"panel-actions inline-actions"},X(X1,{title:"Pipeline OA Event Flow Diagnostics",data:f,onOpen:u,testId:"raw-pipeline-oa-event-flow"})):null)}function kM({quota:f,onRaw:u}){let _=Nf(f?.summary)?f.summary:{},y=Nf(f?.target)?f.target:{},$=Nf(f?.cache)?f.cache:{},l=f?.ok===!0,j=String(f?.modelId||_.modelName||y.modelName||"MiniMax-M2.7"),J=_.totalCount??y.currentIntervalTotalCount,F=_.usageCount??y.currentIntervalUsageCount,A=_.remainingCount??y.currentIntervalRemainingCount,U=_.remainingRatio??(Number.isFinite(Number(J))&&Number(J)>0&&Number.isFinite(Number(A))?Number(A)/Number(J):void 0),z=_.usageRatio??(Number.isFinite(Number(J))&&Number(J)>0&&Number.isFinite(Number(F))?Number(F)/Number(J):void 0),W=_.resetAt||y.endAt,K=_.remainsMs??y.remainsMs,q=Number(A),E=!l||Number.isFinite(q)&&q<=0?"warn":"ok",O=[l?`endpoint ${f?.endpoint||"--"}`:"quota unavailable",`fetched ${n5(f?.fetchedAt)}`,$.hit?`cache ${$1($.ageMs)}`:"live quota"];return X("div",{className:"pipeline-minimax-quota-panel","data-testid":"pipeline-minimax-quota-panel"},X("div",{className:"metric-grid compact"},X(Hu,{label:"MiniMax",value:l?j:"--",hint:f?.modelComponent||f?.error||"model/minimax-m27",tone:E}),X(Hu,{label:"当前窗口",value:`${RF(F)}/${RF(J)}`,hint:`已用 ${Uq(z)}`,tone:E}),X(Hu,{label:"剩余额度",value:RF(A),hint:`剩余 ${Uq(U)}`,tone:E}),X(Hu,{label:"重置时间",value:n5(W),hint:K!==void 0?`约 ${$1(K)}`:z0(W),tone:E})),X(aF,{items:O}),l?X("p",{className:"muted paragraph"},`MiniMax 限额来自 D601 Pipeline 后端实时查询;当前模型匹配 ${_.modelName||y.modelName||j}。`):X(H0,{error:f?.error||"MiniMax 限额查询失败"}),f?X("div",{className:"panel-actions inline-actions"},X(X1,{title:"Pipeline MiniMax Quota",data:f,onOpen:u,testId:"raw-pipeline-minimax-quota"})):null)}function iM({epochs:f,activeRun:u,activePipeline:_,pipelineNodes:y,pipelineEdges:$,runDetails:l,nodeDetails:j,nodeDetailsState:J,ganttScale:F=Tl,onGanttScaleChange:A,onRunChange:U,onIntervalSelect:z,onMarkerSelect:W,selection:K,detailOpen:q,onDetailOpenChange:E,onRaw:O}){let[G,H]=Bu(YM),[Z,V]=Bu({startY:0,endY:0,startMs:0,endMs:0}),[L,M]=Bu(Date.now()),N=e_(null),D=String(u?.runId||""),x=Boolean(q),c=(uf)=>{if(typeof E==="function")E(uf)},v=_y(F??Tl),C=String(l?.runId||"")===D?l?.details:null,P=C?{...Nf(u)?u:{},...Nf(C)?C:{},runId:D,procedureRuns:Ef(C?.procedureRuns).length>0?C.procedureRuns:u?.procedureRuns}:u,w=iq(P,y,L),r=C?IM(C,P):{markers:[],arrows:[]},S=Ef(r.markers),T=LM(P,w,S),Y=MM(T,v,w,L),R=String(Y.source||"frontend-y"),m=w.map((uf)=>SM(uf,Y,L)),p={startMs:Number(Y.startMs),endMs:Number(Y.endMs),durationMs:Math.max(1,Number(Y.durationMs??Number(Y.endMs)-Number(Y.startMs)))},n=_Q(v),_f={...n,pxPerMinute:Number(Y.pxPerMinute??n.pxPerMinute)},t=Math.round(Number(Y.chartHeight||360)),ff=w.some(yQ);c1(()=>{if(!D||!ff)return;let uf=window.setInterval(()=>M(Date.now()),1000);return()=>window.clearInterval(uf)},[D,ff]);let Gf=GM(_,y,Array.isArray($)?$:[]),zf=y.map((uf)=>String(uf?.id||"")).filter(Boolean),jf=m.map((uf)=>String(uf.nodeId||"")).filter(Boolean),Wf=S.map((uf)=>String(uf.nodeId||"")).filter(Boolean),Vf=Array.from(new Set([...Gf,...zf,...jf,...Wf])),Zf={startY:0,endY:t,startMs:Number(p.startMs),endMs:Number(p.endMs)},h=Number(Z?.endY||0)>0?Z:Zf,g=(uf)=>{return f2(uf,p,t,Y)<=Number(h.endY)&&tF(uf,p,t,Y)>=Number(h.startY)},I=(uf)=>{let vf=Iu(uf,p,t,Y);return vf>=Number(h.startY)&&vf<=Number(h.endY)},$f=new Set(Vf.filter((uf)=>m.some((vf)=>vf.nodeId===uf&&g(vf))||S.some((vf)=>vf.nodeId===uf&&I(vf)))),lf=G?Vf.filter((uf)=>$f.has(uf)):Vf,Af=`${PF}px ${lf.length>0?lf.map(()=>`${h1}px`).join(" "):"minmax(160px, 1fr)"}`,Yf=Ef(Y.ticks).filter(Nf),xf=String(K?.mode==="interval"?K?.interval?.procedureRunId||"":""),sf=String(K?.mode==="event"?K?.marker?.id||"":""),j0=()=>{let uf=N.current;if(!uf){V(Zf);return}let vf=Math.max(0,uf.scrollTop-CF),a0=Math.max(120,uf.clientHeight-CF),Bf=Math.min(t,vf+a0),v0={startY:vf,endY:Bf,startMs:Number(p.startMs),endMs:Number(p.endMs)},i0=Math.max(0,Math.min(1,vf/t)),d0=Math.max(i0,Math.min(1,Bf/t)),b0=Math.max(1,Number(p.endMs)-Number(p.startMs));v0.startMs=Number(p.startMs)+b0*i0,v0.endMs=Number(p.startMs)+b0*d0,V(v0)};c1(()=>{let uf=N.current,vf=window.setTimeout(j0,0);return uf?.addEventListener("scroll",j0),window.addEventListener("resize",j0),()=>{window.clearTimeout(vf),uf?.removeEventListener("scroll",j0),window.removeEventListener("resize",j0)}},[D,p.startMs,p.endMs,t]);let u0=Math.max(0,Vf.length-lf.length),D0=new Set(S.filter((uf)=>lf.includes(String(uf.nodeId||""))&&I(uf)).map((uf)=>String(uf.id))),Fu=new Map(S.map((uf)=>[String(uf.id),uf])),O0=Ef(r.arrows).filter((uf)=>{if(!D0.has(String(uf.targetMarkerId||"")))return!1;if(String(uf.action||"")==="observe")return lf.includes(String(uf.sourceNodeId||""));return D0.has(String(uf.sourceMarkerId||""))}),x0=PF+Math.max(1,lf.length)*h1,ku=(uf)=>{let vf=_y(uf.target.value);if(typeof A==="function")A(vf);window.setTimeout(j0,0)},X0=()=>OM({title:`${_?.id||"pipeline"}-${D||"epoch"}-gantt`,meta:[`run ${D||"--"}`,`${z0(p.startMs)} -> ${z0(p.endMs)}`,`duration ${$1(p.durationMs)}`,`${_f.label} / ${IF(_f.pxPerMinute)} px/min`,`${lf.length}/${Vf.length} nodes`,`${S.length} markers`],visibleNodeIds:lf,intervals:m,markers:S.filter((uf)=>lf.includes(String(uf.nodeId||""))),arrows:O0,ticks:Yf,bounds:p,chartHeight:t,backendLayout:Y}),Qu=Nf(C?.gantt?.diagnostics)?C.gantt.diagnostics:null;return X(I1,{title:"Epoch 甘特图",eyebrow:`${_?.id||"pipeline"} / ${f.length} epochs`,className:"pipeline-wide-panel",actions:X("div",{className:"pipeline-gantt-actions"},X("select",{value:D,disabled:f.length===0,onChange:(uf)=>U(uf.target.value),"data-testid":"pipeline-epoch-select"},f.map((uf)=>X("option",{key:uf.runId,value:uf.runId},gF(f,uf)))),X("label",{className:"pipeline-gantt-toggle"},X("input",{type:"checkbox","data-testid":"pipeline-gantt-auto-hide-idle",checked:G,onChange:(uf)=>{H(Boolean(uf.target.checked)),window.setTimeout(j0,0)}}),X("span",null,"自动隐藏空闲列")),X("label",{className:"pipeline-gantt-scale"},X("span",null,X("b",null,"时间尺度"),X("em",{"data-testid":"pipeline-gantt-scale-label"},`${_f.label} · ${IF(_f.pxPerMinute)} px/min`)),X("input",{type:"range",min:0,max:100,step:0.01,value:v,onChange:ku,"aria-label":"调整甘特图时间尺度","data-testid":"pipeline-gantt-time-scale"}),X("small",null,X("span",null,"全局"),X("span",null,"细节"))),u?X("button",{type:"button",className:"ghost-btn",onClick:X0,disabled:lf.length===0,"data-testid":"pipeline-export-gantt"},"导出甘特图"):null,u?X(X1,{title:`Pipeline Epoch ${u.runId}`,data:u,onOpen:O,testId:"raw-pipeline-epoch-gantt"}):null)},!u?X(cu,{title:"暂无 Epoch",text:"当前 pipeline 还没有完整运行记录。"}):m.length===0?X(cu,{title:"暂无时间区间",text:"等待 D601 Pipeline backend 在 procedure summary 中返回 startedAt / finishedAt。"}):X("div",{className:"pipeline-gantt-wrap"},X("div",{className:`pipeline-gantt-detail-layout ${x?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-gantt-detail-layout","data-sidebar-open":x?"true":"false"},X("div",{className:"pipeline-gantt-main"},X("div",{className:"pipeline-gantt-main-head"},X("div",{className:"pipeline-gantt-meta"},X("span",null,`time ${z0(p.startMs)} -> ${z0(p.endMs)}`),X("span",null,`duration ${$1(p.durationMs)}`),X("span",null,`scale ${_f.label} / ${IF(_f.pxPerMinute)} px/min`),X("span",null,`layout ${R}`),Qu?X("span",null,`align ${Qu.timeAxisAlignmentOk===!1?"check":"ok"}`):null,X("span",null,`visible ${lf.length}/${Vf.length} nodes`),C?X("span",null,`markers ${S.length}`):null,G&&u0>0?X("span",null,`hidden idle ${u0}`):null),!x?X("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!K?.mode,onClick:()=>c(!0),"data-testid":"pipeline-gantt-sidebar-toggle"},K?.mode?"展开详情":"点击甘特图元素展开详情"):null),X("div",{className:"pipeline-gantt-viewport",ref:N,"data-testid":"pipeline-epoch-gantt","data-pipeline-id":_?.id||"","data-run-id":D,"data-layout-source":R,"data-start-ms":String(p.startMs),"data-end-ms":String(p.endMs),"data-chart-height":String(t)},X("div",{className:"pipeline-gantt-board",style:{gridTemplateColumns:Af,minWidth:`${x0}px`}},X("div",{className:"pipeline-gantt-head time"},"Time"),lf.length===0?X("div",{className:"pipeline-gantt-head empty"},"当前时间窗无工作节点"):lf.map((uf)=>X("div",{key:`head-${uf}`,className:"pipeline-gantt-head node",title:uf,"data-testid":"pipeline-gantt-head-node","data-node-id":uf},X(sT,{value:uf}))),X("div",{className:"pipeline-gantt-time-axis",style:{height:`${t}px`}},Yf.map((uf)=>{let vf=aq(uf,p,t,Y);return X("div",{key:`tick-${uf.ms}-${vf}`,className:"pipeline-gantt-tick",style:{top:`${vf}px`},"data-testid":"pipeline-gantt-tick","data-ms":String(uf.ms),"data-y":String(vf)},X("b",null,z0(uf.ms)),X("span",null,`+${$1(Number(uf.offsetMs??Number(uf.ms)-Number(p.startMs)))}`))})),lf.length>0?X("svg",{className:"pipeline-gantt-arrow-layer",width:lf.length*h1,height:t,viewBox:`0 0 ${lf.length*h1} ${t}`,style:{left:`${PF}px`,top:`${CF}px`,width:`${lf.length*h1}px`,height:`${t}px`},"aria-hidden":"true"},X("defs",null,X("marker",{id:"pipeline-gantt-arrowhead",viewBox:"0 0 10 10",refX:9,refY:5,markerWidth:6,markerHeight:6,orient:"auto-start-reverse"},X("path",{d:"M 0 0 L 10 5 L 0 10 z",fill:"context-stroke"}))),O0.map((uf)=>{let vf=Fu.get(String(uf.targetMarkerId||""));if(!vf)return null;let a0=Fu.get(String(uf.sourceMarkerId||"")),Bf=String(a0?.nodeId||uf.sourceNodeId||""),v0=lf.indexOf(Bf),i0=lf.indexOf(String(vf.nodeId||""));if(v0<0||i0<0)return null;let d0=v0*h1+h1/2,b0=i0*h1+h1/2,m1=a0?Iu(a0,p,t,Y):Iu(vf,p,t,Y),ef=Iu(vf,p,t,Y);return X("path",{key:uf.id,className:`pipeline-gantt-arrow ${String(uf.sourceKind||"").toLowerCase()} ${String(uf.status||"").toLowerCase()} ${String(uf.action||"").toLowerCase()}`,d:dq(d0,m1,b0,ef),markerEnd:"url(#pipeline-gantt-arrowhead)","data-testid":String(uf.action||"")==="observe"?"pipeline-gantt-observation-arrow":"pipeline-gantt-arrow","data-source-node-id":String(uf.sourceNodeId||""),"data-target-node-id":String(uf.targetNodeId||""),"data-target-marker-id":String(uf.targetMarkerId||""),"data-action":String(uf.action||""),"data-source-y":String(m1),"data-target-y":String(ef)})})):null,lf.length===0?X("div",{className:"pipeline-gantt-empty-col",style:{height:`${t}px`}},"滚动到有活动的时间段后,相关 node 列会自动出现。"):lf.map((uf)=>{let vf=m.filter((Bf)=>Bf.nodeId===uf),a0=S.filter((Bf)=>String(Bf.nodeId||"")===uf);return X("div",{key:`col-${uf}`,className:"pipeline-gantt-node-col",style:{height:`${t}px`}},vf.map((Bf)=>{let v0=f2(Bf,p,t,Y),i0=tF(Bf,p,t,Y),d0=oq(Bf,p,t,Y),b0=String(Bf.procedureRunId||`${uf}-${Bf.startMs}`);return X("button",{key:b0,type:"button",className:`pipeline-gantt-bar ${Bf.status} ${Bf.live?"live":""} ${xf===b0?"selected":""}`,style:{top:`${v0}px`,height:`${d0}px`},title:`${uf} ${Bf.status} ${z0(Bf.startedAt||Bf.startMs)} -> ${z0(Bf.finishedAt||Bf.endMs)}`,onClick:()=>z(Bf),"data-testid":"pipeline-gantt-line","data-node-id":uf,"data-procedure-run-id":String(Bf.procedureRunId||""),"data-status":String(Bf.status||""),"data-live":Bf.live?"true":"false","data-start-ms":String(Bf.startMs||""),"data-end-ms":String(Bf.endMs||""),"data-y1":String(v0),"data-y2":String(i0),"data-natural-height":String(Math.max(0,i0-v0))},X("strong",null,Bf.status||"working"),X("span",null,$1(Bf.durationMs)))}),a0.map((Bf)=>X("button",{key:Bf.id,type:"button",className:`pipeline-gantt-marker ${Bf.kind} ${Bf.tone||""} ${Bf.status||""} ${sf===String(Bf.id)?"selected":""}`,style:{top:`${Iu(Bf,p,t,Y)}px`},title:`${Bf.label||"event"} / ${z0(Bf.timestampIso||Bf.timestamp||Bf.ms)}`,onClick:()=>W(Bf),"data-testid":Bf.kind==="prompt"?"pipeline-gantt-prompt-marker":"pipeline-gantt-control-marker","data-marker-id":String(Bf.id||""),"data-ms":String(Bf.ms??Bf.eventMs??""),"data-y":String(Iu(Bf,p,t,Y))})))})))),x?X(tT,{selection:K,runDetails:l,nodeDetails:j,nodeDetailsState:J,onRaw:O,onCollapse:()=>c(!1)}):null)))}function A_(){return{loading:!1,actionLoading:"",error:"",message:"",details:null,fetchedAt:null,appendPrompt:"",guidePrompt:"",modifyPrompt:"",approveReason:"",redoReason:""}}function d_(){return{mode:"",runId:"",interval:null,marker:null}}function cF(){return{runId:"",loading:!1,error:"",details:null,fetchedAt:null}}function Ol(f,u){return`${f}/microservices/pipeline/proxy${u}`}function gM({activeRun:f,pipelineRuns:u,selectedRunId:_,onRunChange:y,selectedNodeId:$,selectedNodeConfig:l,selectedNodeRuntime:j,control:J,onControlChange:F,onFetch:A,onAction:U,onRaw:z,onCollapse:W}){let K=String(f?.runId||""),q=String(j?.status||"pending"),E=!K||!$||J.loading||Boolean(J.actionLoading),O=(H)=>(Z)=>F({[H]:Z.target.value,error:"",message:""}),G=u.length>0?u:f?[f]:[];return X("aside",{className:"pipeline-node-control","data-testid":"pipeline-node-control"},X("div",{className:"pipeline-node-control-head"},X("div",null,X("p",{className:"panel-eyebrow"},"Manual Node Control"),X("h3",null,$||"点击控制图中的 node")),X("div",{className:"pipeline-node-control-head-actions"},$?X(uy,{status:q},q):X(uy,{status:"pending"},"idle"),X("button",{type:"button",className:"ghost-btn mini",onClick:W,"data-testid":"pipeline-node-sidebar-collapse"},"收起"))),X("div",{className:"pipeline-control-runbar"},X("label",null,X("span",null,"目标 run"),X("select",{value:K||_,disabled:G.length===0,onChange:(H)=>y(H.target.value),"data-testid":"pipeline-node-run-select"},G.map((H)=>X("option",{key:H.runId,value:H.runId},`${H.runId||"--"} / ${H.status||"--"}`)))),X("button",{type:"button",className:"ghost-btn",disabled:E,onClick:A,"data-testid":"pipeline-node-fetch"},J.loading?"抓取中":"抓取过程"),J.details?X(X1,{title:`Pipeline Node ${$}`,data:J.details,onOpen:z,testId:"raw-pipeline-node-control"}):null),X("div",{className:"pipeline-control-meta"},X("span",null,X("b",null,"kind"),String(l?.kind||"--")),X("span",null,X("b",null,"procedure"),String(j?.currentProcedureRunId||"--")),X("span",null,X("b",null,"attempts"),String(j?.attempts??"--")),X("span",null,X("b",null,"updated"),z0(f?.updatedAt))),!$?X(cu,{title:"未选择 node",text:"点击 React Flow 控制图中的任意 node 后,可抓取执行过程、追加 prompt、下发引导、增量修改、审核通过或重做。"}):null,X(H0,{error:J.error,wide:!0}),J.message?X("div",{className:"form-success wide"},J.message):null,X("div",{className:"pipeline-control-actions"},X("label",null,X("span",null,"实时追加 prompt(仅 running node)"),X("textarea",{value:J.appendPrompt,onChange:O("appendPrompt"),placeholder:"让当前执行中的 agent 继续、补充检查或调整当前步骤...",rows:4,disabled:!$,"data-testid":"pipeline-node-append-input"}),X("button",{type:"button",className:"primary-btn compact",disabled:E||!String(J.appendPrompt||"").trim(),onClick:()=>U("append"),"data-testid":"pipeline-node-append-button"},J.actionLoading==="append"?"追加中":"追加到运行中 node")),X("label",null,X("span",null,"下次尝试引导 prompt"),X("textarea",{value:J.guidePrompt,onChange:O("guidePrompt"),placeholder:"给该 node 下一次 attempt 的执行提示;不会立即打断当前 session。",rows:4,disabled:!$,"data-testid":"pipeline-node-guide-input"}),X("button",{type:"button",className:"ghost-btn compact",disabled:E||!String(J.guidePrompt||"").trim(),onClick:()=>U("guide"),"data-testid":"pipeline-node-guide-button"},J.actionLoading==="guide"?"下发中":"下发 guide")),X("label",null,X("span",null,"完成后增量修改 prompt"),X("textarea",{value:J.modifyPrompt,onChange:O("modifyPrompt"),placeholder:"在该 node 已完成结果基础上追加修改要求;runner 会重跑目标 node,并保留同 node 既有 OA 输出作为上下文。",rows:4,disabled:!$,"data-testid":"pipeline-node-modify-input"}),X("button",{type:"button",className:"ghost-btn compact",disabled:E||!String(J.modifyPrompt||"").trim(),onClick:()=>U("modify"),"data-testid":"pipeline-node-modify-button"},J.actionLoading==="modify"?"排队中":"增量修改 node")),X("label",null,X("span",null,"Monitor 审核通过原因"),X("textarea",{value:J.approveReason,onChange:O("approveReason"),placeholder:"当流程配置开启 monitor 审核时,记录审核通过原因并释放后续 node。",rows:3,disabled:!$,"data-testid":"pipeline-node-approve-input"}),X("button",{type:"button",className:"primary-btn compact",disabled:E||!String(J.approveReason||"").trim(),onClick:()=>U("approve"),"data-testid":"pipeline-node-approve-button"},J.actionLoading==="approve"?"提交中":"审核通过")),X("label",null,X("span",null,"重做 / restart 原因"),X("textarea",{value:J.redoReason,onChange:O("redoReason"),placeholder:"说明为什么需要重做;runner 会重置目标 node 以及非 rework 下游 node。",rows:4,disabled:!$,"data-testid":"pipeline-node-redo-input"}),X("button",{type:"button",className:"danger-btn compact",disabled:E||!String(J.redoReason||"").trim(),onClick:()=>U("redo"),"data-testid":"pipeline-node-redo-button"},J.actionLoading==="redo"?"排队中":"重做 node"))),X("div",{className:"pipeline-control-evidence"},X("strong",null,"Node 过程索引"),X(cM,{details:J.details,selectedNodeId:$,selectedNodeRuntime:j,control:J,onRaw:z})))}function eq({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((s)=>s.id==="pipeline")||null,[$,l]=Bu({loading:!1,error:"",health:null,snapshot:null,oaDiagnostics:null,minimaxQuota:null,refreshedAt:null}),[j,J]=Bu(""),[F,A]=Bu(""),[U,z]=Bu(""),[W,K]=Bu(A_()),[q,E]=Bu({}),[O,G]=Bu(d_()),[H,Z]=Bu(cF()),[V,L]=Bu(Tl),[M,N]=Bu(!1),[D,x]=Bu(!1),c=e_(0),v=e_(!1),C=e_(0),P=e_(""),w=e_({}),r=e_(""),S=e_("");async function T(s={}){let Of=s.silent===!0;if(!y)return;if(v.current)return;v.current=!0;let qf=c.current+1;if(c.current=qf,!Of)l((Cf)=>({...Cf,loading:!0,error:""}));try{let Cf=`__unideskArrayLimit=registry.components:80,runs:${ST}`,[_0,G0,If]=await Promise.all([a_(`${_}/microservices/pipeline/proxy/api/snapshot?${Cf}`,{cache:"no-store"}),a_(`${_}/microservices/pipeline/proxy/api/oa-event-flow/diagnostics`,{cache:"no-store"}).catch((Au)=>({ok:!1,error:Mf(Au,"OA event flow diagnostics failed")})),a_(`${_}/microservices/pipeline/proxy/api/model-quota/minimax`,{cache:"no-store"}).catch((Au)=>({ok:!1,error:Mf(Au,"MiniMax quota failed")}))]);if(qf!==c.current)return;let h0={ok:_0?.ok!==!1,service:"pipeline-v2-control snapshot"};l({loading:!1,error:"",health:h0,snapshot:_0,oaDiagnostics:G0,minimaxQuota:If,refreshedAt:new Date})}catch(Cf){if(qf!==c.current)return;l((_0)=>({..._0,loading:!1,error:Mf(Cf,"Pipeline 加载失败")}))}finally{v.current=!1}}c1(()=>{if(T(),!y)return;let s=()=>{if(p5())T({silent:!0})},Of=window.setInterval(()=>{s()},Fq),qf=()=>{if(p5())s()};return document.addEventListener("visibilitychange",qf),()=>{window.clearInterval(Of),document.removeEventListener("visibilitychange",qf)}},[y?.id,y?.runtime?.providerStatus,_]);let Y=oT(y),R=dT(y),m=aT(y),p=$.snapshot||{},n=$.oaDiagnostics||null,_f=$.minimaxQuota||null,{components:t,pipelines:ff,runs:Gf}=eT(p),zf=String(Gf[0]?.pipelineId||""),jf=(zf?ff.find((s)=>String(s.id||"")===zf):null)||ff[0]||{},Wf=ff.find((s)=>String(s.id||"")===j)||jf,Vf=String(Wf.id||""),Zf=Iq(Wf),h=eF(Wf),g=Lq(Gf,Vf),I=NM(Gf,Vf),$f=I.find((s)=>String(s?.runId||"")===F)||g,lf=String(H.runId||"")===String($f?.runId||"")?yM(H.details):null,Af=$M($f,lf),Yf=String(Af?.runId||""),xf=Zf.find((s)=>String(s?.id||"")===U)||null,sf=U?cq(Af,U):null,j0=uM(Gf),u0=FM(t),D0=Number($.health?.components)||qq(p,"registry.components",t.length),Fu=qq(p,"runs",Gf.length),O0=Vq(Wf,Af,t),x0={nodes:O0.nodes.map((s)=>s.id===U?{...s,selected:!0,className:`${s.className||""} selected-control-node`}:s),edges:O0.edges},ku=ff.map((s)=>{let Of=String(s.id||"pipeline"),qf=Lq(Gf,Of);return{title:`${Of}-${qf?.runId||"snapshot"}`,flow:Vq(s,qf,t)}}),X0=String(O?.runId||Yf||""),Qu=String(O?.interval?.nodeId||O?.marker?.nodeId||""),uf=X0&&Qu?q[hF(X0,Qu)]||null:null,vf=s5(W.details,X0,Qu),a0=s5(uf?.details,X0,Qu)||vf,Bf=X0&&Qu?{...Nf(uf)?uf:{},runId:X0,nodeId:Qu,details:a0,loading:Boolean(uf?.loading)||!a0&&Boolean(W.loading)&&U===Qu,error:String(uf?.error||""),fetchedAt:uf?.fetchedAt||(vf?W.fetchedAt:null)}:null,v0=I.map((s)=>String(s?.runId||"")).filter(Boolean).join("|"),i0=Zf.map((s)=>String(s?.id||"")).filter(Boolean).join("|");c1(()=>{r.current=U},[U]),c1(()=>{S.current=Yf},[Yf]),c1(()=>{if(!F||v0.split("|").includes(F))return;A("")},[F,v0]),c1(()=>{if(!U||i0.split("|").includes(U))return;z(""),K(A_()),G(d_()),N(!1),x(!1)},[U,i0]),c1(()=>{if(!U)N(!1)},[U]),c1(()=>{if(!O.mode)x(!1)},[O.mode]);async function d0(s=Yf,Of={}){if(!s){Z(cF());return}let qf=_y(Of.scale??V??Tl),Cf=`${s}:timeline`;if(P.current===Cf)return;P.current=Cf;let _0=Of.silent===!0,G0=C.current+1;C.current=G0,Z((If)=>({runId:s,scale:qf,loading:!_0||String(If.runId||"")!==s||!If.details,error:"",details:_0&&If.runId===s?If.details:If.runId===s?If.details:null,fetchedAt:If.runId===s?If.fetchedAt:null}));try{let[If,h0]=await Promise.all([a_(Ol(_,`/api/node-control/runs/${encodeURIComponent(s)}?tail=160&view=timeline`),{cache:"no-store",strictJson:!0}),a_(Ol(_,`/api/runs/${encodeURIComponent(s)}`),{cache:"no-store"}).catch((Au)=>({ok:!1,runSummaryError:Mf(Au,"抓取评分失败")}))]);if(G0!==C.current)return;Z({runId:s,scale:qf,loading:!1,error:"",details:{...If,run:Nf(h0?.run)?h0.run:void 0,runSummaryError:h0?.runSummaryError},fetchedAt:new Date})}catch(If){if(G0!==C.current)return;Z((h0)=>({runId:s,scale:qf,loading:!1,error:Mf(If,"抓取 epoch 执行过程失败"),details:h0.runId===s?h0.details:null,fetchedAt:h0.runId===s?h0.fetchedAt:null}))}finally{if(P.current===Cf)P.current=""}}function b0(s,Of,qf){let Cf=hF(s,Of);E((_0)=>{let G0={..._0,[Cf]:{...Nf(_0?.[Cf])?_0[Cf]:{},runId:s,nodeId:Of,...qf}},If=Object.keys(G0);if(If.length>32)for(let h0 of If.slice(0,If.length-32))delete G0[h0];return G0})}async function m1(s,Of){if(!s||!Of)return;let qf=hF(s,Of),Cf=Number(w.current?.[qf]||0)+1;w.current={...w.current,[qf]:Cf},b0(s,Of,{loading:!0,error:""});try{let _0=await a_(Ol(_,`/api/node-control/runs/${encodeURIComponent(s)}/nodes/${encodeURIComponent(Of)}?tail=160`),{cache:"no-store",strictJson:!0});if(Number(w.current?.[qf]||0)!==Cf)return;let G0=new Date;if(b0(s,Of,{loading:!1,details:_0,fetchedAt:G0,error:""}),r.current===Of&&S.current===s)K((If)=>({...If,loading:!1,details:_0,fetchedAt:G0,error:""}))}catch(_0){if(Number(w.current?.[qf]||0)!==Cf)return;b0(s,Of,{loading:!1,error:Mf(_0,"抓取 Gantt node 详情失败")})}}c1(()=>{if(!Yf){Z(cF());return}d0(Yf);let s=()=>{if(p5())d0(Yf,{silent:!0})},Of=window.setInterval(()=>{s()},Fq),qf=()=>{if(p5())s()};return document.addEventListener("visibilitychange",qf),()=>{window.clearInterval(Of),document.removeEventListener("visibilitychange",qf)}},[Yf,_]);async function ef(s=Yf,Of=U){if(!s||!Of){K((qf)=>({...qf,error:"请先选择 run 和 node",message:""}));return}K((qf)=>({...qf,loading:!0,error:"",message:""}));try{let qf=await a_(Ol(_,`/api/node-control/runs/${encodeURIComponent(s)}/nodes/${encodeURIComponent(Of)}?tail=160`),{cache:"no-store",strictJson:!0}),Cf=new Date;K((_0)=>({..._0,loading:!1,details:qf,fetchedAt:Cf,error:""})),b0(s,Of,{loading:!1,details:qf,fetchedAt:Cf,error:""})}catch(qf){K((Cf)=>({...Cf,loading:!1,error:Mf(qf,"抓取 node 执行过程失败")}))}}async function iu(s){let Of=String(s?.runId||Yf||""),qf=String(s?.nodeId||"");if(G({mode:"interval",runId:Of,interval:s,marker:null}),x(!0),!Of||!qf)return;if(Of!==Yf)A(Of);z(qf),K(A_()),d0(Of,{silent:!0}),m1(Of,qf)}async function f3(s){let Of=String(s?.runId||Yf||""),qf=String(s?.nodeId||"");if(G({mode:"event",runId:Of,interval:null,marker:s}),x(!0),!Of)return;if(Of!==Yf)A(Of);if(d0(Of,{silent:!0}),!qf)return;z(qf),K(A_()),m1(Of,qf)}async function u3(s){if(!Yf||!U){K((Cf)=>({...Cf,error:"请先选择 run 和 node",message:""}));return}let Of=s==="append"?"prompts":s,qf=s==="append"?W.appendPrompt:s==="guide"?W.guidePrompt:s==="modify"?W.modifyPrompt:s==="approve"?W.approveReason:W.redoReason;if(!String(qf||"").trim()){K((Cf)=>({...Cf,error:"操作内容不能为空",message:""}));return}K((Cf)=>({...Cf,actionLoading:s,error:"",message:""}));try{let Cf=s==="redo"||s==="approve"?{reason:qf,source:"unidesk-frontend",sourceKind:"webui"}:{prompt:qf,source:"unidesk-frontend",sourceKind:"webui"},_0=await a_(Ol(_,`/api/node-control/runs/${encodeURIComponent(Yf)}/nodes/${encodeURIComponent(U)}/${Of}`),{method:"POST",body:JSON.stringify(Cf)});if(K((G0)=>({...G0,actionLoading:"",details:_0,fetchedAt:new Date,appendPrompt:s==="append"?"":G0.appendPrompt,guidePrompt:s==="guide"?"":G0.guidePrompt,modifyPrompt:s==="modify"?"":G0.modifyPrompt,approveReason:s==="approve"?"":G0.approveReason,redoReason:s==="redo"?"":G0.redoReason,message:s==="append"?"已追加到运行中 node":s==="guide"?"已下发 guide,等待 runner 处理":s==="modify"?"已排队增量修改命令":s==="approve"?"已提交审核通过决策":"已排队重做命令"})),await ef(Yf,U),await d0(Yf,{silent:!0}),s!=="append")await T()}catch(Cf){K((_0)=>({..._0,actionLoading:"",error:Mf(Cf,"node 控制操作失败")}))}}if(!y)return X(cu,{title:"Pipeline 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=pipeline"});return X("div",{className:"pipeline-page","data-testid":"pipeline-page"},X(I1,{title:"Pipeline v2 工作台",eyebrow:"D601 Snapshot 用户服务",actions:X("div",{className:"panel-actions"},X("button",{type:"button",className:"ghost-btn",onClick:T,disabled:$.loading,"data-testid":"pipeline-refresh-button"},$.loading?"刷新中":"刷新"),X(X1,{title:"Pipeline 用户服务",data:y,onOpen:u,testId:"raw-pipeline-service"}))},X("div",{className:"pipeline-hero"},X("div",null,X("div",{className:"node-version-line"},X(uy,{status:Y.providerStatus==="online"?"online":"warn"},Y.providerStatus||"unknown"),X("span",null,y.providerId),X("span",null,m.public?"公网暴露":"仅 UniDesk frontend 代理访问")),X("p",{className:"muted paragraph"},y.description)),X("div",{className:"microservice-ref-card"},X("span",null,"Repo"),X("strong",null,R.url||"--"),X("code",null,R.commitId||"--")),X("div",{className:"microservice-ref-card"},X("span",null,"D601 Docker"),X("strong",null,`${m.nodeBindHost||"--"}:${m.nodePort||"--"}`),X("code",null,`${R.composeFile||"--"} / ${R.composeService||"--"}`))),X(H0,{error:$.error,wide:!0})),X("div",{className:"pipeline-grid"},X(I1,{title:"控制图",eyebrow:`${Wf.id||"pipeline"} / run ${Af?.status||"--"}`,className:"pipeline-wide-panel",actions:X("div",{className:"pipeline-toolbar"},X("select",{value:Vf,disabled:ff.length===0,onChange:(s)=>{J(s.target.value),A(""),z(""),K(A_()),G(d_()),N(!1),x(!1)},"data-testid":"pipeline-select"},ff.map((s)=>X("option",{key:s.id,value:s.id},s.id||s.key))),X("select",{value:Yf,disabled:I.length===0,onChange:(s)=>{if(A(s.target.value),K(A_()),G(d_()),N(!1),x(!1),U)ef(s.target.value,U)},"data-testid":"pipeline-run-select"},I.map((s)=>X("option",{key:s.runId,value:s.runId},gF(I,s)))),X("button",{type:"button",className:"ghost-btn",disabled:x0.nodes.length===0,onClick:()=>kq(x0,`${Wf.id||"pipeline"}-${Af?.runId||"snapshot"}`),"data-testid":"pipeline-export-graph"},"导出渲染图"),X("button",{type:"button",className:"ghost-btn",disabled:ku.every((s)=>s.flow.nodes.length===0),onClick:()=>XM(ku),"data-testid":"pipeline-export-all-graphs"},"批量导出"))},Zf.length===0?X(cu,{title:"暂无控制图",text:"等待 D601 pipeline backend 返回 config.nodes / config.edges"}):X("div",{className:`pipeline-control-shell ${M?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-control-shell","data-sidebar-open":M?"true":"false"},X("div",{className:"pipeline-flow-frame","data-testid":"pipeline-react-flow"},X(uq,{nodes:x0.nodes,edges:x0.edges,nodeTypes:xT,edgeTypes:RT,fitView:!0,fitViewOptions:{padding:0.18},nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,minZoom:0.25,maxZoom:1.4,proOptions:{hideAttribution:!0},onNodeClick:(s,Of)=>{let qf=String(Of.id);if(z(qf),K(A_()),N(!0),Yf)ef(Yf,qf)}},X(yq,{gap:22,size:1,color:"rgba(215, 161, 58, 0.24)"}),X(lq,{showInteractive:!1})),!M?X("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!U,onClick:()=>N(!0),"data-testid":"pipeline-node-sidebar-toggle"},U?"展开 node 控制":"点击 node 展开控制"):null),M?X(gM,{activeRun:Af,pipelineRuns:I,selectedRunId:F,onRunChange:(s)=>{if(A(s),K(A_()),G(d_()),U)ef(s,U)},selectedNodeId:U,selectedNodeConfig:xf,selectedNodeRuntime:sf,control:W,onControlChange:(s)=>K((Of)=>({...Of,...s})),onFetch:()=>ef(),onAction:u3,onRaw:u,onCollapse:()=>N(!1)}):null),X("div",{className:"pipeline-flow-summary"},X("span",null,`${x0.nodes.length} nodes`),X("span",null,`${x0.edges.length} edges`),X("span",null,`${ff.length} pipelines`),X("span",null,`source config+components(${t.length})`),X("span",null,`run ${Af?.runId||"--"}`),X("span",null,`score ${iF(Af)}`),X("span",null,U?`selected ${U}`:"click node to control"))),X(iM,{epochs:I,activeRun:Af,activePipeline:Wf,pipelineNodes:Zf,pipelineEdges:h,selection:O,detailOpen:D,onDetailOpenChange:x,runDetails:H,nodeDetails:a0,nodeDetailsState:Bf,ganttScale:V,onGanttScaleChange:L,onIntervalSelect:iu,onMarkerSelect:f3,onRunChange:(s)=>{if(A(s),K(A_()),G(d_()),x(!1),U)ef(s,U)},onRaw:u}),X(I1,{title:"观测指标",eyebrow:$.refreshedAt?`Updated ${u2($.refreshedAt)}`:"Snapshot"},X("div",{className:"metric-grid"},X(Hu,{label:"Health",value:$.health?.ok?"OK":"--",hint:$.health?.service||"D601 /health",tone:$.health?.ok?"ok":"warn"}),X(Hu,{label:"组件",value:D0,hint:"components registry",tone:p?.registry?.ok===!1?"warn":"ok"}),X(Hu,{label:"Pipeline",value:ff.length,hint:`${Zf.length} nodes / ${h.length} edges`}),X(Hu,{label:"运行记录",value:Fu,hint:`${j0.succeeded||0} succeeded / ${j0.running||0} running`}),X(Hu,{label:"OA 记录",value:Array.isArray(g?.submissions)?g.submissions.length:0,hint:g?.runId||"latest run"}),X(Hu,{label:"Procedure",value:Array.isArray(g?.procedureRuns)?g.procedureRuns.length:0,hint:g?.status||"no run"}),X(Hu,{label:"Score",value:iF(Af),hint:Af?.runId||"selected epoch",tone:uQ(Af)})),X("div",{className:"panel-actions inline-actions"},X(X1,{title:"Pipeline Snapshot",data:p,onOpen:u,testId:"raw-pipeline-snapshot"}))),X(I1,{title:"评分器",eyebrow:Af?.runId||"selected epoch"},X(JM,{run:Af,onRaw:u})),X(I1,{title:"MiniMax 限额",eyebrow:"model/minimax-m27 quota"},X(kM,{quota:_f,onRaw:u})),X(I1,{title:"OA 事件流",eyebrow:"100% event-driven diagnostics",className:"pipeline-wide-panel"},X(mM,{diagnostics:n,onRaw:u})),X(I1,{title:"组件矩阵",eyebrow:`${u0.length} classes`},u0.length===0?X(cu,{title:"暂无组件",text:"等待 D601 pipeline backend 返回 registry.components"}):X("div",{className:"component-strata"},u0.map((s)=>X("article",{key:s.name,className:"component-stratum"},X("span",null,s.name),X("strong",null,s.count)))),X("div",{className:"pipeline-component-list"},t.slice(0,12).map((s)=>X("span",{key:s.key,className:"data-chip"},X("b",null,s.componentClass||"--"),X("span",null,s.id||s.key||"--"))))),X(I1,{title:"Epoch 列表",eyebrow:`${I.length}/${Fu} preview`},I.length===0?X(cu,{title:"暂无运行记录",text:"当前 pipeline 在 .state/pipeline-runs 中还没有 epoch。"}):X("div",{className:"pipeline-run-list"},I.map((s)=>{let Of=String(s?.runId||"")===Yf?Af:s;return X("article",{key:s.runId,className:`pipeline-run-card ${String(s.runId||"")===Yf?"active":""}`,role:"button",tabIndex:0,onClick:()=>{A(String(s.runId||"")),G(d_())},onKeyDown:(qf)=>{if(qf.key==="Enter"||qf.key===" ")A(String(s.runId||"")),G(d_())}},X("div",{className:"node-card-head"},X("strong",null,gF(I,s)),X(uy,{status:s.status},s.status||"--")),X("div",{className:"docker-meta compact"},X("span",null,Of?.pipelineId||"--"),X("span",null,`nodes ${Array.isArray(Of?.nodes)?Of.nodes.length:0}`),X("span",null,`oa ${Array.isArray(Of?.submissions)?Of.submissions.length:0}`),X("span",null,`procedures ${Array.isArray(Of?.procedureRuns)?Of.procedureRuns.length:0}`),X(jM,{run:Of})),X("p",{className:"muted paragraph"},t5(Of?.task)),X("span",{className:"pipeline-run-time"},z0(Of?.updatedAt)))}))),X(I1,{title:"运行材料索引",eyebrow:Af?.runId||"selected epoch",className:"pipeline-wide-panel"},X(pM,{activeRun:Af,onRaw:u}))))}var J2=rf(I0(),1);var e=J2.default.createElement,{useEffect:nM}=J2.default,l2=J2.default.useState,lQ={id:"",sequenceNo:"",contractNo:"",name:"",currentStatus:"",pending:"",paymentStatus:"",notes:""};function tM(f){return f.toLocaleTimeString("zh-CN",{hour12:!1})}function sM({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return e("span",{className:`status-badge ${_}`},u||f||"unknown")}function j2({label:f,value:u,hint:_,tone:y}){return e("article",{className:`metric-card ${y||""}`},e("div",{className:"metric-label"},f),e("div",{className:"metric-value"},u),e("div",{className:"metric-hint"},_))}function jQ({title:f,eyebrow:u,actions:_,children:y,className:$}){return e("section",{className:`panel ${$||""}`},e("div",{className:"panel-head"},e("div",null,u?e("p",{className:"panel-eyebrow"},u):null,e("h2",null,f)),_?e("div",{className:"panel-actions"},_):null),e("div",{className:"panel-body"},y))}function fH({title:f,data:u,onOpen:_,testId:y}){return e("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function uH({title:f,text:u}){return e("div",{className:"empty-state"},e("strong",null,f),e("span",null,u))}function oM(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function aM(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function dM(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function G$(f,u){return`${f}/microservices/project-manager/proxy${u}`}function eM(f){return{id:String(f.id||""),sequenceNo:f.sequenceNo===null||f.sequenceNo===void 0?"":String(f.sequenceNo),contractNo:String(f.contractNo||""),name:String(f.name||""),currentStatus:String(f.currentStatus||""),pending:String(f.pending||""),paymentStatus:String(f.paymentStatus||""),notes:String(f.notes||"")}}function fS(f){return{sequenceNo:f.sequenceNo===""?null:Number(f.sequenceNo),contractNo:String(f.contractNo||"").trim(),name:String(f.name||"").trim(),currentStatus:String(f.currentStatus||"").trim(),pending:String(f.pending||"").trim(),paymentStatus:String(f.paymentStatus||"").trim(),paymentRatio:String(f.paymentStatus||"").trim(),notes:String(f.notes||"").trim()}}function JQ(f){return String(f||"item").replace(/[^A-Za-z0-9_-]+/g,"-")}function uS(f){let u=new Uint8Array(f),_="",y=32768;for(let $=0;$e("tr",{key:$.id,className:u===$.id?"active-row":"","data-testid":`project-manager-row-${JQ($.id)}`},e("td",null,$.sequenceNo??"--"),e("td",null,e("strong",null,$.contractNo||"--"),e("code",null,$.id||"--")),e("td",null,e("strong",null,$.name||"--"),e("span",{className:"muted block"},$.sourceFile||"--")),e("td",null,$.currentStatus||"--"),e("td",null,e("span",{className:"preline"},$.pending||"--")),e("td",null,e(sM,{status:Number($.paymentRatio||0)>=1?"online":"warn"},$.paymentStatus||"--")),e("td",null,$.notes||"--"),e("td",null,e("div",{className:"inline-actions"},e("button",{type:"button",className:"ghost-btn",onClick:()=>_($),"data-testid":`project-manager-edit-${JQ($.id)}`},"编辑"),e(fH,{title:`Project ${$.contractNo||$.id}`,data:$,onOpen:y,testId:`raw-project-${JQ($.id)}`}))))))))}function _H({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((N)=>N.id==="project-manager")||null,[$,l]=l2({loading:!1,saving:!1,importing:!1,exporting:!1,error:"",notice:"",health:null,list:null,refreshedAt:null}),[j,J]=l2({...lQ}),[F,A]=l2(""),[U,z]=l2("all");async function W(N=F,D=U){if(!y)return;l((x)=>({...x,loading:!0,error:""}));try{let x=new URLSearchParams({pageSize:"200",status:D});if(N.trim())x.set("q",N.trim());let[c,v]=await Promise.all([wf(`${_}/microservices/project-manager/health`),wf(G$(_,`/api/projects?${x.toString()}`))]);l((C)=>({...C,loading:!1,health:c,list:v,refreshedAt:new Date,error:""}))}catch(x){l((c)=>({...c,loading:!1,error:Mf(x,"Project Manager 加载失败")}))}}nM(()=>{W()},[y?.id,y?.runtime?.providerStatus]);async function K(N){N.preventDefault(),l((D)=>({...D,saving:!0,error:"",notice:""}));try{let D=fS(j);if(j.id)await wf(G$(_,`/api/projects/${encodeURIComponent(j.id)}`),{method:"PUT",body:JSON.stringify(D)});else await wf(G$(_,"/api/projects"),{method:"POST",body:JSON.stringify(D)});l((x)=>({...x,saving:!1,notice:j.id?"项目已更新":"项目已创建"})),await W()}catch(D){l((x)=>({...x,saving:!1,error:Mf(D,"保存项目失败")}))}}async function q(){if(!j.id)return;if(!window.confirm(`删除项目 ${j.contractNo||j.name||j.id} ?`))return;l((N)=>({...N,saving:!0,error:"",notice:""}));try{await wf(G$(_,`/api/projects/${encodeURIComponent(j.id)}`),{method:"DELETE"}),J({...lQ}),l((N)=>({...N,saving:!1,notice:"项目已删除"})),await W()}catch(N){l((D)=>({...D,saving:!1,error:Mf(N,"删除项目失败")}))}}async function E(N){let D=N.target.files?.[0];if(!D)return;l((x)=>({...x,importing:!0,error:"",notice:""}));try{let x=uS(await D.arrayBuffer()),c=await wf(G$(_,"/api/import/excel"),{method:"POST",body:JSON.stringify({fileName:D.name,contentBase64:x,replace:!1})});l((v)=>({...v,importing:!1,notice:`Excel 已导入 ${c.imported||0} 条项目`})),N.target.value="",await W()}catch(x){l((c)=>({...c,importing:!1,error:Mf(x,"Excel 导入失败")}))}}async function O(){l((N)=>({...N,exporting:!0,error:""}));try{let N=await _z(G$(_,"/api/projects/export.xlsx")),D=URL.createObjectURL(N),x=document.createElement("a");x.href=D,x.download=`project-manager-${new Date().toISOString().slice(0,10)}.xlsx`,document.body.appendChild(x),x.click(),x.remove(),URL.revokeObjectURL(D),l((c)=>({...c,exporting:!1,notice:"Excel 已导出"}))}catch(N){l((D)=>({...D,exporting:!1,error:Mf(N,"Excel 导出失败")}))}}if(!y)return e(uH,{title:"Project Manager 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=project-manager"});let G=oM(y),H=dM(y),Z=aM(y),V=Array.isArray($.list?.projects)?$.list.projects:[],L=$.list?.summary||{},M=$.health||{};return e("div",{className:"project-manager-page","data-testid":"project-manager-page"},e(jQ,{title:"项目管理工作台",eyebrow:"Main Server PostgreSQL 用户服务",actions:e("div",{className:"panel-actions"},e("button",{type:"button",className:"ghost-btn",disabled:$.loading,onClick:()=>W(),"data-testid":"project-manager-refresh-button"},$.loading?"刷新中":"刷新"),e("button",{type:"button",className:"ghost-btn",disabled:$.exporting,onClick:O,"data-testid":"project-manager-export-button"},$.exporting?"导出中":"导出 Excel"),e(fH,{title:"Project Manager 用户服务",data:y,onOpen:u,testId:"raw-project-manager-service"}))},e("div",{className:"project-manager-hero"},e(j2,{label:"项目总数",value:L.total??V.length,hint:`PG 表 ${M.storage?.table||"project_manager_projects"}`,tone:"ok"}),e(j2,{label:"进行中",value:L.active??"--",hint:"当前状态未完全完成"}),e(j2,{label:"已完成",value:L.completed??"--",hint:"按 完成 关键字统计",tone:"ok"}),e(j2,{label:"未全款",value:L.unpaid??"--",hint:"付款比例 < 1",tone:Number(L.unpaid||0)>0?"warn":"ok"})),e(H0,{error:$.error}),$.notice?e("div",{className:"form-success"},$.notice):null),e("div",{className:"project-manager-hero"},e("div",{className:"microservice-ref-card"},e("span",null,"Repo"),e("strong",null,H.url||"--"),e("code",null,H.commitId||"--")),e("div",{className:"microservice-ref-card"},e("span",null,"Main Server Docker"),e("strong",null,`${Z.nodeBindHost||"--"}:${Z.nodePort||"--"}`),e("code",null,`${H.composeService||"--"} / ${H.containerName||"--"}`)),e("div",{className:"microservice-ref-card"},e("span",null,"Runtime"),e("strong",null,G.providerName||y.providerId),e("code",null,`Health ${M.ok?"OK":"--"} / ${$.refreshedAt?tM($.refreshedAt):"--"}`)),e("div",{className:"microservice-ref-card"},e("span",null,"Import Source"),e("strong",null,"D601 WeChat Excel"),e("code",null,"合作项目列表_I_20260309.xlsx"))),e("div",{className:"project-manager-layout"},e(jQ,{title:"项目清单",eyebrow:"CRUD + Excel Export",actions:e("div",{className:"inline-actions project-manager-filters"},e("input",{value:F,onChange:(N)=>A(N.target.value),placeholder:"搜索合同号 / 项目名称 / 状态","data-testid":"project-manager-search"}),e("select",{value:U,onChange:(N)=>{z(N.target.value),W(F,N.target.value)},"data-testid":"project-manager-status-filter"},e("option",{value:"all"},"全部"),e("option",{value:"active"},"进行中"),e("option",{value:"completed"},"已完成"),e("option",{value:"unpaid"},"未全款")),e("button",{type:"button",className:"ghost-btn",onClick:()=>W(F,U)},"筛选"))},e(_S,{projects:V,activeId:j.id,onSelect:(N)=>J(eM(N)),onRaw:u})),e(jQ,{title:j.id?"编辑项目":"新建项目",eyebrow:"PostgreSQL Write Path"},e("form",{className:"stack-form project-manager-form",onSubmit:K,"data-testid":"project-manager-form"},j.id?e("label",null,"项目 ID",e("input",{value:j.id,disabled:!0})):null,e("label",null,"序号",e("input",{type:"number",value:j.sequenceNo,onChange:(N)=>J((D)=>({...D,sequenceNo:N.target.value}))})),e("label",null,"合同号",e("input",{value:j.contractNo,onChange:(N)=>J((D)=>({...D,contractNo:N.target.value})),required:!0})),e("label",null,"项目名称",e("input",{value:j.name,onChange:(N)=>J((D)=>({...D,name:N.target.value})),required:!0})),e("label",null,"当前状况",e("textarea",{value:j.currentStatus,onChange:(N)=>J((D)=>({...D,currentStatus:N.target.value}))})),e("label",null,"待完成",e("textarea",{value:j.pending,onChange:(N)=>J((D)=>({...D,pending:N.target.value}))})),e("label",null,"付款情况",e("input",{value:j.paymentStatus,onChange:(N)=>J((D)=>({...D,paymentStatus:N.target.value})),placeholder:"例如 1 / 0.5 / 50%"})),e("label",null,"其它",e("input",{value:j.notes,onChange:(N)=>J((D)=>({...D,notes:N.target.value}))})),e("div",{className:"inline-actions"},e("button",{type:"submit",className:"primary-btn",disabled:$.saving,"data-testid":"project-manager-save-button"},$.saving?"保存中":j.id?"保存修改":"创建项目"),e("button",{type:"button",className:"ghost-btn",onClick:()=>J({...lQ})},"清空"),j.id?e("button",{type:"button",className:"danger-btn",disabled:$.saving,onClick:q,"data-testid":"project-manager-delete-button"},"删除"):null)),e("div",{className:"project-manager-import"},e("p",{className:"muted paragraph"},"浏览器只访问 UniDesk frontend;后端通过同源用户服务代理写入主 PostgreSQL,不暴露 4233 公网端口。"),e("label",{className:"file-import"},$.importing?"导入中...":"导入 Excel",e("input",{type:"file",accept:".xlsx",onChange:E,disabled:$.importing,"data-testid":"project-manager-import-input"}))))))}var U2=rf(I0(),1);var yf=U2.default.createElement,{useEffect:yS}=U2.default,Du=U2.default.useState;function yH(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return u.toLocaleString("zh-CN",{hour12:!1})}function $S(f){return f.toLocaleTimeString("zh-CN",{hour12:!1})}function lS({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return yf("span",{className:`status-badge ${_}`},u||f||"unknown")}function F2({label:f,value:u,hint:_,tone:y}){return yf("article",{className:`metric-card ${y||""}`},yf("div",{className:"metric-label"},f),yf("div",{className:"metric-value"},u),yf("div",{className:"metric-hint"},_))}function FQ({title:f,eyebrow:u,actions:_,children:y,className:$}){return yf("section",{className:`panel ${$||""}`},yf("div",{className:"panel-head"},yf("div",null,u?yf("p",{className:"panel-eyebrow"},u):null,yf("h2",null,f)),_?yf("div",{className:"panel-actions"},_):null),yf("div",{className:"panel-body"},y))}function $H({title:f,data:u,onOpen:_,testId:y}){return yf("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function Q2({title:f,text:u}){return yf("div",{className:"empty-state"},yf("strong",null,f),yf("span",null,u))}function jS(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function JS(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function FS(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function jH(f){return String(f).replace(/[^a-zA-Z0-9_-]/g,"_")}function QS(f){if(!Number.isFinite(f))return"--";return`${f.toFixed(1)}%`}function K$(f,u){return`${f}/microservices/todo-note/proxy${u}`}function JH(f){return f.reduce((u,_)=>{let y=JH(Array.isArray(_.children)?_.children:[]),$=Boolean(_.completed);return{total:u.total+1+y.total,completed:u.completed+($?1:0)+y.completed,active:u.active+($?0:1)+y.active}},{total:0,completed:0,active:0})}function A2(f,u){let _=u==="all"||(u==="completed"?Boolean(f.completed):!f.completed),y=Array.isArray(f.children)?f.children:[];return _||y.some(($)=>A2($,u))}function AS(f){if(!f)return"";let u=new Date(f);if(Number.isNaN(u.getTime()))return"";return new Date(u.getTime()-u.getTimezoneOffset()*60000).toISOString().slice(0,16)}function US(f){if(!f)return null;let u=new Date(f);return Number.isNaN(u.getTime())?null:u.toISOString()}function lH(f){return Array.isArray(f?.instances)?f.instances:[]}function FH({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((I)=>I.id==="todo-note")||null,[$,l]=Du(null),[j,J]=Du(null),[F,A]=Du(""),[U,z]=Du(null),[W,K]=Du("all"),[q,E]=Du(13),[O,G]=Du(""),[H,Z]=Du(""),[V,L]=Du(""),[M,N]=Du(""),[D,x]=Du(""),[c,v]=Du(!1),[C,P]=Du(""),[w,r]=Du(null),S=lH(j),T=JH(Array.isArray(U?.todos)?U.todos:[]),Y=y?jS(y):{},R=y?FS(y):{},m=y?JS(y):{};async function p(I=F){let[$f,lf]=await Promise.all([wf(`${_}/microservices/todo-note/health`),wf(K$(_,"/api/instances"))]);l($f),J(lf);let Af=lH(lf),Yf=Af.some((xf)=>xf.id===I)?I:Af[0]?.id||"";return A(Yf),Yf}async function n(I=F){if(!I){z(null);return}let $f=await wf(K$(_,`/api/instances/${encodeURIComponent(I)}`));z($f)}async function _f(I=F){if(!y)return;v(!0),P("");try{let $f=await p(I);await n($f),r(new Date)}catch($f){P(Mf($f,"Todo Note 加载失败"))}finally{v(!1)}}async function t(I){if(!F)return;P("");try{let $f=await wf(K$(_,`/api/instances/${encodeURIComponent(F)}/actions`),{method:"POST",body:JSON.stringify({action:I})});z($f),await p(F)}catch($f){P(Mf($f,"Todo 操作失败"))}}async function ff(I){I.preventDefault();let $f=O.trim();if(!$f)return;v(!0),P("");try{let lf=await wf(K$(_,"/api/instances"),{method:"POST",body:JSON.stringify({name:$f})});G(""),await _f(lf.id)}catch(lf){P(Mf(lf,"创建清单失败"))}finally{v(!1)}}async function Gf(I){if(!window.confirm("确认删除这个 Todo Note 清单?"))return;v(!0),P("");try{await wf(K$(_,`/api/instances/${encodeURIComponent(I)}`),{method:"DELETE"}),await _f(F===I?"":F)}catch($f){P(Mf($f,"删除清单失败"))}finally{v(!1)}}async function zf(I){I.preventDefault();let $f=H.trim();if(!$f)return;Z(""),await t({type:"addTodo",title:$f})}async function jf(I){if(!F)return;P("");try{let $f=await wf(K$(_,`/api/instances/${encodeURIComponent(F)}/${I}`),{method:"POST",body:JSON.stringify({})});z($f),await p(F)}catch($f){P(Mf($f,`${I} 失败`))}}function Wf(I){L(I.id),N(String(I.title||""))}async function Vf(I){let $f=M.trim();if(L(""),N(""),$f)await t({type:"updateTodoTitle",todoId:I,title:$f})}async function Zf(I){let $f=window.prompt("新增子任务标题");if($f&&$f.trim())await t({type:"addTodo",title:$f.trim(),parentId:I})}async function h(I,$f){if(!D)return;let lf={type:"moveTodo",todoId:D,targetIndex:$f};if(I)lf.targetParentId=I;x(""),await t(lf)}if(yS(()=>{_f()},[y?.id,y?.runtime?.providerStatus]),!y)return yf(Q2,{title:"Todo Note 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=todo-note"});let g=S.find((I)=>I.id===F)||null;return yf("div",{className:"todo-note-page","data-testid":"todo-note-page"},yf(FQ,{title:"Todo Note 工作台",eyebrow:"Main Server 用户服务",actions:yf("div",{className:"panel-actions"},yf("button",{type:"button",className:"ghost-btn",disabled:c,onClick:()=>_f(F),"data-testid":"todo-note-refresh-button"},c?"刷新中":"刷新"),yf($H,{title:"Todo Note 用户服务",data:y,onOpen:u,testId:"raw-todo-note-service"}))},yf("div",{className:"todo-note-hero"},yf("div",null,yf("div",{className:"node-version-line"},yf(lS,{status:Y.providerStatus==="online"?"online":"warn"},Y.providerStatus||"unknown"),yf("span",null,y.providerId),yf("span",null,m.public?"公网暴露":"仅 UniDesk frontend 代理访问"),yf("span",null,$?.ok?"Health OK":"Health --")),yf("p",{className:"muted paragraph"},y.description)),yf("div",{className:"microservice-ref-card"},yf("span",null,"Repo"),yf("strong",null,R.url||"--"),yf("code",null,R.commitId||"--")),yf("div",{className:"microservice-ref-card"},yf("span",null,"Main Server Docker"),yf("strong",null,`${m.nodeBindHost||"--"}:${m.nodePort||"--"}`),yf("code",null,`${R.composeService||"--"} / ${R.containerName||"--"}`))),yf(H0,{error:C,wide:!0})),yf("div",{className:"todo-note-layout"},yf(FQ,{title:"清单",eyebrow:`${S.length} Instances`,className:"todo-list-panel"},yf("form",{className:"todo-create-list",onSubmit:ff},yf("input",{placeholder:"新清单名称",value:O,onChange:(I)=>G(I.target.value),"aria-label":"新清单名称"}),yf("button",{type:"submit",className:"ghost-btn",disabled:c||!O.trim()},"创建")),S.length===0?yf(Q2,{title:"暂无清单",text:"迁移或创建清单后会出现在这里"}):yf("div",{className:"todo-instance-list"},S.map((I)=>yf("button",{key:I.id,type:"button",className:`todo-instance-row ${F===I.id?"active":""}`,onClick:()=>{A(I.id),n(I.id)},"data-testid":`todo-instance-${jH(I.id)}`},yf("strong",null,I.name),yf("span",null,`${I.completedCount??0}/${I.todoCount??0} 完成`),yf("code",null,I.id))))),yf("div",{className:"todo-main-stack"},yf(FQ,{title:g?.name||"待选择清单",eyebrow:w?`Updated ${$S(w)}`:"Todo Tree",actions:U?yf("div",{className:"panel-actions"},yf("button",{type:"button",className:"ghost-btn",onClick:()=>t({type:"renameInstance",name:window.prompt("清单新名称",U.name)||U.name})},"重命名"),yf("button",{type:"button",className:"ghost-btn danger",onClick:()=>Gf(F)},"删除清单"),yf($H,{title:`Todo Instance ${F}`,data:U,onOpen:u,testId:"raw-todo-instance"})):null},!U?yf(Q2,{title:"未选择清单",text:"左侧选择一个 Todo Note 清单"}):yf("div",{className:"todo-workbench",style:{"--todo-font-size":`${q}px`}},yf("div",{className:"todo-toolbar"},yf("form",{className:"todo-add-form",onSubmit:zf},yf("input",{placeholder:"新增根任务",value:H,onChange:(I)=>Z(I.target.value),"aria-label":"新增根任务"}),yf("button",{type:"submit",className:"ghost-btn",disabled:!H.trim()},"新增")),yf("div",{className:"todo-filter-strip"},["all","active","completed"].map((I)=>yf("button",{key:I,type:"button",className:`todo-filter ${W===I?"active":""}`,onClick:()=>K(I)},I==="all"?"全部":I==="active"?"未完成":"已完成"))),yf("div",{className:"todo-toolbar-actions"},yf("button",{type:"button",className:"ghost-btn",onClick:()=>t({type:"setAllTodosExpanded",expanded:!0})},"全部展开"),yf("button",{type:"button",className:"ghost-btn",onClick:()=>t({type:"setAllTodosExpanded",expanded:!1})},"全部收起"),yf("button",{type:"button",className:"ghost-btn",onClick:()=>jf("undo")},"撤销"),yf("button",{type:"button",className:"ghost-btn",onClick:()=>jf("redo")},"重做"),yf("label",{className:"todo-font-control"},"字号",yf("input",{type:"range",min:11,max:18,value:q,onChange:(I)=>E(Number(I.target.value))})))),yf("div",{className:"todo-stats-grid"},yf(F2,{label:"总任务",value:T.total,hint:`${S.length} lists`}),yf(F2,{label:"已完成",value:T.completed,hint:`${QS(T.total?T.completed/T.total*100:0)}`,tone:"ok"}),yf(F2,{label:"未完成",value:T.active,hint:W==="active"?"当前筛选":"active tasks",tone:T.active>0?"warn":"ok"}),yf(F2,{label:"历史指针",value:U.historyPointer??0,hint:"undo / redo"})),yf("div",{className:"todo-root-drop",onDragOver:(I)=>I.preventDefault(),onDrop:(I)=>{I.preventDefault(),h(null,(U.todos||[]).length)}},"拖到这里可移为根任务末尾"),yf("div",{className:"todo-tree","data-testid":"todo-note-tree"},(U.todos||[]).filter((I)=>A2(I,W)).length===0?yf(Q2,{title:"没有匹配任务",text:"调整筛选或新增任务"}):(U.todos||[]).filter((I)=>A2(I,W)).map((I,$f)=>yf(QH,{key:I.id,todo:I,depth:0,parentId:null,index:$f,siblingCount:U.todos.length,filter:W,editingId:V,editingTitle:M,setEditingTitle:N,beginEdit:Wf,saveEdit:Vf,applyTodoAction:t,addChild:Zf,dragTodoId:D,setDragTodoId:x,dropTodo:h}))))))))}function QH(f){let{todo:u,depth:_,parentId:y,index:$,siblingCount:l,filter:j,editingId:J,editingTitle:F,setEditingTitle:A,beginEdit:U,saveEdit:z,applyTodoAction:W,addChild:K,dragTodoId:q,setDragTodoId:E,dropTodo:O}=f,G=Array.isArray(u.children)?u.children:[],H=G.filter((L)=>A2(L,j)),Z=J===u.id,V=y||null;return yf("div",{className:"todo-row-wrap"},yf("article",{className:`todo-row ${u.completed?"completed":""} ${q===u.id?"dragging":""}`,style:{"--todo-depth":_},draggable:!0,onDragStart:(L)=>{E(u.id),L.dataTransfer.effectAllowed="move"},onDragOver:(L)=>L.preventDefault(),onDrop:(L)=>{L.preventDefault(),O(u.id,G.length)},"data-testid":`todo-row-${jH(u.id)}`},yf("button",{type:"button",className:"todo-expand",disabled:G.length===0,onClick:()=>W({type:"toggleTodoExpanded",todoId:u.id})},G.length===0?"·":u.expanded?"▾":"▸"),yf("input",{type:"checkbox",checked:Boolean(u.completed),onChange:()=>W({type:"toggleTodoCompleted",todoId:u.id}),"aria-label":`完成 ${u.title}`}),yf("div",{className:"todo-title-cell",onDoubleClick:()=>U(u)},Z?yf("div",{className:"todo-edit-inline"},yf("input",{value:F,autoFocus:!0,onChange:(L)=>A(L.target.value),onKeyDown:(L)=>{if(L.key==="Enter")z(u.id);if(L.key==="Escape")U({id:"",title:""})}}),yf("button",{type:"button",className:"ghost-btn",onClick:()=>z(u.id)},"保存")):yf("strong",null,u.title||"Untitled"),yf("div",{className:"todo-meta-line"},yf("span",null,`子项 ${G.length}`),yf("span",null,`更新 ${yH(u.updatedAt)}`),u.reminderAt?yf("span",{className:"todo-reminder"},`提醒 ${yH(u.reminderAt)}`):yf("span",null,"无提醒"))),yf("input",{className:"todo-reminder-input",type:"datetime-local",value:AS(u.reminderAt),onChange:(L)=>W({type:"setTodoReminder",todoId:u.id,reminderAt:US(L.target.value)})}),yf("div",{className:"todo-row-actions"},yf("button",{type:"button",className:"ghost-btn",onClick:()=>U(u)},"编辑"),yf("button",{type:"button",className:"ghost-btn",onClick:()=>K(u.id)},"子项"),yf("button",{type:"button",className:"ghost-btn",disabled:$<=0,onClick:()=>W({type:"moveTodo",todoId:u.id,...V?{targetParentId:V}:{},targetIndex:$-1})},"上移"),yf("button",{type:"button",className:"ghost-btn",disabled:$>=l-1,onClick:()=>W({type:"moveTodo",todoId:u.id,...V?{targetParentId:V}:{},targetIndex:$+1})},"下移"),yf("button",{type:"button",className:"ghost-btn",disabled:!y,onClick:()=>W({type:"moveTodo",todoId:u.id,targetIndex:9999})},"提升"),yf("button",{type:"button",className:"ghost-btn danger",onClick:()=>W({type:"deleteTodo",todoId:u.id})},"删除"))),u.expanded&&H.length>0?yf("div",{className:"todo-children"},H.map((L,M)=>yf(QH,{key:L.id,todo:L,depth:_+1,parentId:u.id,index:M,siblingCount:G.length,filter:j,editingId:J,editingTitle:F,setEditingTitle:A,beginEdit:U,saveEdit:z,applyTodoAction:W,addChild:K,dragTodoId:q,setDragTodoId:E,dropTodo:O}))):null)}var AH=rf(I0(),1),yy=AH.default.createElement;function UH({title:f,items:u,actions:_,className:y,testId:$}){let l=Array.isArray(u)?u:[];return yy("section",{className:`top-status-bar ${y||""}`,"data-testid":$},yy("div",{className:"top-status-main"},f?yy("strong",{className:"top-status-title"},f):null,yy("div",{className:"top-status-chips"},l.map((j,J)=>yy("span",{key:j?.key||`${j?.label||"status"}-${J}`,className:`top-status-chip ${j?.tone||""}`,"data-testid":j?.testId},j?.label?yy("b",null,j.label):null,yy("span",null,j?.value??"--"))))),_?yy("div",{className:"top-status-actions"},_):null)}function XH(f,u){let _=document.getElementById("root")?.getAttribute(f);if(!_)return u;try{let y=JSON.parse(_);return typeof y==="object"&&y!==null&&!Array.isArray(y)?y:u}catch{return u}}var tf=XH("data-config",{apiBaseUrl:"/api",authUsername:"admin"}),WS=XH("data-codex-overview",null),Q=Pl.default.createElement,{useEffect:p1,useMemo:Cl}=Pl.default,hf=Pl.default.useState,mu=FG(c4),zS={id:"codex-queue",name:"Codex Queue",providerId:"main-server",description:"Codex Queue",repository:{containerName:"codex-queue-backend"},backend:{nodeBaseUrl:"http://codex-queue:4222",nodeBindHost:"codex-queue",nodePort:4222,public:!1},runtime:{providerStatus:"loading",providerName:"main-server"}};function WH(){return typeof document>"u"||document.visibilityState!=="hidden"}function GS(f,u){if(f==="ops"&&u==="status")return 5000;if(f==="nodes"&&u==="monitor")return 5000;if(f==="tasks"&&(u==="dispatch"||u==="pending"))return 5000;if(f==="nodes"||f==="ops")return 1e4;if(f==="apps")return 15000;if(f==="tasks")return 15000;return 30000}async function KS(f){if(!f?._summaryOnly||!f?.id)return f;return(await wf(`${tf.apiBaseUrl}/tasks/${encodeURIComponent(String(f.id))}`))?.task||f}function Rl(f){return f?._summaryOnly?{...f,_loadRaw:()=>KS(f)}:f}function m0(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return u.toLocaleString("zh-CN",{hour12:!1})}function W2(f){return f.toLocaleTimeString("zh-CN",{hour12:!1})}function H$(f){if(!Number.isFinite(f))return"--";let u=Math.max(0,f);if(u===0)return"0s";if(u<0.01)return"<0.01s";if(u<0.1)return`${u.toFixed(2)}s`;if(u<1)return`${u.toFixed(1)}s`;if(u<10&&!Number.isInteger(u))return`${u.toFixed(1)}s`;if(u<60)return`${Math.round(u)}s`;let _=Math.floor(u);if(_<3600)return`${Math.floor(_/60)}m ${_%60}s`;return`${Math.floor(_/3600)}h ${Math.floor(_%3600/60)}m`}function pu(f){let u=Number(f);if(!Number.isFinite(u))return"--";if(u<1)return`${Math.max(0,u).toFixed(1)}ms`;if(u<10)return`${u.toFixed(1)}ms`;if(u<1000)return`${Math.round(u)}ms`;return H$(u/1000)}function Ju(f){let u=Number(f);if(!Number.isFinite(u)||u<=0)return"--";let _=["B","KB","MB","GB","TB"],y=u,$=0;while(y>=1024&&$<_.length-1)y/=1024,$+=1;return`${y.toFixed($===0?0:1)} ${_[$]}`}function $y(f){let u=Number(f);return Number.isFinite(u)?`${Math.max(0,Math.min(100,u)).toFixed(1)}%`:"--"}function ZS(f){let u=Number(f);return Number.isFinite(u)?`${Math.max(0,u).toFixed(1)}%`:"--"}function QQ(f){let u=Number(f);if(!Number.isFinite(u)||u<=0)return"0 B/s";return`${Ju(u)}/s`}function Tf(f,u=0){let _=Number(f);return Number.isFinite(_)?_:u}function E$(f){return["queued","dispatched","running"].includes(String(f?.status||"").toLowerCase())}function WQ(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return H$(Math.max(0,Math.floor((Date.now()-u.getTime())/1000)))}function Z$(f){if(!f)return null;let u=new Date(f);return Number.isNaN(u.getTime())?null:u.getTime()}function NH(f){let u=Z$(f?.createdAt);if(u===null)return null;let y=["succeeded","failed"].includes(String(f?.status||"").toLowerCase())?Z$(f?.updatedAt):Date.now();if(y===null)return null;return Math.max(0,(y-u)/1000)}function LH(f){if(String(f?.status||"").toLowerCase()!=="failed")return"";let u=f?.result;if(typeof u==="string")return u;if(u&&typeof u==="object"&&!Array.isArray(u)){let _=u;for(let y of["error","reason","message","stderr","detail"])if(typeof _[y]==="string"&&_[y].length>0)return _[y]}return"任务失败但 provider 未返回明确原因"}function dy(f){if(f===null||f===void 0)return"--";if(typeof f==="boolean")return f?"是":"否";if(typeof f==="number")return String(f);if(typeof f==="string")return f.length>80?`${f.slice(0,77)}...`:f;if(Array.isArray(f))return`${f.length} 项`;if(typeof f==="object")return`${Object.keys(f).length} 字段`;return String(f)}function qS(f,u){if(f==="bodyText"&&typeof u==="string")return`${/^\s*[{[]/.test(u)?"JSON":"HTTP"} body ${u.length} chars`;return dy(u)}function YH(f){if(!f||typeof f!=="object"||Array.isArray(f))return[];return Object.entries(f)}function N1(f){return String(f).replace(/[^a-zA-Z0-9_-]/g,"_")}function zQ(f,u){return f&&typeof f==="object"&&!Array.isArray(f)?f[u]:void 0}function G2(f,u,_="未知"){let y=zQ(f?.labels,u);return typeof y==="string"&&y.length>0?y:_}function BH(f){return G2(f,"providerGatewayVersion")}function rl(f){return G2(f,"providerGatewayUpgradePolicy")}function zH(f){return G2(f,"providerGatewayStartedAt","")}function wH(f){let u=zQ(f?.labels,"unideskCapabilities");if(typeof u==="string")return u.split(",").map((_)=>_.trim()).filter(Boolean);return Array.isArray(u)?u.filter((_)=>typeof _==="string"):[]}function DH(f,u){return wH(f).includes(u)}function GH(f,u){let _=zQ(f?.labels,u);return _===!0||_==="true"||_==="1"}function HS(f){if(!DH(f,"host.ssh"))return{tone:"fail",label:"不可用",detail:"未声明 host.ssh"};if(!GH(f,"hostSshConfigured"))return{tone:"warn",label:"未配置",detail:"缺少 SSH 环境变量"};if(!GH(f,"hostSshKeyPresent"))return{tone:"warn",label:"缺 key",detail:"私钥未挂载"};return{tone:"ok",label:"可用",detail:G2(f,"hostSshTarget","host.ssh ready")}}function ES(f){if(!DH(f,"provider.upgrade"))return{tone:"fail",label:"不可用",detail:"未声明 provider.upgrade"};let u=rl(f);if(u!=="always-enabled")return{tone:"warn",label:"待确认",detail:`策略 ${u}`};return{tone:"ok",label:"可用",detail:"always-enabled"}}function GQ(f){let u=typeof f==="string"&&f.length>0?f:"未知";if(u==="未知")return"版本未知";return u.startsWith("v")?u:`v${u}`}function TH(f){return f?.payload&&typeof f.payload==="object"&&!Array.isArray(f.payload)?f.payload:{}}function K2(f){return f?.result&&typeof f.result==="object"&&!Array.isArray(f.result)?f.result:{}}function z2(f){let u=TH(f),_=K2(f);return(u.mode??_.mode)==="schedule"?"schedule":"plan"}function VS(f){let u=TH(f).source;return typeof u==="string"&&u.length>0?u:"unknown"}function OS(f){let u=K2(f),_=u.plan&&typeof u.plan==="object"&&!Array.isArray(u.plan)?u.plan:{},y=u.policy??_.policy;return typeof y==="string"&&y.length>0?y:"--"}function MH(f){let u=K2(f),_=u.plan&&typeof u.plan==="object"&&!Array.isArray(u.plan)?u.plan:{},y=u.targetProviderGatewayVersion??u.providerGatewayVersion??_.targetProviderGatewayVersion??_.providerGatewayVersion;return typeof y==="string"&&y.length>0?GQ(y):"版本未知"}function SH(f){if(String(f?.status||"").toLowerCase()==="failed")return LH(f);if(E$(f))return"等待 provider 回传升级终态";let _=K2(f);if(typeof _.updaterContainerId==="string"&&_.updaterContainerId.length>0)return`updater ${_.updaterContainerId.slice(0,18)}`;if(typeof _.message==="string"&&_.message.length>0)return _.message;if(_.plan)return"升级计划已生成";return"无升级结果摘要"}function rH(f,u){return f.filter((_)=>_?.providerId===u&&_?.command==="provider.upgrade").sort((_,y)=>(Z$(y.updatedAt)??0)-(Z$(_.updatedAt)??0))}function XS(f){return f.find((u)=>z2(u)==="schedule")||f[0]||null}function PH(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function KH(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function NS(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function V0({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return Q("span",{className:`status-badge ${_}`},u||f||"unknown")}function f0({label:f,value:u,hint:_,tone:y,onClick:$,testId:l}){let j=typeof $==="function";return Q("article",{className:`metric-card ${y||""} ${j?"clickable":""}`,role:j?"button":void 0,tabIndex:j?0:void 0,"data-testid":l,onClick:$,onKeyDown:j?(J)=>{if(J.key==="Enter"||J.key===" ")J.preventDefault(),$()}:void 0},Q("div",{className:"metric-label"},f),Q("div",{className:"metric-value"},u),Q("div",{className:"metric-hint"},_))}function kf({title:f,eyebrow:u,actions:_,children:y,className:$}){return Q("section",{className:`panel ${$||""}`},Q("div",{className:"panel-head"},Q("div",null,u?Q("p",{className:"panel-eyebrow"},u):null,Q("h2",null,f)),_?Q("div",{className:"panel-actions"},_):null),Q("div",{className:"panel-body"},y))}function k0({title:f,data:u,onOpen:_,testId:y}){let[$,l]=hf(!1),j=u&&typeof u==="object"&&typeof u._loadRaw==="function"?u._loadRaw:null;async function J(){if(!j){_(f,u);return}l(!0);try{_(f,await j())}catch(F){_(f,{ok:!1,error:Mf(F,"读取原始 JSON 失败"),fallback:u})}finally{l(!1)}}return Q("button",{type:"button",className:"ghost-btn","data-testid":y,disabled:$,onClick:()=>void J()},$?"读取中":"查看原始JSON")}function LS({raw:f,onClose:u}){if(!f)return null;return Q("div",{className:"modal-backdrop",role:"presentation"},Q("section",{className:"raw-dialog",role:"dialog","aria-modal":"true","aria-label":f.title},Q("div",{className:"raw-dialog-head"},Q("h2",null,f.title),Q("button",{type:"button",className:"ghost-btn",onClick:u},"关闭")),Q("pre",{className:"raw-json","data-testid":"raw-json"},JSON.stringify(f.data,null,2))))}function CH({labels:f,limit:u=8}){let _=YH(f).slice(0,u);if(_.length===0)return Q("span",{className:"muted"},"无标签");return Q("div",{className:"chip-row"},_.map(([y,$])=>Q("span",{key:y,className:"data-chip"},Q("b",null,y),Q("span",null,dy($)))))}function q$({node:f}){let u=BH(f);return Q("span",{className:`version-chip ${u==="未知"?"unknown":""}`,"data-testid":`gateway-version-${N1(f?.providerId||"unknown")}`},GQ(u))}function ZH({title:f,state:u,testId:_}){return Q("span",{className:`capability-badge ${u.tone}`,title:u.detail,"data-testid":_},Q("b",null,f),Q("strong",null,u.label),Q("small",null,u.detail))}function KQ({node:f}){let u=N1(f?.providerId||"unknown");return Q("div",{className:"node-availability-strip"},Q(ZH,{title:"SSH 透传",state:HS(f),testId:`ssh-availability-${u}`}),Q(ZH,{title:"远程更新",state:ES(f),testId:`upgrade-availability-${u}`}))}function ey({data:f,empty:u="无数据"}){if(f===null||f===void 0)return Q("span",{className:"muted"},u);if(typeof f!=="object")return Q("span",{className:"summary-value"},dy(f));if(Array.isArray(f))return Q("span",{className:"summary-value"},`${f.length} 项列表`);let _=Object.entries(f).slice(0,5);if(_.length===0)return Q("span",{className:"muted"},u);return Q("div",{className:"summary-grid"},_.map(([y,$])=>Q("span",{key:y,className:"summary-item"},Q("b",null,y),Q("span",null,qS(y,$)))))}function l0({title:f,text:u}){return Q("div",{className:"empty-state"},Q("strong",null,f),Q("span",null,u))}function YS({onLogin:f}){let[u,_]=hf(tf.authUsername||"admin"),[y,$]=hf(""),[l,j]=hf(""),[J,F]=hf(!1);async function A(U){U.preventDefault(),F(!0),j("");try{let z=await wf("/login",{method:"POST",body:JSON.stringify({username:u,password:y})});f(z)}catch(z){j(Mf(z,"登录失败"))}finally{F(!1)}}return Q("main",{className:"login-screen","data-testid":"login-screen"},Q("section",{className:"login-card"},Q("div",{className:"login-brand"},Q("span",{className:"brand-mark"},"UD"),Q("div",null,Q("h1",null,"UniDesk"),Q("p",null,"Control Plane Login"))),Q("form",{className:"login-form",onSubmit:A},Q("label",null,"账号",Q("input",{name:"username",autoComplete:"username",value:u,onChange:(U)=>_(U.target.value)})),Q("label",null,"密码",Q("input",{name:"password",type:"password",autoComplete:"current-password",value:y,onChange:(U)=>$(U.target.value)})),Q(H0,{error:l}),Q("button",{type:"submit",disabled:J},J?"登录中":"登录")),Q("div",{className:"login-note"},"默认账号由 config.json 注入;公网入口只暴露前端登录面。")))}function BS({connection:f,lastRefresh:u,onRefresh:_,onLogout:y,session:$,clock:l,activeStatusItems:j=[]}){let J=[{key:"core",label:"核心",value:f.text,tone:f.ok?"ok":"fail",testId:"conn-text"},...Array.isArray(j)?j:[],{key:"refresh",label:"刷新",value:u?W2(u):"未刷新"},{key:"clock",label:"时间",value:W2(l)},{key:"user",label:"用户",value:$?.user?.username||"--",tone:"user"}];return Q("header",{className:"topbar"},Q("div",null,Q("p",{className:"eyebrow"},"Distributed Work Platform"),Q("h1",null,"UniDesk 控制平面")),Q(UH,{className:"global-top-status",title:"状态",items:J,actions:[Q("button",{key:"refresh",type:"button",className:"ghost-btn",onClick:_},"刷新"),Q("button",{key:"logout",type:"button",className:"ghost-btn danger",onClick:y},"退出")]}))}function wS({activeModule:f,activeTabs:u,onNavigate:_,collapsed:y,onToggle:$}){return Q("aside",{className:`rail ${y?"collapsed":""}`,"aria-label":"主模块"},Q("div",{className:"brand"},Q("span",{className:"brand-mark"},"UD"),Q("span",{className:"brand-text"},"UniDesk"),Q("button",{type:"button",className:"rail-toggle",onClick:$,"aria-label":y?"展开左侧边栏":"收起左侧边栏","data-testid":"rail-toggle"},y?"»":"«")),c4.map((l)=>Q("button",{key:l.id,type:"button",className:`module ${f===l.id?"active":""}`,onClick:()=>_(l.id,u[l.id]||m3[l.id]||l.tabs[0]?.id||""),title:l.label,"data-route":c6(mu,l.id,u[l.id]||m3[l.id]||l.tabs[0]?.id||"")},Q("span",{className:"module-code"},l.code),Q("span",null,l.label))))}function DS({module:f,activeTab:u,onNavigate:_}){return Q("nav",{className:"tabs","aria-label":`${f.label} 子功能`},f.tabs.map((y)=>Q("button",{key:y.id,type:"button",className:`tab ${u===y.id?"active":""}`,onClick:()=>_(f.id,y.id),"data-route":c6(mu,f.id,y.id)},y.label)))}function TS({data:f,onRaw:u,onNavigate:_}){let y=f.overview||{},$=f.nodes.filter((A)=>A.status==="online"),l=f.pendingTasks||f.tasks.filter(E$),j=y.pendingTaskCount??l.length,J=f.tasks.slice(0,5),F=y.pgdata||{};return Q("div",{className:"page-grid overview-grid","data-testid":"overview-page"},Q(kf,{title:"核心指标",eyebrow:"Control"},Q("div",{className:"metric-grid"},Q(f0,{label:"数据库",value:y.dbReady?"READY":"WAIT",hint:"PostgreSQL internal network",tone:y.dbReady?"ok":"warn"}),Q(f0,{label:"PGDATA",value:Ju(F.databaseBytes),hint:`${F.volumeName||"unidesk_pgdata_10gb"} / ${F.databasePretty||"--"}`,tone:"ok",testId:"pgdata-usage-card"}),Q(f0,{label:"在线节点",value:y.onlineNodeCount??0,hint:`${y.nodeCount??0} registered`,tone:"ok"}),Q(f0,{label:"WebSocket",value:y.activeSocketCount??0,hint:"Provider ingress sockets"}),Q(f0,{label:"待处理任务",value:j,hint:j>0?"点击查看具体任务":`timeout ${H$(Math.floor((y.taskPendingTimeoutMs??0)/1000))}`,tone:j>0?"warn":"ok",onClick:()=>_("tasks","pending"),testId:"pending-task-card"}))),Q(kf,{title:"本机 Provider",eyebrow:"Self Connected"},$.length===0?Q(l0,{title:"暂无在线节点",text:"provider-gateway 未完成自接入"}):Q("div",{className:"node-card-list"},$.slice(0,4).map((A)=>Q(MS,{key:A.providerId,node:A,onRaw:u})))),Q(kf,{title:"待处理任务明细",eyebrow:`${j} Pending`,actions:Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("tasks","pending"),"data-testid":"pending-task-detail-link"},"进入任务调度")},l.length===0?Q(l0,{title:"当前无待处理",text:"queued / dispatched / running 超时后会自动转为 failed,避免总览长期卡住"}):Q("div",{className:"compact-list"},l.slice(0,5).map((A)=>Q(VH,{key:A.id,task:A,onRaw:u})))),Q(kf,{title:"最近任务",eyebrow:"Dispatch"},J.length===0?Q(l0,{title:"暂无任务",text:"可以在任务调度模块发起 docker.ps 或 echo"}):Q("div",{className:"compact-list"},J.map((A)=>Q(VH,{key:A.id,task:A,onRaw:u})))))}function MS({node:f,onRaw:u}){return Q("article",{className:"node-card"},Q("div",{className:"node-card-head"},Q("div",null,Q("strong",null,f.name),Q("code",null,f.providerId)),Q(V0,{status:f.status})),Q("div",{className:"node-version-line"},Q(q$,{node:f}),Q("span",null,`升级策略 ${rl(f)}`)),Q(KQ,{node:f}),Q(CH,{labels:f.labels,limit:6}),Q("div",{className:"node-card-foot"},Q("span",null,`心跳 ${m0(f.lastHeartbeat)}`),Q(k0,{title:`Provider ${f.providerId}`,data:f,onOpen:u,testId:`raw-node-${N1(f.providerId)}`})))}function SS({events:f,onRaw:u}){return Q(kf,{title:"事件摘要",eyebrow:"Latest 100"},f.length===0?Q(l0,{title:"暂无事件",text:"Provider 注册、心跳超时和任务状态会写入事件流"}):Q("div",{className:"table-wrap"},Q("table",null,Q("thead",null,Q("tr",null,Q("th",null,"ID"),Q("th",null,"类型"),Q("th",null,"来源"),Q("th",null,"摘要"),Q("th",null,"时间"),Q("th",null,"操作"))),Q("tbody",null,f.map((_)=>Q("tr",{key:_.id},Q("td",null,Q("code",null,_.id)),Q("td",null,Q(V0,{status:_.type},_.type)),Q("td",null,Q("code",null,_.source)),Q("td",null,Q(ey,{data:_.payload})),Q("td",null,m0(_.createdAt)),Q("td",null,Q(k0,{title:`Event ${_.id}`,data:_,onOpen:u}))))))))}function rS({logs:f,onRaw:u}){return Q(kf,{title:"服务日志",eyebrow:"Core Recent"},f.length===0?Q(l0,{title:"暂无日志",text:"backend-core 内存日志会在请求和 provider 事件后出现"}):Q("div",{className:"log-list"},f.slice(-80).reverse().map((_,y)=>Q("article",{key:y,className:`log-row ${_.level||"info"}`},Q("span",null,m0(_.ts)),Q("b",null,_.level||"info"),Q("strong",null,_.message||"log"),Q(ey,{data:_.data,empty:"无附加字段"}),Q(k0,{title:`Log ${_.message||y}`,data:_,onOpen:u})))))}function PS({nodes:f,onRaw:u}){return Q(kf,{title:"节点清单",eyebrow:`${f.length} Providers`},f.length===0?Q(l0,{title:"暂无 Provider 节点",text:"确认 provider-gateway 已连接 provider ingress"}):Q("div",{className:"table-wrap"},Q("table",{className:"node-list-table"},Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"Provider"),Q("th",null,"网关版本"),Q("th",null,"运维可用性"),Q("th",null,"资源标签"),Q("th",null,"连接时间"),Q("th",null,"最后心跳"),Q("th",null,"操作"))),Q("tbody",null,f.map((_)=>Q("tr",{key:_.providerId},Q("td",null,Q(V0,{status:_.status})),Q("td",null,Q("strong",null,_.name),Q("code",null,_.providerId)),Q("td",null,Q("div",{className:"gateway-cell"},Q(q$,{node:_}),Q("span",null,rl(_)))),Q("td",null,Q(KQ,{node:_})),Q("td",null,Q(CH,{labels:_.labels,limit:5})),Q("td",null,m0(_.connectedAt)),Q("td",null,m0(_.lastHeartbeat)),Q("td",null,Q(k0,{title:`Provider ${_.providerId}`,data:_,onOpen:u,testId:`raw-node-table-${N1(_.providerId)}`}))))))))}function CS({nodes:f}){let u=Cl(()=>{let _=[];for(let y of f)for(let[$,l]of YH(y.labels))_.push({providerId:y.providerId,name:y.name,key:$,value:l});return _},[f]);return Q(kf,{title:"资源标签",eyebrow:"Structured Labels"},u.length===0?Q(l0,{title:"暂无标签",text:"provider-gateway 注册消息会同步资源标签"}):Q("div",{className:"label-matrix"},u.map((_)=>Q("article",{key:`${_.providerId}-${_.key}`,className:"label-card"},Q("span",null,_.key),Q("strong",null,dy(_.value)),Q("code",null,_.providerId)))))}function RS({nodes:f}){return Q(kf,{title:"心跳状态",eyebrow:"Provider Liveness"},f.length===0?Q(l0,{title:"无心跳",text:"等待 provider 注册和 heartbeat"}):Q("div",{className:"heartbeat-list"},f.map((u)=>Q("article",{key:u.providerId,className:"heartbeat-row"},Q("span",{className:`pulse ${u.status}`}),Q("div",null,Q("strong",null,u.name),Q("code",null,u.providerId)),Q("div",null,Q("span",null,"connected"),Q("b",null,m0(u.connectedAt))),Q("div",null,Q("span",null,"last heartbeat"),Q("b",null,m0(u.lastHeartbeat)))))))}function xS({nodes:f,systemStatuses:u,tasks:_,onRaw:y,refresh:$}){let[l,j]=hf(""),J=Cl(()=>f.map((E)=>{let O=u.find((G)=>G.providerId===E.providerId);return{...E,systemCurrent:O?.current||null,systemHistory:O?.history||[],systemUpdatedAt:O?.updatedAt||null}}),[f,u]),F=J.find((E)=>E.providerId===l)||J[0]||null;if(p1(()=>{if(!l&&J[0])j(J[0].providerId)},[J.length,l]),!F)return Q(l0,{title:"暂无资源监控",text:"等待 provider 上报 CPU、内存和硬盘指标"});let A=F.systemCurrent,U=F.systemHistory||[],z=A?.cpu||{},W=A?.memory||{},K=A?.disk||{},q=U.length>0?U:A?[{at:A.collectedAt,cpuPercent:Tf(z.percent),memoryPercent:Tf(W.percent),diskPercent:Tf(K.percent)}]:[];return Q("div",{className:"monitor-page","data-testid":"node-monitor-page"},Q("div",{className:"docker-node-strip"},J.map((E)=>Q("button",{key:E.providerId,type:"button",className:`docker-node-tile ${F.providerId===E.providerId?"active":""}`,onClick:()=>j(E.providerId)},Q("span",{className:`pulse ${E.status}`}),Q("strong",null,E.name),Q("code",null,E.providerId),Q("span",null,E.systemCurrent?`CPU ${$y(E.systemCurrent.cpu?.percent)} / MEM ${$y(E.systemCurrent.memory?.percent)}`:"等待指标")))),Q("div",{className:"monitor-layout"},Q(kf,{title:"任务管理器视图",eyebrow:F.name,className:"monitor-main-panel",actions:A?Q(k0,{title:`System ${F.providerId}`,data:{current:A,history:U},onOpen:y}):null},!A?Q(l0,{title:"系统指标未上报",text:"provider-gateway 会周期性采集 /proc 与 df,并保存历史曲线"}):Q("div",null,Q("div",{className:"monitor-hero"},Q("div",null,Q("p",{className:"panel-eyebrow"},"Node Performance"),Q("h3",null,F.name),Q("div",{className:"docker-meta"},Q("span",null,`${z.cores||0} CPU cores`),Q("span",null,`load ${Tf(z.load1).toFixed(2)} / ${Tf(z.load5).toFixed(2)} / ${Tf(z.load15).toFixed(2)}`),Q("span",null,`memory actual ${Ju(W.usedBytes)} / ${Ju(W.totalBytes)}`),Q("span",null,`disk ${Ju(K.usedBytes)} / ${Ju(K.totalBytes)}`))),Q(V0,{status:A.ok?"online":"warn"},A.ok?"METRICS READY":"METRICS DEGRADED")),Q("div",{className:"monitor-chart-grid"},Q(AQ,{title:"CPU",metricKey:"cpuPercent",current:z.percent,points:q,detail:`${z.cores||0} cores / load ${Tf(z.load1).toFixed(2)}`,tone:"cpu",testId:"metric-chart-cpu"}),Q(AQ,{title:"Memory",metricKey:"memoryPercent",current:W.percent,points:q,detail:`${Ju(W.usedBytes)} actual / ${Ju(W.cacheBytes)} cache excluded`,tone:"memory",testId:"metric-chart-memory"}),Q(AQ,{title:"Disk",metricKey:"diskPercent",current:K.percent,points:q,detail:`${K.path||"/"} mounted ${K.mount||"--"}`,tone:"disk",testId:"metric-chart-disk"})),Q("div",{className:"monitor-summary-grid"},Q(f0,{label:"CPU 当前",value:$y(z.percent),hint:`history ${q.length} samples`,tone:"ok"}),Q(f0,{label:"实际内存",value:Ju(W.usedBytes),hint:`${$y(W.percent)} 不含缓存`}),Q(f0,{label:"硬盘已用",value:Ju(K.usedBytes),hint:$y(K.percent)}),Q(f0,{label:"更新时间",value:m0(F.systemUpdatedAt||A.collectedAt),hint:F.providerId})),Q(vS,{current:A,onRaw:y}))),Q("div",{className:"monitor-side-stack"},Q(iS,{provider:F,refresh:$,onRaw:y}),Q(gS,{provider:F,tasks:_,onRaw:y,limit:5}),Q(kf,{title:"采样说明",eyebrow:"Retention"},Q("div",{className:"monitor-note-list"},Q("article",null,Q("b",null,"CPU"),Q("span",null,"从 /proc/stat 计算相邻采样差值,首个采样用 load/cores 近似")),Q("article",null,Q("b",null,"Memory"),Q("span",null,"实际内存 = MemTotal - MemFree - Buffers - Cached - SReclaimable + Shmem,不把 page cache / buffer 计入占用")),Q("article",null,Q("b",null,"Disk"),Q("span",null,"使用 df -PB1 对配置路径采样,默认监控根文件系统")),Q("article",null,Q("b",null,"Process"),Q("span",null,"从 /proc/[pid] 采集进程 CPU、实际内存 RSS、线程数和磁盘 I/O 速率;表格默认按内存占用降序")))))))}function qH(f,u){if(u==="memory")return Tf(f.rssBytes);if(u==="cpu")return Tf(f.cpuPercent);if(u==="disk")return Tf(f.readBytesPerSecond)+Tf(f.writeBytesPerSecond);if(u==="pid")return Tf(f.pid);if(u==="threads")return Tf(f.threads);if(u==="runtime")return Tf(f.elapsedSeconds);if(u==="user")return String(f.user||"");return String(f.name||f.command||"")}function HH({value:f,label:u,tone:_}){let y=Math.max(1,Math.min(100,Tf(f)));return Q("div",{className:`process-meter ${_||""}`},Q("span",{style:{width:`${y}%`}}),Q("b",null,u))}function vS({current:f,onRaw:u}){let[_,y]=hf({key:"memory",direction:"desc"}),$=f?.processSummary&&typeof f.processSummary==="object"?f.processSummary:{},l=Array.isArray(f?.processes)?f.processes:[],j=Cl(()=>{let F=_.direction==="asc"?1:-1;return[...l].sort((A,U)=>{let z=qH(A,_.key),W=qH(U,_.key);if(typeof z==="string"||typeof W==="string")return String(z).localeCompare(String(W),"zh-CN")*F;return(z-W)*F||Tf(A.pid)-Tf(U.pid)})},[l,_.key,_.direction]),J=(F,A)=>{let U=_.key===A,z=U?_.direction==="asc"?"ascending":"descending":"none";return Q("th",{"aria-sort":z},Q("button",{type:"button",className:`process-sort-button ${U?"active":""}`,"data-testid":`process-sort-${A}`,onClick:()=>y((W)=>({key:A,direction:W.key===A&&W.direction==="desc"?"asc":"desc"}))},F,Q("span",null,U?_.direction==="desc"?"↓":"↑":"↕")))};return Q("section",{className:"process-resource-panel","data-testid":"process-resource-panel"},Q("div",{className:"process-resource-head"},Q("div",null,Q("p",{className:"panel-eyebrow"},"Windows Resource Monitor Style"),Q("h3",null,"进程资源占用")),Q("div",{className:"process-resource-actions"},Q("span",{className:"data-chip"},"默认按内存排序"),Q("span",{className:"data-chip"},`${Tf($.visible,j.length)} / ${Tf($.total,j.length)} 进程`),Q(k0,{title:"Process Resource Snapshot",data:{processSummary:$,processes:l},onOpen:u,testId:"raw-process-resources"}))),j.length===0?Q(l0,{title:"暂无进程资源数据",text:"等待 provider-gateway 上报 /proc/[pid] 采样;旧版 provider 需要先升级到支持进程资源表的版本"}):Q("div",{className:"process-table-wrap"},Q("table",{className:"process-resource-table","data-testid":"process-resource-table"},Q("thead",null,Q("tr",null,J("进程","name"),J("PID","pid"),J("用户","user"),Q("th",null,"状态"),J("CPU","cpu"),J("内存","memory"),Q("th",null,"RSS"),J("磁盘 I/O","disk"),J("线程","threads"),J("运行时长","runtime"))),Q("tbody",null,j.map((F)=>{let A=Tf(F.readBytesPerSecond)+Tf(F.writeBytesPerSecond);return Q("tr",{key:`${F.pid}-${F.startedAt}`,"data-testid":`process-row-${N1(F.pid)}`,"data-memory-bytes":String(Tf(F.rssBytes)),"data-cpu-percent":String(Tf(F.cpuPercent)),"data-disk-bps":String(A),"data-pid":String(Tf(F.pid))},Q("td",null,Q("div",{className:"process-name-cell"},Q("strong",null,F.name||"--"),Q("span",{className:"process-command"},F.command||"--"))),Q("td",null,Q("code",null,F.pid||"--")),Q("td",null,F.user||`uid:${F.uid??"--"}`),Q("td",null,Q("span",{className:`process-state state-${N1(F.state||"unknown")}`},F.state||"?")),Q("td",null,Q(HH,{value:F.cpuPercent,label:ZS(F.cpuPercent),tone:"cpu"})),Q("td",null,Q(HH,{value:F.memoryPercent,label:$y(F.memoryPercent),tone:"memory"})),Q("td",null,Ju(F.rssBytes)),Q("td",null,Q("div",{className:"process-io-cell"},Q("strong",null,QQ(A)),Q("span",null,`R ${QQ(F.readBytesPerSecond)} / W ${QQ(F.writeBytesPerSecond)}`))),Q("td",null,F.threads||0),Q("td",null,H$(Tf(F.elapsedSeconds))))})))))}function AQ({title:f,metricKey:u,current:_,points:y,detail:$,tone:l,testId:j}){let J=y.map((W)=>Math.max(0,Math.min(100,Tf(W[u])))),F=J.length>1?J:[J[0]||0,J[0]||0],A=F.length<=1?100:100/(F.length-1),U=F.map((W,K)=>`${(K*A).toFixed(2)},${(46-W*0.42).toFixed(2)}`).join(" "),z=`0,48 ${U} 100,48`;return Q("article",{className:`metric-chart ${l}`,"data-testid":j},Q("div",{className:"metric-chart-head"},Q("div",null,Q("span",null,f),Q("strong",null,$y(_))),Q("code",null,`${y.length} pts`)),Q("svg",{viewBox:"0 0 100 48",preserveAspectRatio:"none",role:"img","aria-label":`${f} usage curve`},Q("polygon",{points:z}),Q("polyline",{points:U}),Q("line",{x1:"0",x2:"100",y1:"24",y2:"24"})),Q("div",{className:"metric-chart-foot"},Q("span",null,"0%"),Q("span",null,$),Q("span",null,"100%")))}function U_(f){return Array.isArray(f)?f:[]}function bS(f){let u=U_(f?.core?.requests?.componentSummary);return[...U_(f?.frontend?.requests?.componentSummary),...u].sort((y,$)=>Tf($.requestCount)-Tf(y.requestCount))}function hS(f){let u=U_(f?.core?.operations?.summary);return[...U_(f?.frontend?.operations?.summary),...u].sort((y,$)=>Tf($.count)-Tf(y.count))}function IS(f){let u=U_(f?.core?.requests?.recentFailures).map((y)=>({source:"backend",...y}));return[...U_(f?.frontend?.requests?.recentFailures).map((y)=>({source:"frontend",...y})),...u].sort((y,$)=>(Z$($.at)??0)-(Z$(y.at)??0)).slice(0,20)}function cS(f){let u=U_(f?.core?.operations?.recentSlowOperations);return[...U_(f?.frontend?.operations?.recentSlowOperations),...u].sort((y,$)=>Tf($.durationMs)-Tf(y.durationMs)).slice(0,20)}function pS(f){let u=performance.memory,_=Number(u?.usedJSHeapSize);if(Number.isFinite(_)&&_>0)return _;let y=Number(f?.appBundleBytes);if(Number.isFinite(y)&&y>0)return y;return Tf(f?.process?.heapUsedBytes)}function mS({points:f}){let u=U_(f),_=u.map((W)=>Tf(W.mb)),y=Math.max(1,..._),$=Math.max(0,Math.min(..._,0)),l=Math.max(1,y-$),j=u.length>1?u:[...u,...u],J=j.length<=1?100:100/(j.length-1),F=j.map((W,K)=>{let q=Tf(W.mb);return`${(K*J).toFixed(2)},${(48-(q-$)/l*42).toFixed(2)}`}).join(" "),A=`0,50 ${F} 100,50`,U=u.at(-1),z=u[0];return Q("article",{className:"performance-memory-card","data-testid":"performance-memory-chart"},Q("div",{className:"performance-memory-head"},Q("strong",null,`Bwebui: ${U?`${Tf(U.mb).toFixed(1)}MB`:"--"}`),Q("span",null,u.length>0?`${u.length} samples`:"等待采样")),Q("svg",{viewBox:"0 0 100 50",preserveAspectRatio:"none",role:"img","aria-label":"Bwebui memory trend"},Q("polygon",{points:A}),Q("polyline",{points:F}),Q("line",{x1:"0",x2:"100",y1:"25",y2:"25"})),Q("div",{className:"performance-axis-row"},Q("span",null,z?W2(new Date(z.at)):"--"),Q("span",null,"时间"),Q("span",null,U?W2(new Date(U.at)):"--")),Q("div",{className:"performance-axis-row"},Q("span",null,`${$.toFixed(1)}`),Q("span",null,"(MB)"),Q("span",null,`${y.toFixed(1)}`)))}function kS({onRaw:f}){let[u,_]=hf({core:null,frontend:null}),[y,$]=hf([]),[l,j]=hf(""),[J,F]=hf(!1),[A,U]=hf(null),[z,W]=hf(!1);async function K(){F(!0),j("");try{let[C,P]=await Promise.all([wf(`${tf.apiBaseUrl}/performance`,{cache:"no-store"}),wf(`${tf.apiBaseUrl}/frontend-performance`,{cache:"no-store"})]);_({core:C,frontend:P});let w=pS(P);$((r)=>[...r,{at:new Date().toISOString(),mb:w/1048576}].slice(-80))}catch(C){j(Mf(C,"性能指标加载失败"))}finally{F(!1)}}p1(()=>{K();let C=setInterval(()=>void K(),5000);return()=>clearInterval(C)},[]);async function q(){W(!0),j(""),U(null);try{let C=await wf(`${tf.apiBaseUrl}/codex-queue-load-test`,{method:"POST",body:JSON.stringify({targetMs:1000,timeoutMs:90000,url:tf.frontendPublicUrl||window.location.origin})});U(C),K()}catch(C){j(Mf(C,"Codex Queue Playwright 测量失败"))}finally{W(!1)}}let E=bS(u),O=IS(u),G=hS(u),H=cS(u),Z=u.core?.process||{},V=u.frontend?.process||{},L=u.core?.database?.codexQueueStorage||{},M=Tf(L.total),N=A?.result||{},D=Tf(N.wallMs,NaN),x=Tf(N.networkIdleMs,NaN),c=N.withinTarget===!0,v=z?"running":A===null?"idle":A.measurementOk===!0?c?"passed":"slow":"failed";return Q("div",{className:"performance-page","data-testid":"performance-page"},Q("div",{className:"performance-hero"},Q("div",null,Q("p",{className:"panel-eyebrow"},"Unified Performance"),Q("h2",null,"性能面板"),Q("p",null,"按组件统计 HTTP 请求、失败率、P95 延迟,并汇总 backend/frontend 内部操作耗时。")),Q("div",{className:"inline-actions"},Q("button",{type:"button",className:"ghost-btn",onClick:()=>void q(),disabled:z,"data-testid":"codex-queue-load-test-button"},z?"测试中...":"测试 Codex Queue 加载"),Q("button",{type:"button",className:"ghost-btn",onClick:()=>void K(),disabled:J,"data-testid":"performance-refresh-button"},J?"刷新中":"刷新"),Q(k0,{title:"Performance Snapshot",data:u,onOpen:f,testId:"raw-performance"}))),Q(H0,{error:l}),Q("div",{className:"performance-top-grid"},Q(mS,{points:y}),Q("div",{className:"performance-metric-stack"},Q(f0,{label:"backend RSS",value:Ju(Z.rssBytes),hint:`heap ${Ju(Z.heapUsedBytes)}`}),Q(f0,{label:"frontend RSS",value:Ju(V.rssBytes),hint:`bundle ${Ju(u.frontend?.appBundleBytes)}`}),Q(f0,{label:"Codex PG 任务",value:M||"--",hint:L.ok?"unidesk_codex_queue_tasks":"等待表初始化",tone:L.ok?"ok":"warn"}),Q(f0,{label:"请求样本",value:Tf(u.core?.requests?.sampleCount)+Tf(u.frontend?.requests?.sampleCount),hint:"rolling window 3000"}))),Q(kf,{title:"Codex Queue 加载基准",eyebrow:"Playwright / target <1s",className:"codex-load-test-panel",actions:Q("div",{className:"panel-actions"},Q("button",{type:"button",className:"primary-btn",onClick:()=>void q(),disabled:z,"data-testid":"codex-queue-load-test-panel-button"},z?"正在运行 Playwright...":"手动触发测试"),A?Q(k0,{title:"Codex Queue Load Test",data:A,onOpen:f,testId:"raw-codex-queue-load-test"}):null)},Q("div",{className:"codex-load-test-grid","data-testid":"codex-queue-load-test-result"},Q(f0,{label:"总耗时",value:z?"运行中":Number.isFinite(D)?pu(D):"--",hint:A===null?"点击按钮启动远端 Playwright":`目标 ${pu(N.targetMs||1000)} / ${N.url||"Codex Queue"}`,tone:v==="passed"?"ok":v==="failed"||v==="slow"?"warn":""}),Q(f0,{label:"判定",value:z?"RUNNING":v==="passed"?"PASS <1s":v==="slow"?"SLOW":v==="failed"?"FAILED":"--",hint:A?.measurementOk===!1?String(A.error||N.error||"measurement failed").slice(0,120):"导航开始 -> DOMContentLoaded -> data-load-state=complete",tone:v==="passed"?"ok":v==="idle"||v==="running"?"":"fail"}),Q(f0,{label:"Network idle",value:Number.isFinite(x)?pu(x):"--",hint:`DOMContentLoaded ${pu(N.domContentLoadedMs)} / ${N.networkIdleReached===!1?"未在 5s 内空闲":"已空闲"}`,tone:Number.isFinite(x)&&x<=1000?"ok":"warn"}),Q(f0,{label:"组件耗时",value:Number.isFinite(Tf(N.componentLoadMs,NaN))?pu(N.componentLoadMs):"--",hint:`queue ${pu(N.queueMs)} / detail ${pu(N.detailMs)}`,tone:Tf(N.componentLoadMs)>1000?"warn":"ok"}),Q(f0,{label:"Trace 规模",value:Number.isFinite(Tf(N.transcriptRows,NaN))?String(N.transcriptRows):"--",hint:`${N.visibleTaskCount??0} visible tasks / ${N.partial?"preview":"complete"}`})),z?Q("div",{className:"performance-empty-line"},"正在通过 main-server Host SSH 启动 Playwright,完成后会显示 wall time、组件耗时和最慢 API。"):null,A&&Array.isArray(N.slowestApi)&&N.slowestApi.length>0?Q("div",{className:"table-wrap performance-table-wrap compact codex-load-api-table"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["API","状态","耗时"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,N.slowestApi.slice(0,5).map((C,P)=>Q("tr",{key:`${C.url}-${P}`},Q("td",null,Q("code",null,C.url)),Q("td",null,C.status),Q("td",null,pu(C.durationMs))))))):null),Q("div",{className:"performance-grid"},Q(kf,{title:"组件汇总",eyebrow:"Requests"},E.length===0?Q(l0,{title:"暂无请求样本",text:"刷新几次或打开页面后会自动形成组件统计"}):Q("div",{className:"table-wrap performance-table-wrap"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["组件","请求数","失败数","失败率","平均延迟","P95"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,E.map((C)=>Q("tr",{key:C.component},Q("td",null,Q("code",null,C.component)),Q("td",null,C.requestCount),Q("td",null,C.failureCount),Q("td",null,$y(Tf(C.failureRate)*100)),Q("td",null,pu(C.averageLatencyMs)),Q("td",null,pu(C.p95LatencyMs)))))))),Q(kf,{title:"最近失败请求",eyebrow:"Failures"},O.length===0?Q("div",{className:"performance-empty-line"},"最近没有失败请求"):Q("div",{className:"table-wrap performance-table-wrap compact"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["时间","来源","组件","状态","路径"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,O.map((C,P)=>Q("tr",{key:`${C.at}-${P}`},Q("td",null,m0(C.at)),Q("td",null,C.source),Q("td",null,Q("code",null,C.component)),Q("td",null,Q(V0,{status:"failed"},C.status)),Q("td",null,Q("code",null,C.path)))))))),Q(kf,{title:"内部操作汇总",eyebrow:"Operations"},G.length===0?Q(l0,{title:"暂无内部操作样本",text:"API 查询和代理请求会自动记录内部操作耗时"}):Q("div",{className:"table-wrap performance-table-wrap"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["服务","操作","次数","平均延迟","P95"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,G.map((C)=>Q("tr",{key:`${C.service}-${C.operation}`},Q("td",null,C.service),Q("td",null,Q("code",null,C.operation)),Q("td",null,C.count),Q("td",null,pu(C.averageLatencyMs)),Q("td",null,pu(C.p95LatencyMs)))))))),Q(kf,{title:"最近慢操作",eyebrow:"Slowest"},H.length===0?Q(l0,{title:"暂无慢操作",text:"后端会记录最近窗口内耗时最高的内部操作"}):Q("div",{className:"table-wrap performance-table-wrap"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["时间","操作","耗时","结果","细节"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,H.map((C,P)=>Q("tr",{key:`${C.at}-${C.operation}-${P}`},Q("td",null,m0(C.at)),Q("td",null,Q("code",null,C.operation)),Q("td",null,pu(C.durationMs)),Q("td",null,C.ok?"成功":"失败"),Q("td",null,C.detail||"-")))))))))}function iS({provider:f,refresh:u,onRaw:_}){let[y,$]=hf(""),[l,j]=hf(null),[J,F]=hf("");async function A(U){$(U),F("");try{let z=await wf(`${tf.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:f.providerId,command:"provider.upgrade",payload:{mode:U,source:"frontend-resource-monitor",requestedAt:new Date().toISOString()}})});j({mode:U,...z}),await u()}catch(z){F(Mf(z,"升级命令下发失败"))}finally{$("")}}return Q(kf,{title:"Provider Gateway 升级",eyebrow:"Remote Control"},Q("div",{className:"upgrade-control","data-testid":"provider-upgrade-control"},Q("p",null,"通过 UniDesk WebSocket 向当前计算节点下发 provider.upgrade;预检只生成升级计划,执行升级会调度节点本地 updater 容器。"),Q("div",{className:"upgrade-target-line"},Q("span",null,"指定 Provider"),Q("code",null,f.providerId),Q(q$,{node:f})),Q("div",{className:"upgrade-actions"},Q("button",{type:"button",className:"ghost-btn",disabled:Boolean(y),onClick:()=>A("plan"),"data-testid":"upgrade-plan-button"},y==="plan"?"预检中":"预检升级"),Q("button",{type:"button",className:"ghost-btn danger",disabled:Boolean(y),onClick:()=>A("schedule"),"data-testid":"upgrade-schedule-button"},y==="schedule"?"调度中":"执行升级")),Q(H0,{error:J}),l?Q("div",{className:"upgrade-result"},Q(V0,{status:l.status||"queued"},l.status||"queued"),Q("span",null,`${l.mode==="schedule"?"执行升级":"预检升级"} 已下发`),Q("span",null,`指定版本 ${GQ(BH(f))}`),Q("code",null,l.taskId||"--"),Q(k0,{title:"Provider Upgrade Dispatch",data:l,onOpen:_})):Q("span",{className:"muted"},"升级任务结果会进入任务历史;执行升级可能导致 provider 短暂重连。")))}function RH({records:f,onRaw:u,compact:_=!1}){if(f.length===0)return Q(l0,{title:"暂无远程更新记录",text:"该节点还没有 provider.upgrade 任务;执行预检或升级后会在这里形成结构化记录"});return Q("div",{className:`upgrade-record-table-wrap table-wrap ${_?"compact":""}`},Q("table",{className:"upgrade-record-table"},Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"模式"),Q("th",null,"任务"),Q("th",null,"来源"),Q("th",null,"耗时"),Q("th",null,"策略"),Q("th",null,"Gateway 版本"),Q("th",null,"结果记录"),Q("th",null,"更新时间"),Q("th",null,"操作"))),Q("tbody",null,f.map((y)=>Q("tr",{key:y.id,"data-testid":`gateway-upgrade-record-${N1(y.id)}`},Q("td",null,Q(V0,{status:y.status})),Q("td",null,Q("span",{className:`mode-chip ${z2(y)}`},z2(y)==="schedule"?"执行升级":"预检")),Q("td",null,Q("strong",null,"provider.upgrade"),Q("code",null,y.id)),Q("td",null,VS(y)),Q("td",null,Q(vH,{task:y})),Q("td",null,OS(y)),Q("td",null,Q("span",{className:"version-chip"},MH(y))),Q("td",null,Q("span",{className:`upgrade-outcome ${String(y.status||"").toLowerCase()}`},SH(y))),Q("td",null,m0(y.updatedAt)),Q("td",null,Q(k0,{title:`Provider Upgrade Task ${y.id}`,data:Rl(y),onOpen:u})))))))}function gS({provider:f,tasks:u,onRaw:_,limit:y=5}){let $=rH(u,f.providerId).slice(0,y);return Q(kf,{title:"远程更新记录",eyebrow:f.providerId,actions:Q(q$,{node:f}),className:"provider-upgrade-records-panel"},Q("div",{"data-testid":`provider-upgrade-records-${N1(f.providerId)}`},Q(RH,{records:$,onRaw:_,compact:!0})))}function nS({nodes:f,tasks:u,onRaw:_}){let y=Cl(()=>f.map((l)=>{let j=rH(u,l.providerId);return{node:l,records:j,latest:XS(j),capabilities:wH(l)}}),[f,u]),$=y.reduce((l,j)=>l+j.records.length,0);return Q("div",{className:"gateway-page","data-testid":"gateway-version-page"},Q(kf,{title:"Provider Gateway 版本",eyebrow:`${f.length} Providers / ${$} 更新记录`},f.length===0?Q(l0,{title:"暂无 Provider 节点",text:"等待 provider-gateway 注册后显示版本号和升级记录"}):Q("div",{className:"table-wrap gateway-version-table-wrap"},Q("table",{className:"gateway-version-table"},Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"Provider"),Q("th",null,"Gateway 版本"),Q("th",null,"升级策略"),Q("th",null,"运维可用性"),Q("th",null,"运行时间"),Q("th",null,"能力"),Q("th",null,"最近远程更新"),Q("th",null,"操作"))),Q("tbody",null,y.map((l)=>Q("tr",{key:l.node.providerId},Q("td",null,Q(V0,{status:l.node.status})),Q("td",null,Q("strong",null,l.node.name),Q("code",null,l.node.providerId)),Q("td",null,Q(q$,{node:l.node})),Q("td",null,rl(l.node)),Q("td",null,Q(KQ,{node:l.node})),Q("td",null,zH(l.node)?m0(zH(l.node)):"待新版上报"),Q("td",null,Q("div",{className:"capability-row"},l.capabilities.length===0?Q("span",{className:"muted"},"未声明"):l.capabilities.slice(0,5).map((j)=>Q("span",{key:j,className:"data-chip"},j)))),Q("td",null,l.latest?Q("div",{className:"latest-upgrade-cell"},Q(V0,{status:l.latest.status}),Q("span",null,`${z2(l.latest)==="schedule"?"执行升级":"预检"} / ${m0(l.latest.updatedAt)}`),Q("small",null,`Gateway ${MH(l.latest)}`),Q("small",null,SH(l.latest))):Q("span",{className:"muted"},"暂无记录")),Q("td",null,Q(k0,{title:`Provider ${l.node.providerId}`,data:l.node,onOpen:_})))))))),Q(kf,{title:"远程更新记录",eyebrow:"Structured provider.upgrade records"},f.length===0?Q(l0,{title:"暂无记录",text:"没有 provider 节点时不会生成远程更新记录"}):Q("div",{className:"gateway-record-grid"},y.map((l)=>Q("article",{key:l.node.providerId,className:"gateway-record-card","data-testid":`gateway-records-${N1(l.node.providerId)}`},Q("div",{className:"gateway-record-head"},Q("div",null,Q("strong",null,l.node.name),Q("code",null,l.node.providerId)),Q(q$,{node:l.node})),Q("div",{className:"gateway-record-meta"},Q("span",null,`心跳 ${m0(l.node.lastHeartbeat)}`),Q("span",null,`策略 ${rl(l.node)}`),Q("span",null,`${l.records.length} 条记录`)),Q(RH,{records:l.records.slice(0,8),onRaw:_,compact:!0}))))))}function tS(f){if(f==="running")return"online";if(f==="paused"||f==="restarting")return"warn";if(f==="exited"||f==="dead")return"offline";return"internal"}function xH(f){return/^[a-f0-9]{48,64}$/i.test(f)}function Sl(f){let u=String(f?.name||""),_=String(f?.labels||"");return u==="unidesk_pgdata_10gb"||_.includes("com.docker.compose.volume=unidesk_pgdata_10gb")||u.toLowerCase().includes("pgdata")}function EH(f){let u=String(f?.name||""),_=String(f?.labels||"");if(Sl(f))return 0;if(_.includes("com.docker.compose.project=unidesk"))return 1;if(!xH(u))return 2;return 3}function sS(f){return[...f].sort((u,_)=>{let y=EH(u)-EH(_);if(y!==0)return y;return String(u.name||"").localeCompare(String(_.name||""))})}function oS({nodes:f,dockerStatuses:u,onRaw:_}){let[y,$]=hf(""),l=Cl(()=>f.map((H)=>{let Z=u.find((V)=>V.providerId===H.providerId);return{...H,dockerStatus:Z?.dockerStatus||null,dockerUpdatedAt:Z?.updatedAt||null}}),[f,u]),j=l.find((H)=>H.providerId===y)||l[0]||null;if(p1(()=>{if(!y&&l[0])$(l[0].providerId)},[l.length,y]),!j)return Q(l0,{title:"暂无 Docker 节点",text:"等待 provider 上报 Docker daemon 状态"});let J=j.dockerStatus,F=j.providerId==="main-server",A=J?.counts||{},U=J?.daemon||{},z=J?.containers||[],W=J?.images||[],K=sS(J?.volumes||[]),q=F?K.find(Sl):null,E=J?.networks||[],O=z.filter((H)=>H.state==="running"),G=z.filter((H)=>H.state!=="running");return Q("div",{className:"docker-page","data-testid":"docker-status-page"},Q("div",{className:"docker-node-strip"},l.map((H)=>Q("button",{key:H.providerId,type:"button",className:`docker-node-tile ${j.providerId===H.providerId?"active":""}`,onClick:()=>$(H.providerId)},Q("span",{className:`pulse ${H.status}`}),Q("strong",null,H.name),Q("code",null,H.providerId),Q("span",null,H.dockerStatus?`Docker ${H.dockerStatus.ok?"ready":"degraded"}`:"等待上报")))),Q("div",{className:"docker-layout"},Q(kf,{title:"Docker Desktop 视图",eyebrow:j.name,className:"docker-main-panel",actions:J?Q(k0,{title:`Docker ${j.providerId}`,data:J,onOpen:_}):null},!J?Q(l0,{title:"Docker 状态未上报",text:"provider-gateway 会在连接后周期性采集 docker info / ps / images / volume / network"}):Q("div",null,Q("div",{className:"docker-hero"},Q("div",null,Q("p",{className:"panel-eyebrow"},"Daemon"),Q("h3",null,U.name||j.providerId),Q("div",{className:"docker-meta"},Q("span",null,U.serverVersion?`Engine ${U.serverVersion}`:"Engine --"),Q("span",null,U.operatingSystem||"OS --"),Q("span",null,U.architecture||"arch --"),Q("span",null,`${U.cpus||0} CPU / ${Ju(U.memoryBytes)}`))),Q(V0,{status:J.ok?"online":"warn"},J.ok?"Docker Ready":"Docker Degraded")),Q("div",{className:"docker-metrics"},Q(f0,{label:"Containers",value:A.containers??z.length,hint:`${A.running??O.length} running / ${A.stopped??G.length} stopped`,tone:"ok"}),Q(f0,{label:"Images",value:A.images??W.length,hint:`${A.daemonImages??A.images??W.length} daemon images`}),Q(f0,{label:"Volumes",value:A.volumes??K.length,hint:F?q?"database volume visible":"database volume missing":"node local volumes",tone:q?"ok":""}),Q(f0,{label:"Networks",value:A.networks??E.length,hint:U.driver?`driver ${U.driver}`:"docker networks"})),F?Q(aS,{volume:q,volumeCount:K.length}):null,Q("div",{className:"docker-section-head"},Q("h3",null,"Containers"),Q("span",null,`updated ${m0(j.dockerUpdatedAt||J.collectedAt)}`)),Q("div",{className:"docker-container-table table-wrap","data-testid":"docker-container-table"},Q("table",null,Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"容器"),Q("th",null,"镜像"),Q("th",null,"端口"),Q("th",null,"运行时间"),Q("th",null,"大小"))),Q("tbody",null,z.length===0?Q("tr",null,Q("td",{colSpan:6},"暂无容器")):z.map((H)=>Q("tr",{key:`${H.id}-${H.name}`},Q("td",null,Q(V0,{status:tS(H.state)},H.state||"unknown")),Q("td",null,Q("strong",null,H.name||"--"),Q("code",null,H.id||"--")),Q("td",null,H.image||"--"),Q("td",null,H.ports||Q("span",{className:"muted"},"未发布")),Q("td",null,H.runningFor||H.status||"--"),Q("td",null,H.size||"--")))))))),Q("div",{className:"docker-side-stack"},Q(UQ,{title:"Images",items:W,render:(H)=>Q("article",{key:`${H.id}-${H.repository}`,className:"docker-side-row"},Q("strong",null,`${H.repository}:${H.tag}`),Q("span",null,H.size||"--"),Q("code",null,H.id||"--"))}),Q(UQ,{title:"Volumes",items:K,limit:K.length,render:(H)=>Q("article",{key:H.name,className:`docker-side-row volume-row ${F&&Sl(H)?"database-volume":""}`,"data-testid":F&&Sl(H)?"database-volume-row":void 0},Q("strong",null,H.name),Q("span",null,F&&Sl(H)?"PostgreSQL":xH(String(H.name||""))?"anonymous":"named"),Q("code",null,H.mountpoint||H.driver||H.scope||"--"))}),Q(UQ,{title:"Networks",items:E,render:(H)=>Q("article",{key:H.id||H.name,className:"docker-side-row"},Q("strong",null,H.name),Q("span",null,H.driver||"--"),Q("code",null,H.id||"--"))}))))}function aS({volume:f,volumeCount:u}){return Q("section",{className:`docker-volume-focus ${f?"ready":"missing"}`,"data-testid":"database-volume-card"},Q("div",{className:"volume-focus-head"},Q("span",{className:"panel-eyebrow"},"Database Named Volume"),Q(V0,{status:f?"online":"warn"},f?"FOUND":"MISSING")),f?Q("div",{className:"volume-focus-body"},Q("strong",null,f.name),Q("span",null,"PostgreSQL data volume for unidesk-database"),Q("div",{className:"volume-route"},Q("code",null,f.mountpoint||"/var/lib/docker/volumes/unidesk_pgdata_10gb/_data"),Q("span",null,"->"),Q("code",null,"unidesk-database:/var/lib/postgresql/data")),Q("div",{className:"docker-meta compact"},Q("span",null,`driver ${f.driver||"--"}`),Q("span",null,`scope ${f.scope||"--"}`),Q("span",null,`${u} volumes reported`))):Q("div",{className:"volume-focus-body"},Q("strong",null,"unidesk_pgdata_10gb"),Q("span",null,"当前 Docker 快照没有发现数据库命名卷;请检查 provider-gateway 的 Docker volume 上报。")))}function UQ({title:f,items:u,render:_,limit:y}){let $=u.slice(0,y??12),l=Math.max(0,u.length-$.length);return Q(kf,{title:f,eyebrow:`${u.length} items`,className:"docker-side-panel"},u.length===0?Q(l0,{title:`暂无 ${f}`,text:"等待 Docker 状态采集"}):Q("div",{className:"docker-side-list"},$.map(_),l>0?Q("div",{className:"docker-side-more"},`+ ${l} more`):null))}function dS({microservices:f,onRaw:u,onNavigate:_}){let y=f.filter(($)=>KH($).public===!1);return Q("div",{className:"microservice-page","data-testid":"microservice-catalog-page"},Q(kf,{title:"用户服务目录",eyebrow:"Provider Mounted User Services"},Q("div",{className:"metric-grid"},Q(f0,{label:"服务总数",value:f.length,hint:"config.json 用户服务登记"}),Q(f0,{label:"私有后端",value:y.length,hint:"不直接暴露公网",tone:"ok"}),Q(f0,{label:"D601 服务",value:f.filter(($)=>$.providerId==="D601").length,hint:"compute-node docker"}),Q(f0,{label:"集成前端",value:f.filter(($)=>$.frontend?.integrated).length,hint:"UniDesk React 页面"}))),Q(kf,{title:"服务映射",eyebrow:"Repo Reference + Runtime"},f.length===0?Q(l0,{title:"暂无用户服务",text:"在 config.json 的 microservices 中登记用户服务的 provider、仓库引用和后端映射"}):Q("div",{className:"table-wrap"},Q("table",{className:"microservice-table"},Q("thead",null,Q("tr",null,Q("th",null,"服务"),Q("th",null,"Provider"),Q("th",null,"代码引用"),Q("th",null,"Docker 引用"),Q("th",null,"后端映射"),Q("th",null,"开发入口"),Q("th",null,"运行态"),Q("th",null,"操作"))),Q("tbody",null,f.map(($)=>{let l=PH($),j=NS($),J=KH($);return Q("tr",{key:$.id,"data-testid":`microservice-row-${N1($.id)}`},Q("td",null,Q("strong",null,$.name),Q("code",null,$.id)),Q("td",null,Q("strong",null,l.providerName||$.providerId),Q("code",null,$.providerId)),Q("td",null,Q("span",null,j.url||"--"),Q("code",null,j.commitId||"--")),Q("td",null,Q("span",null,j.composeFile||"--"),Q("code",null,`${j.composeService||"--"} / ${j.containerName||"--"}`)),Q("td",null,Q(V0,{status:J.public?"warn":"online"},J.public?"public":"private"),Q("code",null,`${J.nodeBindHost||"--"}:${J.nodePort||"--"} -> ${J.proxyMode||"--"}`)),Q("td",null,Q("span",null,$.development?.sshPassthrough?"SSH 透传":"未配置"),Q("code",null,$.development?.worktreePath||"--")),Q("td",null,Q(V0,{status:l.providerStatus==="online"?"online":"warn"},l.providerStatus||"unknown"),Q(ey,{data:l.container,empty:"容器快照未上报"})),Q("td",null,Q("div",{className:"microservice-actions"},$.id==="findjob"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","findjob"),"data-testid":"open-findjob-button"},"打开"):null,$.id==="pipeline"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","pipeline"),"data-testid":"open-pipeline-button"},"打开"):null,$.id==="todo-note"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","todo-note"),"data-testid":"open-todo-note-button"},"打开"):null,$.id==="met-nonlinear"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","met-nonlinear"),"data-testid":"open-met-nonlinear-button"},"打开"):null,$.id==="claudeqq"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","claudeqq"),"data-testid":"open-claudeqq-button"},"打开"):null,$.id==="codex-queue"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","codex-queue"),"data-testid":"open-codex-queue-button"},"打开"):null,$.id==="project-manager"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","project-manager"),"data-testid":"open-project-manager-button"},"打开"):null,Q(k0,{title:`用户服务 ${$.id}`,data:$,onOpen:u}))))}))))))}function eS({nodes:f,onDispatched:u,onRaw:_}){let y=f.filter((v)=>v.status==="online"),[$,l]=hf(y[0]?.providerId||f[0]?.providerId||""),[j,J]=hf("docker.ps"),[F,A]=hf("frontend"),[U,z]=hf("operator-check"),[W,K]=hf("normal"),[q,E]=hf(!1),[O,G]=hf(""),[H,Z]=hf(!1),[V,L]=hf(null),[M,N]=hf("");p1(()=>{if(!$&&(y[0]?.providerId||f[0]?.providerId))l(y[0]?.providerId||f[0].providerId)},[f.length,y.length,$]);function D(){return{source:F,note:U,priority:W}}function x(){G(JSON.stringify(D(),null,2)),E(!0)}async function c(v){v.preventDefault(),Z(!0),N("");try{let C=q?JSON.parse(O||"{}"):D(),P=await wf(`${tf.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:$,command:j,payload:C})});L(P),await u()}catch(C){N(Mf(C,"下发失败"))}finally{Z(!1)}}return Q("div",{className:"page-grid dispatch-grid"},Q(kf,{title:"下发任务",eyebrow:"Real WebSocket Dispatch"},Q("form",{className:"dispatch-form",onSubmit:c},Q("label",null,"Provider",Q("select",{value:$,onChange:(v)=>l(v.target.value)},f.map((v)=>Q("option",{key:v.providerId,value:v.providerId},`${v.name} / ${v.providerId}`)))),Q("label",null,"Command",Q("select",{value:j,onChange:(v)=>J(v.target.value)},Q("option",{value:"docker.ps"},"docker.ps"),Q("option",{value:"host.ssh"},"host.ssh"),Q("option",{value:"microservice.http"},"microservice.http"),Q("option",{value:"echo"},"echo"))),Q("label",null,"来源",Q("input",{value:F,onChange:(v)=>A(v.target.value)})),Q("label",null,"备注",Q("input",{value:U,onChange:(v)=>z(v.target.value)})),Q("label",null,"优先级",Q("select",{value:W,onChange:(v)=>K(v.target.value)},Q("option",{value:"normal"},"normal"),Q("option",{value:"low"},"low"),Q("option",{value:"urgent"},"urgent"))),Q("div",{className:"dispatch-actions"},Q("button",{type:"button",className:"ghost-btn",onClick:x},"查看原始JSON"),Q("button",{type:"submit",disabled:H||!$},H?"下发中":"下发任务")),q?Q("label",{className:"raw-editor-label"},"高级 Payload",Q("textarea",{className:"raw-editor",value:O,onChange:(v)=>G(v.target.value)})):null,Q(H0,{error:M,wide:!0}))),Q(kf,{title:"下发结果",eyebrow:"Response"},V?Q("div",{className:"result-card"},Q(V0,{status:V.status||"queued"},V.status||"queued"),Q("dl",null,Q("dt",null,"Task ID"),Q("dd",null,Q("code",null,V.taskId||"--")),Q("dt",null,"Provider 在线"),Q("dd",null,dy(V.providerOnline))),Q(k0,{title:"Dispatch Response",data:V,onOpen:_})):Q(l0,{title:"等待操作",text:"任务响应会以结构化结果卡展示"})))}function VH({task:f,onRaw:u}){return Q("article",{className:"compact-row"},Q(V0,{status:f.status}),Q("div",null,Q("strong",null,f.command),Q("code",null,f.id)),Q("span",null,E$(f)?`已等待 ${WQ(f.updatedAt)}`:`耗时 ${H$(NH(f)??0)}`),Q(k0,{title:`Task ${f.id}`,data:Rl(f),onOpen:u}))}function vH({task:f}){let u=NH(f),_=E$(f);return Q("div",{className:"task-duration"},Q("strong",null,u===null?"--":H$(u)),Q("span",null,_?`已运行 / 创建 ${m0(f.createdAt)}`:`创建 ${m0(f.createdAt)}`))}function fr({task:f}){let u=String(f?.status||"").toLowerCase(),_=f?.result,y=_&&typeof _==="object"&&!Array.isArray(_)?_:{},l=["exitCode","code","signal","timeoutMs","previousStatus","mode"].filter((j)=>y[j]!==void 0&&y[j]!==null);if(u==="failed"){let j=LH(f);return Q("div",{className:"task-diagnostic failed"},Q("b",null,"失败原因"),Q("span",{className:"diagnostic-reason"},dy(j)),l.length>0?Q("div",{className:"diagnostic-meta"},l.map((J)=>Q("span",{key:J,className:"data-chip"},Q("b",null,J),Q("span",null,dy(y[J]))))):null)}if(E$(f))return Q("div",{className:"task-diagnostic warn"},Q("b",null,"等待终态"),Q("span",null,`最后更新 ${WQ(f.updatedAt)} 前`));return Q("div",{className:"task-diagnostic ok"},Q("b",null,"完成摘要"),Q(ey,{data:_,empty:"无执行输出"}))}function ur({tasks:f,onRaw:u}){let _=f.filter(E$);return Q("div",{"data-testid":"pending-task-page"},Q(kf,{title:"待处理任务",eyebrow:`${_.length} Pending`},_.length===0?Q(l0,{title:"当前无待处理任务",text:"queued / dispatched / running 会在超时后自动转为 failed;历史记录仍可在任务历史中查看"}):Q("div",{className:"table-wrap","data-testid":"pending-task-table"},Q("table",null,Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"任务"),Q("th",null,"Provider"),Q("th",null,"已等待"),Q("th",null,"载荷摘要"),Q("th",null,"操作"))),Q("tbody",null,_.map((y)=>Q("tr",{key:y.id},Q("td",null,Q(V0,{status:y.status})),Q("td",null,Q("strong",null,y.command),Q("code",null,y.id)),Q("td",null,Q("code",null,y.providerId)),Q("td",null,WQ(y.updatedAt)),Q("td",null,Q(ey,{data:y.payload})),Q("td",null,Q(k0,{title:`Pending Task ${y.id}`,data:Rl(y),onOpen:u})))))))))}function _r({tasks:f,onRaw:u}){return Q("div",{"data-testid":"task-history-page"},Q(kf,{title:"任务历史",eyebrow:`${f.length} Tasks`},f.length===0?Q(l0,{title:"暂无任务",text:"下发任务后会在这里看到生命周期"}):Q("div",{className:"table-wrap"},Q("table",{className:"task-history-table"},Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"任务"),Q("th",null,"Provider"),Q("th",null,"任务耗时"),Q("th",null,"载荷摘要"),Q("th",null,"诊断信息"),Q("th",null,"更新时间"),Q("th",null,"操作"))),Q("tbody",null,f.map((_)=>Q("tr",{key:_.id,"data-testid":`task-row-${N1(_.id)}`},Q("td",null,Q(V0,{status:_.status})),Q("td",null,Q("strong",null,_.command),Q("code",null,_.id)),Q("td",null,Q("code",null,_.providerId)),Q("td",null,Q(vH,{task:_})),Q("td",null,Q(ey,{data:_.payload})),Q("td",null,Q(fr,{task:_})),Q("td",null,m0(_.updatedAt)),Q("td",null,Q(k0,{title:`Task ${_.id}`,data:Rl(_),onOpen:u})))))))))}function yr({tasks:f,onRaw:u}){let _=f.filter((y)=>["succeeded","failed"].includes(y.status));return Q(kf,{title:"执行结果",eyebrow:"Finished Tasks"},_.length===0?Q(l0,{title:"暂无结果",text:"任务完成后展示 provider 返回的结构化摘要"}):Q("div",{className:"result-grid"},_.map((y)=>Q("article",{key:y.id,className:"result-card"},Q("div",{className:"node-card-head"},Q("strong",null,y.command),Q(V0,{status:y.status})),Q("code",null,y.id),Q(ey,{data:y.result,empty:"无执行输出"}),Q(k0,{title:`Task Result ${y.id}`,data:Rl(y),onOpen:u})))))}function $r({data:f}){let u=f.overview||{};return Q("div",{className:"page-grid topology-grid"},Q(kf,{title:"公开入口",eyebrow:"Public"},Q("div",{className:"endpoint-list"},Q("article",null,Q("b",null,"Frontend"),Q("span",null,tf.frontendPublicUrl||window.location.origin),Q(V0,{status:"online"},"public")),Q("article",null,Q("b",null,"Provider Ingress"),Q("span",null,tf.providerIngressPublicUrl||"ws://public/ws/provider"),Q(V0,{status:"online"},"public")))),Q(kf,{title:"内部服务",eyebrow:"Docker Network Only"},Q("div",{className:"endpoint-list"},Q("article",null,Q("b",null,"backend-core API"),Q("span",null,"http://backend-core:8080"),Q(V0,{status:"internal"},"internal")),Q("article",null,Q("b",null,"database"),Q("span",null,"postgres://database:5432/unidesk"),Q(V0,{status:"internal"},"internal")))),Q(kf,{title:"运行态",eyebrow:"Runtime"},Q("div",{className:"metric-grid"},Q(f0,{label:"DB Ready",value:u.dbReady?"YES":"NO",hint:"internal health"}),Q(f0,{label:"Online Nodes",value:u.onlineNodeCount??0,hint:"provider-gateway self-link"}))))}function lr({session:f}){return Q(kf,{title:"认证策略",eyebrow:"Frontend Login"},Q("div",{className:"policy-grid"},Q("article",null,Q("span",null,"默认账号"),Q("strong",null,tf.authUsername||"admin")),Q("article",null,Q("span",null,"当前会话"),Q("strong",null,f?.user?.username||"--")),Q("article",null,Q("span",null,"Session TTL"),Q("strong",null,`${tf.sessionTtlSeconds||0}s`)),Q("article",null,Q("span",null,"API 访问"),Q("strong",null,"同源 Cookie 保护"))),Q("p",{className:"muted paragraph"},"浏览器只访问 frontend 同源接口;frontend 容器使用 Docker 内网代理 backend-core API。"))}function jr(){return Q(kf,{title:"安全边界",eyebrow:"Exposure Rule"},Q("div",{className:"security-board"},Q("article",{className:"allow"},Q("b",null,"允许公网"),Q("span",null,"frontend 登录入口"),Q("span",null,"provider ingress WebSocket/health")),Q("article",{className:"deny"},Q("b",null,"禁止公网"),Q("span",null,"backend-core REST API"),Q("span",null,"PostgreSQL database")),Q("article",null,Q("b",null,"数据库卷"),Q("span",null,"named volume unidesk_pgdata_10gb"),Q("span",null,"CLI stop/start 不删除数据卷"))))}function Jr({activeModule:f,activeTab:u,data:_,session:y,refresh:$,onRaw:l,onNavigate:j}){if(f==="ops"&&u==="status")return Q(TS,{data:_,onRaw:l,onNavigate:j});if(f==="ops"&&u==="performance")return Q(kS,{onRaw:l});if(f==="ops"&&u==="events")return Q(SS,{events:_.events,onRaw:l});if(f==="ops"&&u==="logs")return Q(rS,{logs:_.logs,onRaw:l});if(f==="nodes"&&u==="list")return Q(PS,{nodes:_.nodes,onRaw:l});if(f==="nodes"&&u==="monitor")return Q(xS,{nodes:_.nodes,systemStatuses:_.systemStatuses,tasks:_.tasks,onRaw:l,refresh:$});if(f==="nodes"&&u==="docker")return Q(oS,{nodes:_.nodes,dockerStatuses:_.dockerStatuses,onRaw:l});if(f==="nodes"&&u==="gateway")return Q(nS,{nodes:_.nodes,tasks:_.tasks,onRaw:l});if(f==="nodes"&&u==="labels")return Q(CS,{nodes:_.nodes});if(f==="nodes"&&u==="heartbeats")return Q(RS,{nodes:_.nodes});if(f==="tasks"&&u==="dispatch")return Q(eS,{nodes:_.nodes,onDispatched:$,onRaw:l});if(f==="tasks"&&u==="pending")return Q(ur,{tasks:_.pendingTasks,onRaw:l});if(f==="tasks"&&u==="history")return Q(_r,{tasks:_.tasks,onRaw:l});if(f==="tasks"&&u==="results")return Q(yr,{tasks:_.tasks,onRaw:l});if(f==="apps"&&u==="catalog")return Q(dS,{microservices:_.microservices,onRaw:l,onNavigate:j});if(f==="apps"&&u==="todo-note")return Q(FH,{microservices:_.microservices,onRaw:l,apiBaseUrl:tf.apiBaseUrl});if(f==="apps"&&u==="findjob")return Q(fG,{microservices:_.microservices,onRaw:l,apiBaseUrl:tf.apiBaseUrl});if(f==="apps"&&u==="pipeline")return Q(eq,{microservices:_.microservices,onRaw:l,apiBaseUrl:tf.apiBaseUrl});if(f==="apps"&&u==="met-nonlinear")return Q(lG,{microservices:_.microservices,onRaw:l,apiBaseUrl:tf.apiBaseUrl});if(f==="apps"&&u==="claudeqq")return Q(Jz,{microservices:_.microservices,onRaw:l,apiBaseUrl:tf.apiBaseUrl});if(f==="apps"&&u==="codex-queue")return Q(ez,{microservices:_.microservices,onRaw:l,apiBaseUrl:tf.apiBaseUrl,initialTasksData:WS});if(f==="apps"&&u==="project-manager")return Q(_H,{microservices:_.microservices,onRaw:l,apiBaseUrl:tf.apiBaseUrl});if(f==="config"&&u==="topology")return Q($r,{data:_});if(f==="config"&&u==="auth")return Q(lr,{session:y});if(f==="config"&&u==="security")return Q(jr);return Q(l0,{title:"未找到页面",text:"请选择左侧主模块和顶部子功能标签"})}function Fr({session:f,onLogout:u}){let _=Dj(mu,window.location.pathname),[y,$]=hf(_.moduleId),[l,j]=hf({...m3,[_.moduleId]:_.tabId}),[J,F]=hf({overview:null,nodes:[],systemStatuses:[],dockerStatuses:[],microservices:[],events:[],tasks:[],pendingTasks:[],logs:[]}),[A,U]=hf({ok:!1,text:"连接中"}),[z,W]=hf(null),[K,q]=hf(new Date),[E,O]=hf(null),[G,H]=hf(!1),Z=Pl.default.useRef(!1),V=mu.moduleById[y]||mu.modules[0],L=l[y]||m3[y]||V.tabs[0].id,M=Array.isArray(J.microservices)?J.microservices:[],N=M.length===0&&y==="apps"&&L==="codex-queue"?[zS]:M,D=N===M?J:{...J,microservices:N},x=y==="apps"?N.find((S)=>String(S?.id||"")===L):null,c=x?PH(x):{},v=V.tabs.find((S)=>S.id===L)?.label||L,C=x?[{key:"microservice",label:"用户服务",value:`${v} ${c.providerStatus==="online"?"在线":c.providerStatus||"未知"}`,tone:c.providerStatus==="online"?"ok":"warn",testId:"active-microservice-status"}]:[];async function P(){if(Z.current)return;Z.current=!0;try{let S=[],T=(n,_f)=>{S.push([n,wf(_f)])},Y=y==="ops"&&L==="status",R=Y||y==="config"&&L==="topology",m=Y||y==="nodes"||y==="tasks"&&L==="dispatch",p=y==="apps"&&L!=="codex-queue";if(R)T("overview",`${tf.apiBaseUrl}/overview`);if(m)T("nodes",`${tf.apiBaseUrl}/nodes`);if(y==="nodes"&&L==="monitor")T("systemStatuses",`${tf.apiBaseUrl}/nodes/system-status?limit=60`),T("tasks",`${tf.apiBaseUrl}/tasks?limit=120&summary=1`);else if(y==="nodes"&&L==="docker")T("dockerStatuses",`${tf.apiBaseUrl}/nodes/docker-status`);else if(y==="nodes"&&L==="gateway")T("tasks",`${tf.apiBaseUrl}/tasks?limit=300&summary=1`);else if(y==="tasks"&&L==="pending")T("pendingTasks",`${tf.apiBaseUrl}/tasks?status=pending&limit=100&summary=1`);else if(y==="tasks"&&(L==="history"||L==="results"))T("tasks",`${tf.apiBaseUrl}/tasks?limit=300&summary=1`);else if(Y)T("tasks",`${tf.apiBaseUrl}/tasks?limit=8&lite=1`),T("pendingTasks",`${tf.apiBaseUrl}/tasks?status=pending&limit=20&lite=1`);if(p)T("microservices",`${tf.apiBaseUrl}/microservices`);if(y==="ops"&&L==="events")T("events",`${tf.apiBaseUrl}/events?limit=100`);if(y==="ops"&&L==="logs")T("logs","/logs?limit=100");await Promise.all(S.map(async([n,_f])=>{let t=await _f,ff={};if(n==="overview")ff.overview=t;if(n==="nodes")ff.nodes=t.nodes||[];if(n==="systemStatuses")ff.systemStatuses=t.systemStatuses||[];if(n==="dockerStatuses")ff.dockerStatuses=t.dockerStatuses||[];if(n==="microservices")ff.microservices=t.microservices||[];if(n==="events")ff.events=t.events||[];if(n==="tasks")ff.tasks=t.tasks||[];if(n==="pendingTasks")ff.pendingTasks=t.tasks||[];if(n==="logs")ff.logs=t.logs||[];F((Gf)=>({...Gf,...ff}))})),U({ok:!0,text:"核心在线"}),W(new Date)}catch(S){if(U({ok:!1,text:Mf(S,"连接失败")}),S.status===401)u(!1)}finally{Z.current=!1}}p1(()=>{let S=()=>{if(!WH())return;P()};S();let T=setInterval(S,GS(y,L)),Y=()=>{if(WH())S()};return document.addEventListener("visibilitychange",Y),()=>{clearInterval(T),document.removeEventListener("visibilitychange",Y)}},[y,L]),p1(()=>{let S=setInterval(()=>q(new Date),1000);return()=>clearInterval(S)},[]),p1(()=>{let S=QG(mu,window.location.pathname);if(S&&window.location.pathname!==S)window.history.replaceState(null,"",S)},[]),p1(()=>{let S=()=>{let T=Dj(mu,window.location.pathname);$(T.moduleId),j((Y)=>({...Y,[T.moduleId]:T.tabId})),O(null)};return window.addEventListener("popstate",S),()=>window.removeEventListener("popstate",S)},[]),p1(()=>{window.scrollTo({top:0,left:0,behavior:"auto"})},[y,L]);function w(S,T,Y="push"){let R=mu.moduleById[S]?S:mu.fallbackTarget.moduleId,m=mu.moduleById[R]?.tabs.some((n)=>n.id===T)?T:m3[R]||mu.moduleById[R]?.tabs[0]?.id||mu.fallbackTarget.tabId;$(R),j((n)=>({...n,[R]:m}));let p=c6(mu,R,m);if(window.location.pathname!==p){let n=Y==="replace"?"replaceState":"pushState";window.history[n](null,"",p)}}function r(S,T){O({title:S,data:T})}return Q("div",{className:`shell ${G?"rail-collapsed":""}`,"data-testid":"app-shell"},Q(wS,{activeModule:y,activeTabs:l,onNavigate:w,collapsed:G,onToggle:()=>H((S)=>!S)}),Q("main",{className:"workspace"},Q(BS,{connection:A,lastRefresh:z,onRefresh:P,onLogout:()=>u(!0),session:f,clock:K,activeStatusItems:C}),Q(DS,{module:V,activeTab:L,onNavigate:w}),Q(Jr,{activeModule:y,activeTab:L,data:D,session:f,refresh:P,onRaw:r,onNavigate:w})),Q(LS,{raw:E,onClose:()=>O(null)}))}function Qr(){let[f,u]=hf(!0),[_,y]=hf(null);async function $(){u(!0);try{let j=await wf("/api/session");y(j.authenticated?j:null)}catch{y(null)}finally{u(!1)}}async function l(j){if(j)try{await wf("/logout",{method:"POST"})}catch{}y(null)}if(p1(()=>{$()},[]),f)return Q("main",{className:"loading-screen"},Q("div",{className:"brand-mark"},"UD"),Q("span",null,"加载会话"));if(!_)return Q(YS,{onLogin:y});return Q(Fr,{session:_,onLogout:l})}var bH=document.getElementById("root");if(bH===null)throw Error("root element not found");OH.createRoot(bH).render(Q(Qr));})(); + ${P} + ${B} + ${M} + `,width:H,height:O}}function a5(f,u){let _=URL.createObjectURL(f),y=document.createElement("a");y.href=_,y.download=u,y.click(),setTimeout(()=>URL.revokeObjectURL(_),1000)}async function nq(f,u){let _=gq(u,"pipeline"),{svg:y,width:l,height:$}=Er(f,u),j=new Blob([y],{type:"image/svg+xml;charset=utf-8"}),J=URL.createObjectURL(j);try{let F=new Image;await new Promise((W,K)=>{F.onload=()=>W(),F.onerror=()=>K(Error("svg image load failed")),F.src=J});let A=document.createElement("canvas");A.width=l,A.height=$;let U=A.getContext("2d");if(!U)throw Error("canvas unavailable");U.drawImage(F,0,0);let G=await new Promise((W)=>A.toBlob(W,"image/png"));if(!G)throw Error("png export failed");a5(G,`${_}.png`)}catch{a5(j,`${_}.svg`)}finally{URL.revokeObjectURL(J)}}async function Nr(f){let u=gq(String(f?.title||"pipeline-gantt"),"pipeline-gantt"),{svg:_,width:y,height:l}=Xr(f),$=new Blob([_],{type:"image/svg+xml;charset=utf-8"}),j=URL.createObjectURL($);try{let J=new Image;await new Promise((G,W)=>{J.onload=()=>G(),J.onerror=()=>W(Error("gantt svg image load failed")),J.src=j});let F=document.createElement("canvas");F.width=y,F.height=l;let A=F.getContext("2d");if(!A)throw Error("canvas unavailable");A.drawImage(J,0,0);let U=await new Promise((G)=>F.toBlob(G,"image/png"));if(!U)throw Error("gantt png export failed");a5(U,`${u}.png`)}catch{a5($,`${u}.svg`)}finally{URL.revokeObjectURL(j)}}async function Lr(f){for(let u of f){if(u.flow.nodes.length===0)continue;await nq(u.flow,u.title),await new Promise((_)=>setTimeout(_,750))}}function Dq(f,u){return f.find((_)=>String(_?.pipelineId||"")===u)||null}function wq(f){return Cf(f?.startedAt)??Cf(f?.artifact?.startedAt)??Cf(f?.request?.createdAt)??Cf(f?.updatedAt)??0}function Yr(f,u){return f.filter((_)=>String(_?.pipelineId||"")===u).slice().sort((_,y)=>wq(_)-wq(y)||String(_?.runId||"").localeCompare(String(y?.runId||"")))}function tF(f,u){let _=String(u?.runId||""),y=f.findIndex((j)=>String(j?.runId||"")===_),l=y>=0?y+1:f.length,$=String(u?.status||"--");return`Epoch ${l} / ${_||"--"} / ${$}`}function $1(f){return String(f?.procedureRunId||f?.runId||"")}function u2(f,u){let _=String(f?.nodeId||f?.request?.nodeId||"");if(_)return _;let y=$1(f),l=`${u}__`;if(y.startsWith(l))return y.slice(l.length).replace(/__\d+$/u,"");return""}function p5(f,u){let _=Xf(f?.artifact)?f.artifact:{},y=Xf(f?.request)?f.request:{};return D6(f?.startedAt,_.startedAt,y.createdAt,y.startedAt,f?.createdAt,f?.updatedAt,u?.startedAt,u?.request?.createdAt)}function k5(f,u){let _=String(f?.status?.status||f?.artifact?.status||f?.status||"").toLowerCase(),y=Xf(f?.artifact)?f.artifact:{},l=dF(_);return D6(f?.finishedAt,y.finishedAt,f?.completedAt,l?f?.updatedAt:void 0,l?y.updatedAt:void 0,l?u?.updatedAt:void 0)}function tq(f,u,_=Date.now()){let y=String(f?.runId||""),l=new Set(u.map(($)=>String($?.id||"")).filter(Boolean));return Vf(f?.procedureRuns).flatMap(($)=>{let j=u2($,y);if(!j)return[];let J=String($?.status?.status||$?.artifact?.status||$?.status||"unknown").toLowerCase(),F=p5($,f),A=Cf(F);if(A===null)return[];let U=k5($,f),G=Cf(U)??(dF(J)?Cf($?.updatedAt)??A+1000:_),W=Math.max(A+1000,G);return[{nodeId:j,knownNode:l.has(j),procedureRunId:$1($),status:J,startMs:A,endMs:W,startedAt:L6(A),finishedAt:L6(W),durationMs:W-A,runId:y,raw:$}]}).sort(($,j)=>$.startMs-j.startMs||$.endMs-j.endMs||$.nodeId.localeCompare(j.nodeId))}function Br(f,u,_=[]){let y=u.map((U)=>Number(U.startMs)).filter(Number.isFinite),l=u.map((U)=>Number(U.endMs)).filter(Number.isFinite);for(let U of _){let G=V0(U?.eventMs??U?.ms);if(G!==null)y.push(G),l.push(G)}let $=Cf(f?.startedAt)??Cf(f?.artifact?.startedAt)??Cf(f?.request?.createdAt),j=Cf(f?.finishedAt)??Cf(f?.artifact?.finishedAt)??Cf(f?.updatedAt);if($!==null)y.push($);if(j!==null)l.push(j);let J=Date.now(),F=y.length>0?Math.min(...y):J-60000,A=Math.max(F+60000,l.length>0?Math.max(...l):J);return{startMs:F,endMs:A,durationMs:A-F}}var m5=12,sq=20,sF=100,Dr=!1;function _y(f){let u=Number(f);if(!Number.isFinite(u))return 0;return Math.max(0,Math.min(100,Math.round(u*100)/100))}function wr(f){let u=Math.max(m5,Number(f||m5)),_=Math.log(u/m5)/Math.log(sq);return _y(_*100)}var B6=wr(sF);function lQ(f){let u=_y(f)/100,_=m5*Math.pow(sq,u),y=u<0.24?"全局":u<0.64?"均衡":"细节";return{value:_y(u*100),pxPerMinute:_,label:y}}function pF(f){let u=Math.round(Number(f));return Math.abs(u-sF)<=1?sF:u}function Tr(f,u=B6){let _=Math.max(1,Number(f.durationMs||0)/60000),y=lQ(u);return Math.round(Math.max(360,Math.min(7200,_*Number(y.pxPerMinute||48))))}function rr(f,u=7){let _=Math.max(1,Number(f.endMs||0)-Number(f.startMs||0));return Array.from({length:u},(y,l)=>{let $=u===1?0:l/(u-1);return{ms:Number(f.startMs)+_*$,percent:$*100}})}function Mr(f,u){let _=Math.max(1,Number(u.endMs)-Number(u.startMs));return Math.max(0,Math.min(100,(f-Number(u.startMs))/_*100))}function V0(f){let u=Number(f);return Number.isFinite(u)?u:null}function $Q(f){return Rq(f?.status)&&!dF(f?.status)}function oq(f,u,_,y){let l=Math.max(1,_-u),$=Math.max(0,Math.min(1,(f-u)/l));return Number(($*y).toFixed(3))}function Tq(f,u){if(!u)return null;let _=V0(u?.startMs),y=V0(u?.endMs),l=V0(u?.chartHeight);if(_===null||y===null||l===null)return null;return oq(f,_,y,l)}function aq(f,u){let _=V0(f?.rawStartMs??f?.startMs)??V0(f?.startMs)??u,y=V0(f?.endMs)??_+1000;if(!$Q(f))return Math.max(_+1000,y);return Math.max(_+1000,y,u)}function Pr(f,u,_,y){let l=V0(f?.startMs)??y-60000,$=V0(f?.endMs)??y,j=_.reduce((E,H)=>Math.max(E,aq(H,y)),$),J=Math.max(l+60000,$,j),F=Math.max(1,J-l),A={startMs:l,endMs:J,durationMs:F},U=Tr(A,u),G=lQ(u),W=Math.max(5,Math.min(18,Math.round(U/150))),K=rr(A,W).map((E)=>{let H=Number(E.ms),O=oq(H,l,J,U);return{...E,y:O,timestamp:L6(H),offsetMs:H-l}});return{source:"frontend-y",startMs:l,endMs:J,durationMs:F,chartHeight:U,scale:_y(u),normalizedScale:Number((_y(u)/100).toFixed(3)),pxPerMinute:Number(Number(G.pxPerMinute||0).toFixed(3)),ticks:K}}function Sr(f,u,_){if(!$Q(f))return f;let y=V0(f?.rawStartMs??f?.startMs)??V0(f?.startMs)??_,l=aq(f,_),$=Tq(y,u),j=Tq(l,u),J=V0($??f?.y1??f?.startY)??0,F=V0(j??f?.y2??f?.endY)??J+10,A=Math.max(24,F-J);return{...f,live:!0,startMs:y,endMs:l,durationMs:Math.max(1000,l-y),finishedAt:L6(l),y1:J,y2:F,startY:J,endY:F,height:A}}function jQ(f,u,_){return Mr(f,u)/100*_}function G3(f){return Boolean(f&&String(f?.source||"")!=="frontend-y")}function dq(f,u,_,y,l){if(G3(y))for(let j of l){let J=V0(f?.[j]);if(J!==null)return J}let $=V0(f?.ms??f?.eventMs??f?.startMs);return jQ($??Number(u.startMs),u,_)}function d5(f,u,_,y){return dq(f,u,_,y,["y1","startY"])}function oF(f,u,_,y){if(G3(y)){let $=V0(f?.y2??f?.endY);if($!==null)return $}let l=V0(f?.endMs)??Number(u.endMs);return jQ(l,u,_)}function eq(f,u,_,y){if(G3(y)){let $=V0(f?.height);if($!==null)return Math.max(1,$)}let l=f?.live?24:10;return Math.max(l,oF(f,u,_,y)-d5(f,u,_,y))}function cu(f,u,_,y){return dq(f,u,_,y,["y","timeAxisY"])}function fE(f,u,_,y){if(G3(y)||String(y?.source||"")==="frontend-y"){let j=V0(f?.y);if(j!==null)return j}let l=V0(f?.percent);if(l!==null)return l/100*_;let $=V0(f?.ms)??Number(u.startMs);return jQ($,u,_)}function Cr(f){let u=String(f?.promptEvent||f?.raw?.promptEvent||f?.event||"").toLowerCase();if(!["node-long-running-observation","node-finished"].includes(u))return"";let _=String(f?.sourceNodeId||f?.raw?.sourceNodeId||f?.raw?.detail?.nodeId||""),y=String(f?.nodeId||f?.targetNodeId||"");return _&&_!==y?_:""}function Rr(f,u){let _=new Set(u.map((l)=>[String(l.sourceNodeId||""),String(l.targetNodeId||""),String(l.targetMarkerId||""),String(l.action||"")].join(":"))),y=[...u];for(let l of f){let $=Cr(l),j=String(l?.nodeId||""),J=String(l?.id||"");if(!$||!j||!J)continue;let F=[$,j,J,"observe"].join(":");if(_.has(F))continue;_.add(F),y.push({id:`observation-arrow:${J}:${$}:${j}`,commandId:String(l?.commandId||l?.eventId||J),sourceNodeId:$,targetNodeId:j,sourceMarkerId:"",targetMarkerId:J,sourceKind:"monitor",action:"observe",status:"observation"})}return{markers:f,arrows:y}}function rq(f,u=""){let _=V1(f)||u,y=String(f?.promptEvent||"");if(_==="initial-prompt-delivered")return"initial";if(y==="node-finished"||y==="node-long-running-observation"||y.startsWith("monitor-"))return"monitor";if(_==="monitor-prompt-delivered"||String(f?.sourceKind||"").toLowerCase()==="monitor"||u==="monitor-prompt-queued")return"monitor";return"append"}function xr(f){return Vf(f?.tags||f?.raw?.tags).map((u)=>String(u||"")).filter(Boolean)}function Mq(f,u=""){let _=V1(f)||u,y=String(f?.promptEvent||"");if(_==="initial-prompt-delivered")return"初始 prompt";if(y==="node-long-running-observation")return"长任务观察";if(y==="node-finished")return xr(f).includes("monitor.audit")?"节点完成 / OA 审核":"节点完成";if(y==="monitor-interval")return"旧版轮询";if(y==="monitor-start")return"Monitor start";if(y==="monitor-stop")return"Monitor stop";if(_==="monitor-prompt-delivered"||u==="monitor-prompt-queued")return"Monitor prompt";if(_==="append-prompt-queued")return"追加 prompt 已排队";return"追加 prompt"}function Pq(f){let u=V1(f);if(u==="control-command-applied")return 3;if(u==="control-command-ignored")return 2;if(u==="control-command-queued")return 1;return 0}function Sq(f,u){let _=String(f?.commandId||"");if(_)return`command:${_}`;return["fallback",gy(f)||D6(f?.createdAt,f?.timestamp)||`index-${u}`,String(f?.sourceKind||""),String(f?.sourceNodeId||""),String(f?.targetNodeId||""),ny(f)].join(":")}function vr(f){return gF([f?.targetNodeId,...Vf(f?.resetNodeIds)])}function br(f,u){let _=X6(f),y=V1(f),l=String(f?.targetNodeId||""),$=Boolean(l)&&u!==l;if(y==="control-command-applied")return $?`${_} 波及`:`${_} 生效`;if(y==="control-command-ignored")return`${_} 忽略`;if(y==="control-command-queued")return`${_} 已发起`;return $?`${_} 波及`:_}function hr(f){if(V1(f)==="control-command-ignored")return"ignored";let _=ny(f);if(_==="restart"||_==="redo")return"restart";if(_==="modify")return"modify";if(_==="approve")return"approve";if(_==="guide")return"guide";return"pending"}function Ir(f){let u=String(f?.sourceKind||"").toLowerCase();if(u==="monitor")return"monitor";if(u==="webui")return"webui";if(u==="cli")return"cli";return"system"}function cr(f,u,_,y){let l=f.filter((A)=>String(A.nodeId||"")===u).sort((A,U)=>Number(A.startMs)-Number(U.startMs)),$=l.find((A)=>_>=Number(A.startMs)-1000&&_<=Number(A.endMs)+1000);if($)return{ms:_,onInterval:!0,snapReason:"inside-interval",procedureRunId:String($.procedureRunId||"")};let j=ny(y),J=l.slice().reverse().find((A)=>Number(A.endMs)<=_+1000);if(J&&j==="approve")return{ms:Number(J.endMs),onInterval:!0,snapReason:"previous-interval-end",procedureRunId:String(J.procedureRunId||"")};let F=l.find((A)=>Number(A.startMs)>=_-1000);if(F&&["guide","modify","restart","redo"].includes(j))return{ms:Number(F.startMs),onInterval:!0,snapReason:"next-interval-start",procedureRunId:String(F.procedureRunId||"")};return{ms:_,onInterval:!1,snapReason:"event-time",procedureRunId:String(y?.procedureRunId||"")}}function uE(f,u,_,y){let l=Math.hypot(_-f,y-u),$=l>Wq?Wq:0,j=$>0?_-(_-f)/l*$:_,J=$>0?y-(y-u)/l*$:y,F=j-f,A=Math.max(16,Math.min(42,Math.abs(F)*0.45+12)),U=F===0?1:Math.sign(F);return`M ${f},${u} C ${f+U*A},${u} ${j-U*A},${J} ${j},${J}`}function pr(f,u){let _=String(f?.runId||u?.runId||""),y=tq({...Xf(u)?u:{},...Xf(f)?f:{},runId:_,procedureRuns:Vf(f?.procedureRuns).length>0?f.procedureRuns:u?.procedureRuns},[]),l=[],$=[],j=[],J=new Set,F=new Map,A=(W,K)=>{if(!W.nodeId||!Number.isFinite(Number(W.ms)))return;if(J.has(W.id))return;J.add(W.id),K.push(W)};for(let W of Vf(f?.procedureRuns)){let K=u2(W,_),E=$1(W);if(!K)continue;for(let H of Vf(W?.attempts)){let O=f2(H),z=new Set,q=new Set;for(let V of O6(H?.controlEventRecords)){let L=V1(V);if(!["initial-prompt-delivered","append-prompt-delivered","monitor-prompt-delivered"].includes(L))continue;let r=gy(V),N=Cf(r);if(N===null)continue;let D=String(V?.eventId||"");if(D)z.add(D);q.add(`${L}:${r}:${String(V?.sourceKind||"")}:${String(V?.promptPreview||"")}`),A({id:`prompt:${D||`${E}:${O}:${L}:${N}`}`,runId:_,nodeId:K,procedureRunId:E,attempt:O,kind:"prompt",tone:rq(V,L),status:"delivered",label:Mq(V,L),ms:N,timestampIso:r,sourceKind:String(V?.sourceKind||""),sourceNodeId:String(V?.sourceNodeId||""),targetNodeId:K,action:"",eventId:D,commandId:String(V?.commandId||""),raw:V},l)}let Z=[{records:O6(H?.controlPromptRecords),fallbackKind:"append-prompt-queued"},{records:O6(H?.monitorPromptRecords),fallbackKind:"monitor-prompt-queued"}];for(let V of Z)for(let L of V.records){let r=gy(L),N=Cf(r);if(N===null)continue;let D=String(L?.eventId||"");if(D&&z.has(D))continue;let c=`${V.fallbackKind==="monitor-prompt-queued"?"monitor-prompt-delivered":"append-prompt-delivered"}:${r}:${String(L?.sourceKind||"")}:${String(L?.promptPreview||"")}`;if(q.has(c))continue;A({id:`prompt-fallback:${D||`${E}:${O}:${V.fallbackKind}:${N}`}`,runId:_,nodeId:K,procedureRunId:E,attempt:O,kind:"prompt",tone:rq(L,V.fallbackKind),status:"queued",label:Mq(L,V.fallbackKind),ms:N,timestampIso:r,sourceKind:String(L?.sourceKind||""),sourceNodeId:String(L?.sourceNodeId||""),targetNodeId:K,action:"",eventId:D,commandId:String(L?.commandId||""),raw:L},l)}}}let U=new Map;O6(f?.controlEvents).forEach((W,K)=>{let E=Sq(W,K),H=U.get(E)||{key:E,events:[],commands:[]};H.events.push(W),U.set(E,H)}),Vf(f?.controlCommands).filter(Xf).forEach((W,K)=>{let E=Sq(W,K),H=U.get(E)||{key:E,events:[],commands:[]};H.commands.push(W),U.set(E,H)});for(let W of U.values()){let K=Vf(W.events).slice().sort((C,S)=>Pq(S)-Pq(C)),E=Vf(W.commands),H=Vf(W.events).find((C)=>V1(C)==="control-command-queued")||E[0]||null,O=K[0]||E[0]||H;if(!H&&!O)continue;let z=String(H?.sourceNodeId||O?.sourceNodeId||""),q=String(H?.sourceKind||O?.sourceKind||""),Z=gy(H)||gy(O)||D6(H?.createdAt,O?.createdAt),V=Cf(Z),L=String(O?.commandId||H?.commandId||W.key),r=(V1(O)||"control-command-queued").replace(/^control-command-/u,""),N="";if(z&&V!==null)N=`control-source:${L}:${z}`,F.set(L,N),A({id:N,runId:_,nodeId:z,procedureRunId:String(H?.procedureRunId||O?.procedureRunId||""),attempt:"",kind:"control-source",tone:Ir(H||O),status:r,label:`${X6(H||O)} 发起`,ms:V,timestampIso:Z,action:ny(H||O),sourceKind:q,sourceNodeId:z,targetNodeId:String(O?.targetNodeId||H?.targetNodeId||""),commandId:L,raw:H||O},$);let D=O||H,x=gy(D)||Z,c=Cf(x);if(c===null)continue;let v=vr(D);for(let C of v){let S=cr(y,C,c,D),B=`control-target:${L}:${C}`;if(A({id:B,runId:_,nodeId:C,procedureRunId:S.procedureRunId,attempt:"",kind:"control-target",tone:hr(D),status:r,label:br(D,C),ms:S.ms,eventMs:c,onInterval:S.onInterval,snapReason:S.snapReason,snapped:Number(S.ms)!==c,timestampIso:x,renderedTimestampIso:L6(Number(S.ms)),action:ny(D),sourceKind:q,sourceNodeId:z,targetNodeId:C,commandId:L,raw:D},$),N&&z&&z!==C)j.push({id:`control-arrow:${L}:${z}:${C}`,commandId:L,sourceNodeId:z,targetNodeId:C,sourceMarkerId:N,targetMarkerId:B,sourceKind:q,action:ny(D),status:r})}}let G=[...l,...$].sort((W,K)=>Number(W.ms)-Number(K.ms)||String(W.nodeId).localeCompare(String(K.nodeId))||String(W.id).localeCompare(String(K.id)));return{...Rr(G,j),sourceMarkerByCommand:F}}function kr({details:f,selectedNodeId:u,selectedNodeRuntime:_,control:y,onRaw:l}){if(!f)return X("span",{className:"muted"},"点击“抓取过程”读取 node 运行材料;主界面只显示结构化摘要,完整内容需点开原始 JSON。");let $=Vf(f.procedureRuns),j=$.at(-1)||{},J=Vf(j.attempts),F=J.at(-1)||{},A=Vf(j.workerLogTail),U=Vf(F.controlEventsTail),G=Vf(F.controlPromptsTail),W=Vf(F.monitorPromptsTail),K=bF(U),E=bF(G),H=bF(W),O=F.opencodeMessages||{};return X("div",{className:"pipeline-evidence-list compact"},X(y1,{title:"Node runtime",subtitle:u||"--",facts:[`status ${_?.status||"pending"}`,`attempts ${_?.attempts??J.length}`,`procedure ${_?.currentProcedureRunId||$1(j)||"--"}`,y.fetchedAt?`fetched ${L0(y.fetchedAt)}`:"not fetched"],data:f.node||f,onRaw:l,testId:"raw-pipeline-node-runtime"}),X(y1,{title:"Procedure runs",subtitle:`${$.length} groups`,facts:[`latest ${j.status?.status||j.status||"--"}`,`steps ${Vf(j.recentSteps).length}`,`duration ${l1(Cf(j.finishedAt)&&Cf(j.startedAt)?Number(Cf(j.finishedAt))-Number(Cf(j.startedAt)):j.durationMs)}`],data:$,onRaw:l,testId:"raw-pipeline-node-procedures"}),X(y1,{title:"OpenCode messages",subtitle:String(O.exists?"available":"not indexed"),facts:[`messages ${g5(O.messageCount)}`,`size ${g5(O.size)}`,`updated ${zf(O.updatedAt)}`],data:O,onRaw:l,testId:"raw-pipeline-node-messages"}),X(y1,{title:"Control prompts",subtitle:"manual / monitor append queues",facts:[`manual tail ${E.total}`,`monitor tail ${H.total}`,`last ${zf(aF(E.lastAt,H.lastAt))}`],data:{controlPromptsTail:G,monitorPromptsTail:W},onRaw:l,testId:"raw-pipeline-node-prompts"}),X(y1,{title:"Control events",subtitle:K.eventKinds.length>0?K.eventKinds.join(", "):"event tail",facts:[`tail ${K.total}`,`parsed ${K.parsed}`,`last ${zf(K.lastAt)}`],data:U,onRaw:l,testId:"raw-pipeline-node-events"}),X(y1,{title:"Worker log",subtitle:"tail is hidden on main canvas",facts:[`tail ${A.length} lines`,"raw only via button",`procedure ${$1(j)||"--"}`],data:A,onRaw:l,testId:"raw-pipeline-node-worker-log"}))}function mr({activeRun:f,onRaw:u}){if(!f)return X(pu,{title:"暂无运行材料",text:"没有 Pipeline epoch 时不会展示运行材料索引。"});let _=Vf(f.nodes),y=Vf(f.procedureRuns),l=Vf(f.submissions),$=Vf(f.workerLogTail),j=Kq(_),J=Kq(y),F=y.filter((U)=>String(U?.status||"").toLowerCase()==="failed"),A=aF(...y.flatMap((U)=>[U.updatedAt,U.finishedAt,U.startedAt]));return X("div",{className:"pipeline-evidence-list"},X(y1,{title:"Epoch overview",subtitle:f.runId||"--",facts:[`pipeline ${f.pipelineId||"--"}`,`status ${f.status||"--"}`,`started ${zf(f.startedAt)}`,`updated ${zf(f.updatedAt)}`],data:f,onRaw:u,testId:"raw-pipeline-run"}),X(y1,{title:"Node states",subtitle:`${_.length} nodes`,facts:[`running ${j.running||0}`,`succeeded ${j.succeeded||0}`,`failed ${j.failed||0}`,`pending ${j.pending||0}`],data:_,onRaw:u,testId:"raw-pipeline-run-nodes"}),X(y1,{title:"Procedure run index",subtitle:`${y.length} procedure records`,facts:[`succeeded ${J.succeeded||0}`,`failed ${J.failed||0}`,`latest ${zf(A)}`,`errors ${F.length}`],data:y,onRaw:u,testId:"raw-pipeline-run-procedures"}),X(y1,{title:"OA submissions",subtitle:`${l.length} submission files`,facts:[`records ${l.length}`,`task ${g5(f.task)}`,"raw grouped by run"],data:l,onRaw:u,testId:"raw-pipeline-run-submissions"}),X(y1,{title:"Worker log tail",subtitle:"hidden from main interface",facts:[`tail ${$.length} lines`,"display raw only after click",`updated ${zf(f.updatedAt)}`],data:$,onRaw:u,testId:"raw-pipeline-run-worker-log"}))}function ir({diagnostics:f,onRaw:u}){let _=Vf(f?.runs).filter(Xf),y=Vf(f?.forbiddenResiduals),l=Xf(f?.guarantees)?f.guarantees:{},$=f?.hasNeutralNodeFinishedEvidence===!0&&f?.hasNoAuditPolicyEvidence===!0&&f?.hasAuditPolicyEvidence===!0,j=f?.ok===!0&&$&&y.length===0,J=_[0]||null,F=[{label:"中性完成事实",ok:l.neutralNodeFinished===!0,hint:"node-finished 不携带流程策略"},{label:"Config 策略判定",ok:l.auditPolicyFromConfig===!0,hint:"OA backend 读取当前 epoch 配置"},{label:"控制命令来自 OA",ok:l.runnerConsumesControlCommandsFromOaEvents===!0,hint:"runner 只消费 OA control.command"},{label:"无独立审核事件",ok:l.noIndependentAuditRequestEvent===!0,hint:"审核由 node-finished + policy 派生"},{label:"无批次门禁",ok:l.noBatchFinishedControlGate===!0,hint:"下游启动由每个 node 完成驱动"}];return X("div",{className:"pipeline-oa-panel","data-testid":"pipeline-oa-event-flow-panel"},X("div",{className:"metric-grid compact"},X(Eu,{label:"OA Flow",value:j?"100%":"--",hint:String(f?.mode||"waiting diagnostics"),tone:j?"ok":"warn"}),X(Eu,{label:"禁止残留",value:y.length,hint:y.length===0?"source scan clean":"needs cleanup",tone:y.length===0?"ok":"warn"}),X(Eu,{label:"No-audit",value:f?.hasNoAuditPolicyEvidence?"OK":"--",hint:"OA 下游策略证据",tone:f?.hasNoAuditPolicyEvidence?"ok":"warn"}),X(Eu,{label:"Monitor 审核",value:f?.hasAuditPolicyEvidence?"OK":"--",hint:"OA 控制事件闭环",tone:f?.hasAuditPolicyEvidence?"ok":"warn"})),X("div",{className:"pipeline-oa-guarantees"},F.map((A)=>X("article",{key:A.label,className:`pipeline-oa-guarantee ${A.ok?"ok":"warn"}`},X(uy,{status:A.ok?"online":"warn"},A.ok?"OK":"MISS"),X("div",null,X("strong",null,A.label),X("span",null,A.hint))))),X("div",{className:"pipeline-evidence-list compact"},_.slice(0,6).map((A)=>X(y1,{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:u,testId:`raw-pipeline-oa-run-${String(A.runId||"run").replace(/[^a-zA-Z0-9_.-]+/g,"-")}`}))),J?X("p",{className:"muted paragraph"},`最新证据 ${J.runId}: ${J.nodeFinishedCount||0} 个 node-finished,${J.controlAppliedCount||0} 个控制结果。`):X(pu,{title:"暂无 OA 事件流证据",text:"等待 Pipeline backend 暴露 diagnostics。"}),f?X("div",{className:"panel-actions inline-actions"},X(O1,{title:"Pipeline OA Event Flow Diagnostics",data:f,onOpen:u,testId:"raw-pipeline-oa-event-flow"})):null)}function gr({quota:f,onRaw:u}){let _=Xf(f?.summary)?f.summary:{},y=Xf(f?.target)?f.target:{},l=Xf(f?.cache)?f.cache:{},$=f?.ok===!0,j=String(f?.modelId||_.modelName||y.modelName||"MiniMax-M2.7"),J=_.totalCount??y.currentIntervalTotalCount,F=_.usageCount??y.currentIntervalUsageCount,A=_.remainingCount??y.currentIntervalRemainingCount,U=_.remainingRatio??(Number.isFinite(Number(J))&&Number(J)>0&&Number.isFinite(Number(A))?Number(A)/Number(J):void 0),G=_.usageRatio??(Number.isFinite(Number(J))&&Number(J)>0&&Number.isFinite(Number(F))?Number(F)/Number(J):void 0),W=_.resetAt||y.endAt,K=_.remainsMs??y.remainsMs,E=Number(A),H=!$||Number.isFinite(E)&&E<=0?"warn":"ok",O=[$?`endpoint ${f?.endpoint||"--"}`:"quota unavailable",`fetched ${i5(f?.fetchedAt)}`,l.hit?`cache ${l1(l.ageMs)}`:"live quota"];return X("div",{className:"pipeline-minimax-quota-panel","data-testid":"pipeline-minimax-quota-panel"},X("div",{className:"metric-grid compact"},X(Eu,{label:"MiniMax",value:$?j:"--",hint:f?.modelComponent||f?.error||"model/minimax-m27",tone:H}),X(Eu,{label:"当前窗口",value:`${vF(F)}/${vF(J)}`,hint:`已用 ${zq(G)}`,tone:H}),X(Eu,{label:"剩余额度",value:vF(A),hint:`剩余 ${zq(U)}`,tone:H}),X(Eu,{label:"重置时间",value:i5(W),hint:K!==void 0?`约 ${l1(K)}`:zf(W),tone:H})),X(eF,{items:O}),$?X("p",{className:"muted paragraph"},`MiniMax 限额来自 D601 Pipeline 后端实时查询;当前模型匹配 ${_.modelName||y.modelName||j}。`):X(H0,{error:f?.error||"MiniMax 限额查询失败"}),f?X("div",{className:"panel-actions inline-actions"},X(O1,{title:"Pipeline MiniMax Quota",data:f,onOpen:u,testId:"raw-pipeline-minimax-quota"})):null)}function nr({epochs:f,activeRun:u,activePipeline:_,pipelineNodes:y,pipelineEdges:l,runDetails:$,nodeDetails:j,nodeDetailsState:J,ganttScale:F=B6,onGanttScaleChange:A,onRunChange:U,onIntervalSelect:G,onMarkerSelect:W,selection:K,detailOpen:E,onDetailOpenChange:H,onRaw:O}){let[z,q]=wu(Dr),[Z,V]=wu({startY:0,endY:0,startMs:0,endMs:0}),[L,r]=wu(Date.now()),N=e_(null),D=String(u?.runId||""),x=Boolean(E),c=(uf)=>{if(typeof H==="function")H(uf)},v=_y(F??B6),C=String($?.runId||"")===D?$?.details:null,S=C?{...Xf(u)?u:{},...Xf(C)?C:{},runId:D,procedureRuns:Vf(C?.procedureRuns).length>0?C.procedureRuns:u?.procedureRuns}:u,B=tq(S,y,L),P=C?pr(C,S):{markers:[],arrows:[]},M=Vf(P.markers),w=Br(S,B,M),Y=Pr(w,v,B,L),R=String(Y.source||"frontend-y"),k=B.map((uf)=>Sr(uf,Y,L)),p={startMs:Number(Y.startMs),endMs:Number(Y.endMs),durationMs:Math.max(1,Number(Y.durationMs??Number(Y.endMs)-Number(Y.startMs)))},n=lQ(v),_f={...n,pxPerMinute:Number(Y.pxPerMinute??n.pxPerMinute)},s=Math.round(Number(Y.chartHeight||360)),ff=B.some($Q);b1(()=>{if(!D||!ff)return;let uf=window.setInterval(()=>r(Date.now()),1000);return()=>window.clearInterval(uf)},[D,ff]);let Kf=Zr(_,y,Array.isArray(l)?l:[]),Gf=y.map((uf)=>String(uf?.id||"")).filter(Boolean),jf=k.map((uf)=>String(uf.nodeId||"")).filter(Boolean),Wf=M.map((uf)=>String(uf.nodeId||"")).filter(Boolean),Of=Array.from(new Set([...Kf,...Gf,...jf,...Wf])),Zf={startY:0,endY:s,startMs:Number(p.startMs),endMs:Number(p.endMs)},h=Number(Z?.endY||0)>0?Z:Zf,i=(uf)=>{return d5(uf,p,s,Y)<=Number(h.endY)&&oF(uf,p,s,Y)>=Number(h.startY)},I=(uf)=>{let vf=cu(uf,p,s,Y);return vf>=Number(h.startY)&&vf<=Number(h.endY)},lf=new Set(Of.filter((uf)=>k.some((vf)=>vf.nodeId===uf&&i(vf))||M.some((vf)=>vf.nodeId===uf&&I(vf)))),$f=z?Of.filter((uf)=>lf.has(uf)):Of,Af=`${RF}px ${$f.length>0?$f.map(()=>`${x1}px`).join(" "):"minmax(160px, 1fr)"}`,Yf=Vf(Y.ticks).filter(Xf),xf=String(K?.mode==="interval"?K?.interval?.procedureRunId||"":""),of=String(K?.mode==="event"?K?.marker?.id||"":""),F0=()=>{let uf=N.current;if(!uf){V(Zf);return}let vf=Math.max(0,uf.scrollTop-xF),o0=Math.max(120,uf.clientHeight-xF),Bf=Math.min(s,vf+o0),b0={startY:vf,endY:Bf,startMs:Number(p.startMs),endMs:Number(p.endMs)},i0=Math.max(0,Math.min(1,vf/s)),a0=Math.max(i0,Math.min(1,Bf/s)),nf=Math.max(1,Number(p.endMs)-Number(p.startMs));b0.startMs=Number(p.startMs)+nf*i0,b0.endMs=Number(p.startMs)+nf*a0,V(b0)};b1(()=>{let uf=N.current,vf=window.setTimeout(F0,0);return uf?.addEventListener("scroll",F0),window.addEventListener("resize",F0),()=>{window.clearTimeout(vf),uf?.removeEventListener("scroll",F0),window.removeEventListener("resize",F0)}},[D,p.startMs,p.endMs,s]);let y0=Math.max(0,Of.length-$f.length),T0=new Set(M.filter((uf)=>$f.includes(String(uf.nodeId||""))&&I(uf)).map((uf)=>String(uf.id))),Qu=new Map(M.map((uf)=>[String(uf.id),uf])),X0=Vf(P.arrows).filter((uf)=>{if(!T0.has(String(uf.targetMarkerId||"")))return!1;if(String(uf.action||"")==="observe")return $f.includes(String(uf.sourceNodeId||""));return T0.has(String(uf.sourceMarkerId||""))}),v0=RF+Math.max(1,$f.length)*x1,iu=(uf)=>{let vf=_y(uf.target.value);if(typeof A==="function")A(vf);window.setTimeout(F0,0)},K0=()=>Nr({title:`${_?.id||"pipeline"}-${D||"epoch"}-gantt`,meta:[`run ${D||"--"}`,`${zf(p.startMs)} -> ${zf(p.endMs)}`,`duration ${l1(p.durationMs)}`,`${_f.label} / ${pF(_f.pxPerMinute)} px/min`,`${$f.length}/${Of.length} nodes`,`${M.length} markers`],visibleNodeIds:$f,intervals:k,markers:M.filter((uf)=>$f.includes(String(uf.nodeId||""))),arrows:X0,ticks:Yf,bounds:p,chartHeight:s,backendLayout:Y}),Au=Xf(C?.gantt?.diagnostics)?C.gantt.diagnostics:null;return X(v1,{title:"Epoch 甘特图",eyebrow:`${_?.id||"pipeline"} / ${f.length} epochs`,className:"pipeline-wide-panel",actions:X("div",{className:"pipeline-gantt-actions"},X("select",{value:D,disabled:f.length===0,onChange:(uf)=>U(uf.target.value),"data-testid":"pipeline-epoch-select"},f.map((uf)=>X("option",{key:uf.runId,value:uf.runId},tF(f,uf)))),X("label",{className:"pipeline-gantt-toggle"},X("input",{type:"checkbox","data-testid":"pipeline-gantt-auto-hide-idle",checked:z,onChange:(uf)=>{q(Boolean(uf.target.checked)),window.setTimeout(F0,0)}}),X("span",null,"自动隐藏空闲列")),X("label",{className:"pipeline-gantt-scale"},X("span",null,X("b",null,"时间尺度"),X("em",{"data-testid":"pipeline-gantt-scale-label"},`${_f.label} · ${pF(_f.pxPerMinute)} px/min`)),X("input",{type:"range",min:0,max:100,step:0.01,value:v,onChange:iu,"aria-label":"调整甘特图时间尺度","data-testid":"pipeline-gantt-time-scale"}),X("small",null,X("span",null,"全局"),X("span",null,"细节"))),u?X("button",{type:"button",className:"ghost-btn",onClick:K0,disabled:$f.length===0,"data-testid":"pipeline-export-gantt"},"导出甘特图"):null,u?X(O1,{title:`Pipeline Epoch ${u.runId}`,data:u,onOpen:O,testId:"raw-pipeline-epoch-gantt"}):null)},!u?X(pu,{title:"暂无 Epoch",text:"当前 pipeline 还没有完整运行记录。"}):k.length===0?X(pu,{title:"暂无时间区间",text:"等待 D601 Pipeline backend 在 procedure summary 中返回 startedAt / finishedAt。"}):X("div",{className:"pipeline-gantt-wrap"},X("div",{className:`pipeline-gantt-detail-layout ${x?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-gantt-detail-layout","data-sidebar-open":x?"true":"false"},X("div",{className:"pipeline-gantt-main"},X("div",{className:"pipeline-gantt-main-head"},X("div",{className:"pipeline-gantt-meta"},X("span",null,`time ${zf(p.startMs)} -> ${zf(p.endMs)}`),X("span",null,`duration ${l1(p.durationMs)}`),X("span",null,`scale ${_f.label} / ${pF(_f.pxPerMinute)} px/min`),X("span",null,`layout ${R}`),Au?X("span",null,`align ${Au.timeAxisAlignmentOk===!1?"check":"ok"}`):null,X("span",null,`visible ${$f.length}/${Of.length} nodes`),C?X("span",null,`markers ${M.length}`):null,z&&y0>0?X("span",null,`hidden idle ${y0}`):null),!x?X("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!K?.mode,onClick:()=>c(!0),"data-testid":"pipeline-gantt-sidebar-toggle"},K?.mode?"展开详情":"点击甘特图元素展开详情"):null),X("div",{className:"pipeline-gantt-viewport",ref:N,"data-testid":"pipeline-epoch-gantt","data-pipeline-id":_?.id||"","data-run-id":D,"data-layout-source":R,"data-start-ms":String(p.startMs),"data-end-ms":String(p.endMs),"data-chart-height":String(s)},X("div",{className:"pipeline-gantt-board",style:{gridTemplateColumns:Af,minWidth:`${v0}px`}},X("div",{className:"pipeline-gantt-head time"},"Time"),$f.length===0?X("div",{className:"pipeline-gantt-head empty"},"当前时间窗无工作节点"):$f.map((uf)=>X("div",{key:`head-${uf}`,className:"pipeline-gantt-head node",title:uf,"data-testid":"pipeline-gantt-head-node","data-node-id":uf},X(aT,{value:uf}))),X("div",{className:"pipeline-gantt-time-axis",style:{height:`${s}px`}},Yf.map((uf)=>{let vf=fE(uf,p,s,Y);return X("div",{key:`tick-${uf.ms}-${vf}`,className:"pipeline-gantt-tick",style:{top:`${vf}px`},"data-testid":"pipeline-gantt-tick","data-ms":String(uf.ms),"data-y":String(vf)},X("b",null,zf(uf.ms)),X("span",null,`+${l1(Number(uf.offsetMs??Number(uf.ms)-Number(p.startMs)))}`))})),$f.length>0?X("svg",{className:"pipeline-gantt-arrow-layer",width:$f.length*x1,height:s,viewBox:`0 0 ${$f.length*x1} ${s}`,style:{left:`${RF}px`,top:`${xF}px`,width:`${$f.length*x1}px`,height:`${s}px`},"aria-hidden":"true"},X("defs",null,X("marker",{id:"pipeline-gantt-arrowhead",viewBox:"0 0 10 10",refX:9,refY:5,markerWidth:6,markerHeight:6,orient:"auto-start-reverse"},X("path",{d:"M 0 0 L 10 5 L 0 10 z",fill:"context-stroke"}))),X0.map((uf)=>{let vf=Qu.get(String(uf.targetMarkerId||""));if(!vf)return null;let o0=Qu.get(String(uf.sourceMarkerId||"")),Bf=String(o0?.nodeId||uf.sourceNodeId||""),b0=$f.indexOf(Bf),i0=$f.indexOf(String(vf.nodeId||""));if(b0<0||i0<0)return null;let a0=b0*x1+x1/2,nf=i0*x1+x1/2,d0=o0?cu(o0,p,s,Y):cu(vf,p,s,Y),Hu=cu(vf,p,s,Y);return X("path",{key:uf.id,className:`pipeline-gantt-arrow ${String(uf.sourceKind||"").toLowerCase()} ${String(uf.status||"").toLowerCase()} ${String(uf.action||"").toLowerCase()}`,d:uE(a0,d0,nf,Hu),markerEnd:"url(#pipeline-gantt-arrowhead)","data-testid":String(uf.action||"")==="observe"?"pipeline-gantt-observation-arrow":"pipeline-gantt-arrow","data-source-node-id":String(uf.sourceNodeId||""),"data-target-node-id":String(uf.targetNodeId||""),"data-target-marker-id":String(uf.targetMarkerId||""),"data-action":String(uf.action||""),"data-source-y":String(d0),"data-target-y":String(Hu)})})):null,$f.length===0?X("div",{className:"pipeline-gantt-empty-col",style:{height:`${s}px`}},"滚动到有活动的时间段后,相关 node 列会自动出现。"):$f.map((uf)=>{let vf=k.filter((Bf)=>Bf.nodeId===uf),o0=M.filter((Bf)=>String(Bf.nodeId||"")===uf);return X("div",{key:`col-${uf}`,className:"pipeline-gantt-node-col",style:{height:`${s}px`}},vf.map((Bf)=>{let b0=d5(Bf,p,s,Y),i0=oF(Bf,p,s,Y),a0=eq(Bf,p,s,Y),nf=String(Bf.procedureRunId||`${uf}-${Bf.startMs}`);return X("button",{key:nf,type:"button",className:`pipeline-gantt-bar ${Bf.status} ${Bf.live?"live":""} ${xf===nf?"selected":""}`,style:{top:`${b0}px`,height:`${a0}px`},title:`${uf} ${Bf.status} ${zf(Bf.startedAt||Bf.startMs)} -> ${zf(Bf.finishedAt||Bf.endMs)}`,onClick:()=>G(Bf),"data-testid":"pipeline-gantt-line","data-node-id":uf,"data-procedure-run-id":String(Bf.procedureRunId||""),"data-status":String(Bf.status||""),"data-live":Bf.live?"true":"false","data-start-ms":String(Bf.startMs||""),"data-end-ms":String(Bf.endMs||""),"data-y1":String(b0),"data-y2":String(i0),"data-natural-height":String(Math.max(0,i0-b0))},X("strong",null,Bf.status||"working"),X("span",null,l1(Bf.durationMs)))}),o0.map((Bf)=>X("button",{key:Bf.id,type:"button",className:`pipeline-gantt-marker ${Bf.kind} ${Bf.tone||""} ${Bf.status||""} ${of===String(Bf.id)?"selected":""}`,style:{top:`${cu(Bf,p,s,Y)}px`},title:`${Bf.label||"event"} / ${zf(Bf.timestampIso||Bf.timestamp||Bf.ms)}`,onClick:()=>W(Bf),"data-testid":Bf.kind==="prompt"?"pipeline-gantt-prompt-marker":"pipeline-gantt-control-marker","data-marker-id":String(Bf.id||""),"data-ms":String(Bf.ms??Bf.eventMs??""),"data-y":String(cu(Bf,p,s,Y))})))})))),x?X(oT,{selection:K,runDetails:$,nodeDetails:j,nodeDetailsState:J,onRaw:O,onCollapse:()=>c(!1)}):null)))}function $_(){return{loading:!1,actionLoading:"",error:"",message:"",details:null,fetchedAt:null,appendPrompt:"",guidePrompt:"",modifyPrompt:"",approveReason:"",redoReason:""}}function d_(){return{mode:"",runId:"",interval:null,marker:null}}function kF(){return{runId:"",loading:!1,error:"",details:null,fetchedAt:null}}function E6(f,u){return`${f}/microservices/pipeline/proxy${u}`}function tr({activeRun:f,pipelineRuns:u,selectedRunId:_,onRunChange:y,selectedNodeId:l,selectedNodeConfig:$,selectedNodeRuntime:j,control:J,onControlChange:F,onFetch:A,onAction:U,onRaw:G,onCollapse:W}){let K=String(f?.runId||""),E=String(j?.status||"pending"),H=!K||!l||J.loading||Boolean(J.actionLoading),O=(q)=>(Z)=>F({[q]:Z.target.value,error:"",message:""}),z=u.length>0?u:f?[f]:[];return X("aside",{className:"pipeline-node-control","data-testid":"pipeline-node-control"},X("div",{className:"pipeline-node-control-head"},X("div",null,X("p",{className:"panel-eyebrow"},"Manual Node Control"),X("h3",null,l||"点击控制图中的 node")),X("div",{className:"pipeline-node-control-head-actions"},l?X(uy,{status:E},E):X(uy,{status:"pending"},"idle"),X("button",{type:"button",className:"ghost-btn mini",onClick:W,"data-testid":"pipeline-node-sidebar-collapse"},"收起"))),X("div",{className:"pipeline-control-runbar"},X("label",null,X("span",null,"目标 run"),X("select",{value:K||_,disabled:z.length===0,onChange:(q)=>y(q.target.value),"data-testid":"pipeline-node-run-select"},z.map((q)=>X("option",{key:q.runId,value:q.runId},`${q.runId||"--"} / ${q.status||"--"}`)))),X("button",{type:"button",className:"ghost-btn",disabled:H,onClick:A,"data-testid":"pipeline-node-fetch"},J.loading?"抓取中":"抓取过程"),J.details?X(O1,{title:`Pipeline Node ${l}`,data:J.details,onOpen:G,testId:"raw-pipeline-node-control"}):null),X("div",{className:"pipeline-control-meta"},X("span",null,X("b",null,"kind"),String($?.kind||"--")),X("span",null,X("b",null,"procedure"),String(j?.currentProcedureRunId||"--")),X("span",null,X("b",null,"attempts"),String(j?.attempts??"--")),X("span",null,X("b",null,"updated"),zf(f?.updatedAt))),!l?X(pu,{title:"未选择 node",text:"点击 React Flow 控制图中的任意 node 后,可抓取执行过程、追加 prompt、下发引导、增量修改、审核通过或重做。"}):null,X(H0,{error:J.error,wide:!0}),J.message?X("div",{className:"form-success wide"},J.message):null,X("div",{className:"pipeline-control-actions"},X("label",null,X("span",null,"实时追加 prompt(仅 running node)"),X("textarea",{value:J.appendPrompt,onChange:O("appendPrompt"),placeholder:"让当前执行中的 agent 继续、补充检查或调整当前步骤...",rows:4,disabled:!l,"data-testid":"pipeline-node-append-input"}),X("button",{type:"button",className:"primary-btn compact",disabled:H||!String(J.appendPrompt||"").trim(),onClick:()=>U("append"),"data-testid":"pipeline-node-append-button"},J.actionLoading==="append"?"追加中":"追加到运行中 node")),X("label",null,X("span",null,"下次尝试引导 prompt"),X("textarea",{value:J.guidePrompt,onChange:O("guidePrompt"),placeholder:"给该 node 下一次 attempt 的执行提示;不会立即打断当前 session。",rows:4,disabled:!l,"data-testid":"pipeline-node-guide-input"}),X("button",{type:"button",className:"ghost-btn compact",disabled:H||!String(J.guidePrompt||"").trim(),onClick:()=>U("guide"),"data-testid":"pipeline-node-guide-button"},J.actionLoading==="guide"?"下发中":"下发 guide")),X("label",null,X("span",null,"完成后增量修改 prompt"),X("textarea",{value:J.modifyPrompt,onChange:O("modifyPrompt"),placeholder:"在该 node 已完成结果基础上追加修改要求;runner 会重跑目标 node,并保留同 node 既有 OA 输出作为上下文。",rows:4,disabled:!l,"data-testid":"pipeline-node-modify-input"}),X("button",{type:"button",className:"ghost-btn compact",disabled:H||!String(J.modifyPrompt||"").trim(),onClick:()=>U("modify"),"data-testid":"pipeline-node-modify-button"},J.actionLoading==="modify"?"排队中":"增量修改 node")),X("label",null,X("span",null,"Monitor 审核通过原因"),X("textarea",{value:J.approveReason,onChange:O("approveReason"),placeholder:"当流程配置开启 monitor 审核时,记录审核通过原因并释放后续 node。",rows:3,disabled:!l,"data-testid":"pipeline-node-approve-input"}),X("button",{type:"button",className:"primary-btn compact",disabled:H||!String(J.approveReason||"").trim(),onClick:()=>U("approve"),"data-testid":"pipeline-node-approve-button"},J.actionLoading==="approve"?"提交中":"审核通过")),X("label",null,X("span",null,"重做 / restart 原因"),X("textarea",{value:J.redoReason,onChange:O("redoReason"),placeholder:"说明为什么需要重做;runner 会重置目标 node 以及非 rework 下游 node。",rows:4,disabled:!l,"data-testid":"pipeline-node-redo-input"}),X("button",{type:"button",className:"danger-btn compact",disabled:H||!String(J.redoReason||"").trim(),onClick:()=>U("redo"),"data-testid":"pipeline-node-redo-button"},J.actionLoading==="redo"?"排队中":"重做 node"))),X("div",{className:"pipeline-control-evidence"},X("strong",null,"Node 过程索引"),X(kr,{details:J.details,selectedNodeId:l,selectedNodeRuntime:j,control:J,onRaw:G})))}function _E({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((t)=>t.id==="pipeline")||null,[l,$]=wu({loading:!1,error:"",health:null,snapshot:null,oaDiagnostics:null,minimaxQuota:null,refreshedAt:null}),[j,J]=wu(""),[F,A]=wu(""),[U,G]=wu(""),[W,K]=wu($_()),[E,H]=wu({}),[O,z]=wu(d_()),[q,Z]=wu(kF()),[V,L]=wu(B6),[r,N]=wu(!1),[D,x]=wu(!1),c=e_(0),v=e_(!1),C=e_(0),S=e_(""),B=e_({}),P=e_(""),M=e_("");async function w(t={}){let Hf=t.silent===!0;if(!y)return;if(v.current)return;v.current=!0;let Df=c.current+1;if(c.current=Df,!Hf)$((If)=>({...If,loading:!0,error:""}));try{let If=`__unideskArrayLimit=registry.components:80,runs:${ST}`,[Rf,Q0,af]=await Promise.all([a_(`${_}/microservices/pipeline/proxy/api/snapshot?${If}`,{cache:"no-store"}),a_(`${_}/microservices/pipeline/proxy/api/oa-event-flow/diagnostics`,{cache:"no-store"}).catch((e0)=>({ok:!1,error:Pf(e0,"OA event flow diagnostics failed")})),a_(`${_}/microservices/pipeline/proxy/api/model-quota/minimax`,{cache:"no-store"}).catch((e0)=>({ok:!1,error:Pf(e0,"MiniMax quota failed")}))]);if(Df!==c.current)return;let h0={ok:Rf?.ok!==!1,service:"pipeline-v2-control snapshot"};$({loading:!1,error:"",health:h0,snapshot:Rf,oaDiagnostics:Q0,minimaxQuota:af,refreshedAt:new Date})}catch(If){if(Df!==c.current)return;$((Rf)=>({...Rf,loading:!1,error:Pf(If,"Pipeline 加载失败")}))}finally{v.current=!1}}b1(()=>{if(w(),!y)return;let t=()=>{if(I5())w({silent:!0})},Hf=window.setInterval(()=>{t()},Uq),Df=()=>{if(I5())t()};return document.addEventListener("visibilitychange",Df),()=>{window.clearInterval(Hf),document.removeEventListener("visibilitychange",Df)}},[y?.id,y?.runtime?.providerStatus,_]);let Y=dT(y),R=fr(y),k=eT(y),p=l.snapshot||{},n=l.oaDiagnostics||null,_f=l.minimaxQuota||null,{components:s,pipelines:ff,runs:Kf}=ur(p),Gf=String(Kf[0]?.pipelineId||""),jf=(Gf?ff.find((t)=>String(t.id||"")===Gf):null)||ff[0]||{},Wf=ff.find((t)=>String(t.id||"")===j)||jf,Of=String(Wf.id||""),Zf=kq(Wf),h=uQ(Wf),i=Dq(Kf,Of),I=Yr(Kf,Of),lf=I.find((t)=>String(t?.runId||"")===F)||i,$f=String(q.runId||"")===String(lf?.runId||"")?$r(q.details):null,Af=jr(lf,$f),Yf=String(Af?.runId||""),xf=Zf.find((t)=>String(t?.id||"")===U)||null,of=U?mq(Af,U):null,F0=yr(Kf),y0=Ar(s),T0=Number(l.health?.components)||Vq(p,"registry.components",s.length),Qu=Vq(p,"runs",Kf.length),X0=Nq(Wf,Af,s),v0={nodes:X0.nodes.map((t)=>t.id===U?{...t,selected:!0,className:`${t.className||""} selected-control-node`}:t),edges:X0.edges},iu=ff.map((t)=>{let Hf=String(t.id||"pipeline"),Df=Dq(Kf,Hf);return{title:`${Hf}-${Df?.runId||"snapshot"}`,flow:Nq(t,Df,s)}}),K0=String(O?.runId||Yf||""),Au=String(O?.interval?.nodeId||O?.marker?.nodeId||""),uf=K0&&Au?E[cF(K0,Au)]||null:null,vf=n5(W.details,K0,Au),o0=n5(uf?.details,K0,Au)||vf,Bf=K0&&Au?{...Xf(uf)?uf:{},runId:K0,nodeId:Au,details:o0,loading:Boolean(uf?.loading)||!o0&&Boolean(W.loading)&&U===Au,error:String(uf?.error||""),fetchedAt:uf?.fetchedAt||(vf?W.fetchedAt:null)}:null,b0=I.map((t)=>String(t?.runId||"")).filter(Boolean).join("|"),i0=Zf.map((t)=>String(t?.id||"")).filter(Boolean).join("|");b1(()=>{P.current=U},[U]),b1(()=>{M.current=Yf},[Yf]),b1(()=>{if(!F||b0.split("|").includes(F))return;A("")},[F,b0]),b1(()=>{if(!U||i0.split("|").includes(U))return;G(""),K($_()),z(d_()),N(!1),x(!1)},[U,i0]),b1(()=>{if(!U)N(!1)},[U]),b1(()=>{if(!O.mode)x(!1)},[O.mode]);async function a0(t=Yf,Hf={}){if(!t){Z(kF());return}let Df=_y(Hf.scale??V??B6),If=`${t}:timeline`;if(S.current===If)return;S.current=If;let Rf=Hf.silent===!0,Q0=C.current+1;C.current=Q0,Z((af)=>({runId:t,scale:Df,loading:!Rf||String(af.runId||"")!==t||!af.details,error:"",details:Rf&&af.runId===t?af.details:af.runId===t?af.details:null,fetchedAt:af.runId===t?af.fetchedAt:null}));try{let[af,h0]=await Promise.all([a_(E6(_,`/api/node-control/runs/${encodeURIComponent(t)}?tail=160&view=timeline`),{cache:"no-store",strictJson:!0}),a_(E6(_,`/api/runs/${encodeURIComponent(t)}`),{cache:"no-store"}).catch((e0)=>({ok:!1,runSummaryError:Pf(e0,"抓取评分失败")}))]);if(Q0!==C.current)return;Z({runId:t,scale:Df,loading:!1,error:"",details:{...af,run:Xf(h0?.run)?h0.run:void 0,runSummaryError:h0?.runSummaryError},fetchedAt:new Date})}catch(af){if(Q0!==C.current)return;Z((h0)=>({runId:t,scale:Df,loading:!1,error:Pf(af,"抓取 epoch 执行过程失败"),details:h0.runId===t?h0.details:null,fetchedAt:h0.runId===t?h0.fetchedAt:null}))}finally{if(S.current===If)S.current=""}}function nf(t,Hf,Df){let If=cF(t,Hf);H((Rf)=>{let Q0={...Rf,[If]:{...Xf(Rf?.[If])?Rf[If]:{},runId:t,nodeId:Hf,...Df}},af=Object.keys(Q0);if(af.length>32)for(let h0 of af.slice(0,af.length-32))delete Q0[h0];return Q0})}async function d0(t,Hf){if(!t||!Hf)return;let Df=cF(t,Hf),If=Number(B.current?.[Df]||0)+1;B.current={...B.current,[Df]:If},nf(t,Hf,{loading:!0,error:""});try{let Rf=await a_(E6(_,`/api/node-control/runs/${encodeURIComponent(t)}/nodes/${encodeURIComponent(Hf)}?tail=160`),{cache:"no-store",strictJson:!0});if(Number(B.current?.[Df]||0)!==If)return;let Q0=new Date;if(nf(t,Hf,{loading:!1,details:Rf,fetchedAt:Q0,error:""}),P.current===Hf&&M.current===t)K((af)=>({...af,loading:!1,details:Rf,fetchedAt:Q0,error:""}))}catch(Rf){if(Number(B.current?.[Df]||0)!==If)return;nf(t,Hf,{loading:!1,error:Pf(Rf,"抓取 Gantt node 详情失败")})}}b1(()=>{if(!Yf){Z(kF());return}a0(Yf);let t=()=>{if(I5())a0(Yf,{silent:!0})},Hf=window.setInterval(()=>{t()},Uq),Df=()=>{if(I5())t()};return document.addEventListener("visibilitychange",Df),()=>{window.clearInterval(Hf),document.removeEventListener("visibilitychange",Df)}},[Yf,_]);async function Hu(t=Yf,Hf=U){if(!t||!Hf){K((Df)=>({...Df,error:"请先选择 run 和 node",message:""}));return}K((Df)=>({...Df,loading:!0,error:"",message:""}));try{let Df=await a_(E6(_,`/api/node-control/runs/${encodeURIComponent(t)}/nodes/${encodeURIComponent(Hf)}?tail=160`),{cache:"no-store",strictJson:!0}),If=new Date;K((Rf)=>({...Rf,loading:!1,details:Df,fetchedAt:If,error:""})),nf(t,Hf,{loading:!1,details:Df,fetchedAt:If,error:""})}catch(Df){K((If)=>({...If,loading:!1,error:Pf(Df,"抓取 node 执行过程失败")}))}}async function oy(t){let Hf=String(t?.runId||Yf||""),Df=String(t?.nodeId||"");if(z({mode:"interval",runId:Hf,interval:t,marker:null}),x(!0),!Hf||!Df)return;if(Hf!==Yf)A(Hf);G(Df),K($_()),a0(Hf,{silent:!0}),d0(Hf,Df)}async function J_(t){let Hf=String(t?.runId||Yf||""),Df=String(t?.nodeId||"");if(z({mode:"event",runId:Hf,interval:null,marker:t}),x(!0),!Hf)return;if(Hf!==Yf)A(Hf);if(a0(Hf,{silent:!0}),!Df)return;G(Df),K($_()),d0(Hf,Df)}async function ay(t){if(!Yf||!U){K((If)=>({...If,error:"请先选择 run 和 node",message:""}));return}let Hf=t==="append"?"prompts":t,Df=t==="append"?W.appendPrompt:t==="guide"?W.guidePrompt:t==="modify"?W.modifyPrompt:t==="approve"?W.approveReason:W.redoReason;if(!String(Df||"").trim()){K((If)=>({...If,error:"操作内容不能为空",message:""}));return}K((If)=>({...If,actionLoading:t,error:"",message:""}));try{let If=t==="redo"||t==="approve"?{reason:Df,source:"unidesk-frontend",sourceKind:"webui"}:{prompt:Df,source:"unidesk-frontend",sourceKind:"webui"},Rf=await a_(E6(_,`/api/node-control/runs/${encodeURIComponent(Yf)}/nodes/${encodeURIComponent(U)}/${Hf}`),{method:"POST",body:JSON.stringify(If)});if(K((Q0)=>({...Q0,actionLoading:"",details:Rf,fetchedAt:new Date,appendPrompt:t==="append"?"":Q0.appendPrompt,guidePrompt:t==="guide"?"":Q0.guidePrompt,modifyPrompt:t==="modify"?"":Q0.modifyPrompt,approveReason:t==="approve"?"":Q0.approveReason,redoReason:t==="redo"?"":Q0.redoReason,message:t==="append"?"已追加到运行中 node":t==="guide"?"已下发 guide,等待 runner 处理":t==="modify"?"已排队增量修改命令":t==="approve"?"已提交审核通过决策":"已排队重做命令"})),await Hu(Yf,U),await a0(Yf,{silent:!0}),t!=="append")await w()}catch(If){K((Rf)=>({...Rf,actionLoading:"",error:Pf(If,"node 控制操作失败")}))}}if(!y)return X(pu,{title:"Pipeline 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=pipeline"});return X("div",{className:"pipeline-page","data-testid":"pipeline-page"},X(v1,{title:"Pipeline v2 工作台",eyebrow:"D601 Snapshot 用户服务",actions:X("div",{className:"panel-actions"},X("button",{type:"button",className:"ghost-btn",onClick:w,disabled:l.loading,"data-testid":"pipeline-refresh-button"},l.loading?"刷新中":"刷新"),X(O1,{title:"Pipeline 用户服务",data:y,onOpen:u,testId:"raw-pipeline-service"}))},X("div",{className:"pipeline-hero"},X("div",null,X("div",{className:"node-version-line"},X(uy,{status:Y.providerStatus==="online"?"online":"warn"},Y.providerStatus||"unknown"),X("span",null,y.providerId),X("span",null,k.public?"公网暴露":"仅 UniDesk frontend 代理访问")),X("p",{className:"muted paragraph"},y.description)),X("div",{className:"microservice-ref-card"},X("span",null,"Repo"),X("strong",null,R.url||"--"),X("code",null,R.commitId||"--")),X("div",{className:"microservice-ref-card"},X("span",null,"D601 Docker"),X("strong",null,`${k.nodeBindHost||"--"}:${k.nodePort||"--"}`),X("code",null,`${R.composeFile||"--"} / ${R.composeService||"--"}`))),X(H0,{error:l.error,wide:!0})),X("div",{className:"pipeline-grid"},X(v1,{title:"控制图",eyebrow:`${Wf.id||"pipeline"} / run ${Af?.status||"--"}`,className:"pipeline-wide-panel",actions:X("div",{className:"pipeline-toolbar"},X("select",{value:Of,disabled:ff.length===0,onChange:(t)=>{J(t.target.value),A(""),G(""),K($_()),z(d_()),N(!1),x(!1)},"data-testid":"pipeline-select"},ff.map((t)=>X("option",{key:t.id,value:t.id},t.id||t.key))),X("select",{value:Yf,disabled:I.length===0,onChange:(t)=>{if(A(t.target.value),K($_()),z(d_()),N(!1),x(!1),U)Hu(t.target.value,U)},"data-testid":"pipeline-run-select"},I.map((t)=>X("option",{key:t.runId,value:t.runId},tF(I,t)))),X("button",{type:"button",className:"ghost-btn",disabled:v0.nodes.length===0,onClick:()=>nq(v0,`${Wf.id||"pipeline"}-${Af?.runId||"snapshot"}`),"data-testid":"pipeline-export-graph"},"导出渲染图"),X("button",{type:"button",className:"ghost-btn",disabled:iu.every((t)=>t.flow.nodes.length===0),onClick:()=>Lr(iu),"data-testid":"pipeline-export-all-graphs"},"批量导出"))},Zf.length===0?X(pu,{title:"暂无控制图",text:"等待 D601 pipeline backend 返回 config.nodes / config.edges"}):X("div",{className:`pipeline-control-shell ${r?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-control-shell","data-sidebar-open":r?"true":"false"},X("div",{className:"pipeline-flow-frame","data-testid":"pipeline-react-flow"},X(lq,{nodes:v0.nodes,edges:v0.edges,nodeTypes:bT,edgeTypes:vT,fitView:!0,fitViewOptions:{padding:0.18},nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,minZoom:0.25,maxZoom:1.4,proOptions:{hideAttribution:!0},onNodeClick:(t,Hf)=>{let Df=String(Hf.id);if(G(Df),K($_()),N(!0),Yf)Hu(Yf,Df)}},X(jq,{gap:22,size:1,color:"rgba(215, 161, 58, 0.24)"}),X(Fq,{showInteractive:!1})),!r?X("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!U,onClick:()=>N(!0),"data-testid":"pipeline-node-sidebar-toggle"},U?"展开 node 控制":"点击 node 展开控制"):null),r?X(tr,{activeRun:Af,pipelineRuns:I,selectedRunId:F,onRunChange:(t)=>{if(A(t),K($_()),z(d_()),U)Hu(t,U)},selectedNodeId:U,selectedNodeConfig:xf,selectedNodeRuntime:of,control:W,onControlChange:(t)=>K((Hf)=>({...Hf,...t})),onFetch:()=>Hu(),onAction:ay,onRaw:u,onCollapse:()=>N(!1)}):null),X("div",{className:"pipeline-flow-summary"},X("span",null,`${v0.nodes.length} nodes`),X("span",null,`${v0.edges.length} edges`),X("span",null,`${ff.length} pipelines`),X("span",null,`source config+components(${s.length})`),X("span",null,`run ${Af?.runId||"--"}`),X("span",null,`score ${nF(Af)}`),X("span",null,U?`selected ${U}`:"click node to control"))),X(nr,{epochs:I,activeRun:Af,activePipeline:Wf,pipelineNodes:Zf,pipelineEdges:h,selection:O,detailOpen:D,onDetailOpenChange:x,runDetails:q,nodeDetails:o0,nodeDetailsState:Bf,ganttScale:V,onGanttScaleChange:L,onIntervalSelect:oy,onMarkerSelect:J_,onRunChange:(t)=>{if(A(t),K($_()),z(d_()),x(!1),U)Hu(t,U)},onRaw:u}),X(v1,{title:"观测指标",eyebrow:l.refreshedAt?`Updated ${L0(l.refreshedAt)}`:"Snapshot"},X("div",{className:"metric-grid"},X(Eu,{label:"Health",value:l.health?.ok?"OK":"--",hint:l.health?.service||"D601 /health",tone:l.health?.ok?"ok":"warn"}),X(Eu,{label:"组件",value:T0,hint:"components registry",tone:p?.registry?.ok===!1?"warn":"ok"}),X(Eu,{label:"Pipeline",value:ff.length,hint:`${Zf.length} nodes / ${h.length} edges`}),X(Eu,{label:"运行记录",value:Qu,hint:`${F0.succeeded||0} succeeded / ${F0.running||0} running`}),X(Eu,{label:"OA 记录",value:Array.isArray(i?.submissions)?i.submissions.length:0,hint:i?.runId||"latest run"}),X(Eu,{label:"Procedure",value:Array.isArray(i?.procedureRuns)?i.procedureRuns.length:0,hint:i?.status||"no run"}),X(Eu,{label:"Score",value:nF(Af),hint:Af?.runId||"selected epoch",tone:yQ(Af)})),X("div",{className:"panel-actions inline-actions"},X(O1,{title:"Pipeline Snapshot",data:p,onOpen:u,testId:"raw-pipeline-snapshot"}))),X(v1,{title:"评分器",eyebrow:Af?.runId||"selected epoch"},X(Qr,{run:Af,onRaw:u})),X(v1,{title:"MiniMax 限额",eyebrow:"model/minimax-m27 quota"},X(gr,{quota:_f,onRaw:u})),X(v1,{title:"OA 事件流",eyebrow:"100% event-driven diagnostics",className:"pipeline-wide-panel"},X(ir,{diagnostics:n,onRaw:u})),X(v1,{title:"组件矩阵",eyebrow:`${y0.length} classes`},y0.length===0?X(pu,{title:"暂无组件",text:"等待 D601 pipeline backend 返回 registry.components"}):X("div",{className:"component-strata"},y0.map((t)=>X("article",{key:t.name,className:"component-stratum"},X("span",null,t.name),X("strong",null,t.count)))),X("div",{className:"pipeline-component-list"},s.slice(0,12).map((t)=>X("span",{key:t.key,className:"data-chip"},X("b",null,t.componentClass||"--"),X("span",null,t.id||t.key||"--"))))),X(v1,{title:"Epoch 列表",eyebrow:`${I.length}/${Qu} preview`},I.length===0?X(pu,{title:"暂无运行记录",text:"当前 pipeline 在 .state/pipeline-runs 中还没有 epoch。"}):X("div",{className:"pipeline-run-list"},I.map((t)=>{let Hf=String(t?.runId||"")===Yf?Af:t;return X("article",{key:t.runId,className:`pipeline-run-card ${String(t.runId||"")===Yf?"active":""}`,role:"button",tabIndex:0,onClick:()=>{A(String(t.runId||"")),z(d_())},onKeyDown:(Df)=>{if(Df.key==="Enter"||Df.key===" ")A(String(t.runId||"")),z(d_())}},X("div",{className:"node-card-head"},X("strong",null,tF(I,t)),X(uy,{status:t.status},t.status||"--")),X("div",{className:"docker-meta compact"},X("span",null,Hf?.pipelineId||"--"),X("span",null,`nodes ${Array.isArray(Hf?.nodes)?Hf.nodes.length:0}`),X("span",null,`oa ${Array.isArray(Hf?.submissions)?Hf.submissions.length:0}`),X("span",null,`procedures ${Array.isArray(Hf?.procedureRuns)?Hf.procedureRuns.length:0}`),X(Fr,{run:Hf})),X("p",{className:"muted paragraph"},g5(Hf?.task)),X("span",{className:"pipeline-run-time"},zf(Hf?.updatedAt)))}))),X(v1,{title:"运行材料索引",eyebrow:Af?.runId||"selected epoch",className:"pipeline-wide-panel"},X(mr,{activeRun:Af,onRaw:u}))))}var l2=Sf(c0(),1);var e=l2.default.createElement,{useEffect:sr}=l2.default,_2=l2.default.useState,JQ={id:"",sequenceNo:"",contractNo:"",name:"",currentStatus:"",pending:"",paymentStatus:"",notes:""};function or({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return e("span",{className:`status-badge ${_}`},u||f||"unknown")}function y2({label:f,value:u,hint:_,tone:y}){return e("article",{className:`metric-card ${y||""}`},e("div",{className:"metric-label"},f),e("div",{className:"metric-value"},u),e("div",{className:"metric-hint"},_))}function FQ({title:f,eyebrow:u,actions:_,children:y,className:l}){return e("section",{className:`panel ${l||""}`},e("div",{className:"panel-head"},e("div",null,u?e("p",{className:"panel-eyebrow"},u):null,e("h2",null,f)),_?e("div",{className:"panel-actions"},_):null),e("div",{className:"panel-body"},y))}function yE({title:f,data:u,onOpen:_,testId:y}){return e("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function lE({title:f,text:u}){return e("div",{className:"empty-state"},e("strong",null,f),e("span",null,u))}function ar(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function dr(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function er(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function z3(f,u){return`${f}/microservices/project-manager/proxy${u}`}function fM(f){return{id:String(f.id||""),sequenceNo:f.sequenceNo===null||f.sequenceNo===void 0?"":String(f.sequenceNo),contractNo:String(f.contractNo||""),name:String(f.name||""),currentStatus:String(f.currentStatus||""),pending:String(f.pending||""),paymentStatus:String(f.paymentStatus||""),notes:String(f.notes||"")}}function uM(f){return{sequenceNo:f.sequenceNo===""?null:Number(f.sequenceNo),contractNo:String(f.contractNo||"").trim(),name:String(f.name||"").trim(),currentStatus:String(f.currentStatus||"").trim(),pending:String(f.pending||"").trim(),paymentStatus:String(f.paymentStatus||"").trim(),paymentRatio:String(f.paymentStatus||"").trim(),notes:String(f.notes||"").trim()}}function QQ(f){return String(f||"item").replace(/[^A-Za-z0-9_-]+/g,"-")}function _M(f){let u=new Uint8Array(f),_="",y=32768;for(let l=0;le("tr",{key:l.id,className:u===l.id?"active-row":"","data-testid":`project-manager-row-${QQ(l.id)}`},e("td",null,l.sequenceNo??"--"),e("td",null,e("strong",null,l.contractNo||"--"),e("code",null,l.id||"--")),e("td",null,e("strong",null,l.name||"--"),e("span",{className:"muted block"},l.sourceFile||"--")),e("td",null,l.currentStatus||"--"),e("td",null,e("span",{className:"preline"},l.pending||"--")),e("td",null,e(or,{status:Number(l.paymentRatio||0)>=1?"online":"warn"},l.paymentStatus||"--")),e("td",null,l.notes||"--"),e("td",null,e("div",{className:"inline-actions"},e("button",{type:"button",className:"ghost-btn",onClick:()=>_(l),"data-testid":`project-manager-edit-${QQ(l.id)}`},"编辑"),e(yE,{title:`Project ${l.contractNo||l.id}`,data:l,onOpen:y,testId:`raw-project-${QQ(l.id)}`}))))))))}function $E({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((N)=>N.id==="project-manager")||null,[l,$]=_2({loading:!1,saving:!1,importing:!1,exporting:!1,error:"",notice:"",health:null,list:null,refreshedAt:null}),[j,J]=_2({...JQ}),[F,A]=_2(""),[U,G]=_2("all");async function W(N=F,D=U){if(!y)return;$((x)=>({...x,loading:!0,error:""}));try{let x=new URLSearchParams({pageSize:"200",status:D});if(N.trim())x.set("q",N.trim());let[c,v]=await Promise.all([wf(`${_}/microservices/project-manager/health`),wf(z3(_,`/api/projects?${x.toString()}`))]);$((C)=>({...C,loading:!1,health:c,list:v,refreshedAt:new Date,error:""}))}catch(x){$((c)=>({...c,loading:!1,error:Pf(x,"Project Manager 加载失败")}))}}sr(()=>{W()},[y?.id,y?.runtime?.providerStatus]);async function K(N){N.preventDefault(),$((D)=>({...D,saving:!0,error:"",notice:""}));try{let D=uM(j);if(j.id)await wf(z3(_,`/api/projects/${encodeURIComponent(j.id)}`),{method:"PUT",body:JSON.stringify(D)});else await wf(z3(_,"/api/projects"),{method:"POST",body:JSON.stringify(D)});$((x)=>({...x,saving:!1,notice:j.id?"项目已更新":"项目已创建"})),await W()}catch(D){$((x)=>({...x,saving:!1,error:Pf(D,"保存项目失败")}))}}async function E(){if(!j.id)return;if(!window.confirm(`删除项目 ${j.contractNo||j.name||j.id} ?`))return;$((N)=>({...N,saving:!0,error:"",notice:""}));try{await wf(z3(_,`/api/projects/${encodeURIComponent(j.id)}`),{method:"DELETE"}),J({...JQ}),$((N)=>({...N,saving:!1,notice:"项目已删除"})),await W()}catch(N){$((D)=>({...D,saving:!1,error:Pf(N,"删除项目失败")}))}}async function H(N){let D=N.target.files?.[0];if(!D)return;$((x)=>({...x,importing:!0,error:"",notice:""}));try{let x=_M(await D.arrayBuffer()),c=await wf(z3(_,"/api/import/excel"),{method:"POST",body:JSON.stringify({fileName:D.name,contentBase64:x,replace:!1})});$((v)=>({...v,importing:!1,notice:`Excel 已导入 ${c.imported||0} 条项目`})),N.target.value="",await W()}catch(x){$((c)=>({...c,importing:!1,error:Pf(x,"Excel 导入失败")}))}}async function O(){$((N)=>({...N,exporting:!0,error:""}));try{let N=await JG(z3(_,"/api/projects/export.xlsx")),D=URL.createObjectURL(N),x=document.createElement("a");x.href=D,x.download=`project-manager-${IQ()}.xlsx`,document.body.appendChild(x),x.click(),x.remove(),URL.revokeObjectURL(D),$((c)=>({...c,exporting:!1,notice:"Excel 已导出"}))}catch(N){$((D)=>({...D,exporting:!1,error:Pf(N,"Excel 导出失败")}))}}if(!y)return e(lE,{title:"Project Manager 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=project-manager"});let z=ar(y),q=er(y),Z=dr(y),V=Array.isArray(l.list?.projects)?l.list.projects:[],L=l.list?.summary||{},r=l.health||{};return e("div",{className:"project-manager-page","data-testid":"project-manager-page"},e(FQ,{title:"项目管理工作台",eyebrow:"Main Server PostgreSQL 用户服务",actions:e("div",{className:"panel-actions"},e("button",{type:"button",className:"ghost-btn",disabled:l.loading,onClick:()=>W(),"data-testid":"project-manager-refresh-button"},l.loading?"刷新中":"刷新"),e("button",{type:"button",className:"ghost-btn",disabled:l.exporting,onClick:O,"data-testid":"project-manager-export-button"},l.exporting?"导出中":"导出 Excel"),e(yE,{title:"Project Manager 用户服务",data:y,onOpen:u,testId:"raw-project-manager-service"}))},e("div",{className:"project-manager-hero"},e(y2,{label:"项目总数",value:L.total??V.length,hint:`PG 表 ${r.storage?.table||"project_manager_projects"}`,tone:"ok"}),e(y2,{label:"进行中",value:L.active??"--",hint:"当前状态未完全完成"}),e(y2,{label:"已完成",value:L.completed??"--",hint:"按 完成 关键字统计",tone:"ok"}),e(y2,{label:"未全款",value:L.unpaid??"--",hint:"付款比例 < 1",tone:Number(L.unpaid||0)>0?"warn":"ok"})),e(H0,{error:l.error}),l.notice?e("div",{className:"form-success"},l.notice):null),e("div",{className:"project-manager-hero"},e("div",{className:"microservice-ref-card"},e("span",null,"Repo"),e("strong",null,q.url||"--"),e("code",null,q.commitId||"--")),e("div",{className:"microservice-ref-card"},e("span",null,"Main Server Docker"),e("strong",null,`${Z.nodeBindHost||"--"}:${Z.nodePort||"--"}`),e("code",null,`${q.composeService||"--"} / ${q.containerName||"--"}`)),e("div",{className:"microservice-ref-card"},e("span",null,"Runtime"),e("strong",null,z.providerName||y.providerId),e("code",null,`Health ${r.ok?"OK":"--"} / ${l.refreshedAt?L0(l.refreshedAt):"--"}`)),e("div",{className:"microservice-ref-card"},e("span",null,"Import Source"),e("strong",null,"D601 WeChat Excel"),e("code",null,"合作项目列表_I_20260309.xlsx"))),e("div",{className:"project-manager-layout"},e(FQ,{title:"项目清单",eyebrow:"CRUD + Excel Export",actions:e("div",{className:"inline-actions project-manager-filters"},e("input",{value:F,onChange:(N)=>A(N.target.value),placeholder:"搜索合同号 / 项目名称 / 状态","data-testid":"project-manager-search"}),e("select",{value:U,onChange:(N)=>{G(N.target.value),W(F,N.target.value)},"data-testid":"project-manager-status-filter"},e("option",{value:"all"},"全部"),e("option",{value:"active"},"进行中"),e("option",{value:"completed"},"已完成"),e("option",{value:"unpaid"},"未全款")),e("button",{type:"button",className:"ghost-btn",onClick:()=>W(F,U)},"筛选"))},e(yM,{projects:V,activeId:j.id,onSelect:(N)=>J(fM(N)),onRaw:u})),e(FQ,{title:j.id?"编辑项目":"新建项目",eyebrow:"PostgreSQL Write Path"},e("form",{className:"stack-form project-manager-form",onSubmit:K,"data-testid":"project-manager-form"},j.id?e("label",null,"项目 ID",e("input",{value:j.id,disabled:!0})):null,e("label",null,"序号",e("input",{type:"number",value:j.sequenceNo,onChange:(N)=>J((D)=>({...D,sequenceNo:N.target.value}))})),e("label",null,"合同号",e("input",{value:j.contractNo,onChange:(N)=>J((D)=>({...D,contractNo:N.target.value})),required:!0})),e("label",null,"项目名称",e("input",{value:j.name,onChange:(N)=>J((D)=>({...D,name:N.target.value})),required:!0})),e("label",null,"当前状况",e("textarea",{value:j.currentStatus,onChange:(N)=>J((D)=>({...D,currentStatus:N.target.value}))})),e("label",null,"待完成",e("textarea",{value:j.pending,onChange:(N)=>J((D)=>({...D,pending:N.target.value}))})),e("label",null,"付款情况",e("input",{value:j.paymentStatus,onChange:(N)=>J((D)=>({...D,paymentStatus:N.target.value})),placeholder:"例如 1 / 0.5 / 50%"})),e("label",null,"其它",e("input",{value:j.notes,onChange:(N)=>J((D)=>({...D,notes:N.target.value}))})),e("div",{className:"inline-actions"},e("button",{type:"submit",className:"primary-btn",disabled:l.saving,"data-testid":"project-manager-save-button"},l.saving?"保存中":j.id?"保存修改":"创建项目"),e("button",{type:"button",className:"ghost-btn",onClick:()=>J({...JQ})},"清空"),j.id?e("button",{type:"button",className:"danger-btn",disabled:l.saving,onClick:E,"data-testid":"project-manager-delete-button"},"删除"):null)),e("div",{className:"project-manager-import"},e("p",{className:"muted paragraph"},"浏览器只访问 UniDesk frontend;后端通过同源用户服务代理写入主 PostgreSQL,不暴露 4233 公网端口。"),e("label",{className:"file-import"},l.importing?"导入中...":"导入 Excel",e("input",{type:"file",accept:".xlsx",onChange:H,disabled:l.importing,"data-testid":"project-manager-import-input"}))))))}var F2=Sf(c0(),1);var yf=F2.default.createElement,{useEffect:lM}=F2.default,ru=F2.default.useState;function $M({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return yf("span",{className:`status-badge ${_}`},u||f||"unknown")}function $2({label:f,value:u,hint:_,tone:y}){return yf("article",{className:`metric-card ${y||""}`},yf("div",{className:"metric-label"},f),yf("div",{className:"metric-value"},u),yf("div",{className:"metric-hint"},_))}function AQ({title:f,eyebrow:u,actions:_,children:y,className:l}){return yf("section",{className:`panel ${l||""}`},yf("div",{className:"panel-head"},yf("div",null,u?yf("p",{className:"panel-eyebrow"},u):null,yf("h2",null,f)),_?yf("div",{className:"panel-actions"},_):null),yf("div",{className:"panel-body"},y))}function jE({title:f,data:u,onOpen:_,testId:y}){return yf("button",{type:"button",className:"ghost-btn","data-testid":y,onClick:()=>_(f,u)},"查看原始JSON")}function j2({title:f,text:u}){return yf("div",{className:"empty-state"},yf("strong",null,f),yf("span",null,u))}function jM(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function JM(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function FM(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function FE(f){return String(f).replace(/[^a-zA-Z0-9_-]/g,"_")}function QM(f){if(!Number.isFinite(f))return"--";return`${f.toFixed(1)}%`}function K3(f,u){return`${f}/microservices/todo-note/proxy${u}`}function QE(f){return f.reduce((u,_)=>{let y=QE(Array.isArray(_.children)?_.children:[]),l=Boolean(_.completed);return{total:u.total+1+y.total,completed:u.completed+(l?1:0)+y.completed,active:u.active+(l?0:1)+y.active}},{total:0,completed:0,active:0})}function J2(f,u){let _=u==="all"||(u==="completed"?Boolean(f.completed):!f.completed),y=Array.isArray(f.children)?f.children:[];return _||y.some((l)=>J2(l,u))}function JE(f){return Array.isArray(f?.instances)?f.instances:[]}function AE({microservices:f,onRaw:u,apiBaseUrl:_="/api"}){let y=f.find((I)=>I.id==="todo-note")||null,[l,$]=ru(null),[j,J]=ru(null),[F,A]=ru(""),[U,G]=ru(null),[W,K]=ru("all"),[E,H]=ru(13),[O,z]=ru(""),[q,Z]=ru(""),[V,L]=ru(""),[r,N]=ru(""),[D,x]=ru(""),[c,v]=ru(!1),[C,S]=ru(""),[B,P]=ru(null),M=JE(j),w=QE(Array.isArray(U?.todos)?U.todos:[]),Y=y?jM(y):{},R=y?FM(y):{},k=y?JM(y):{};async function p(I=F){let[lf,$f]=await Promise.all([wf(`${_}/microservices/todo-note/health`),wf(K3(_,"/api/instances"))]);$(lf),J($f);let Af=JE($f),Yf=Af.some((xf)=>xf.id===I)?I:Af[0]?.id||"";return A(Yf),Yf}async function n(I=F){if(!I){G(null);return}let lf=await wf(K3(_,`/api/instances/${encodeURIComponent(I)}`));G(lf)}async function _f(I=F){if(!y)return;v(!0),S("");try{let lf=await p(I);await n(lf),P(new Date)}catch(lf){S(Pf(lf,"Todo Note 加载失败"))}finally{v(!1)}}async function s(I){if(!F)return;S("");try{let lf=await wf(K3(_,`/api/instances/${encodeURIComponent(F)}/actions`),{method:"POST",body:JSON.stringify({action:I})});G(lf),await p(F)}catch(lf){S(Pf(lf,"Todo 操作失败"))}}async function ff(I){I.preventDefault();let lf=O.trim();if(!lf)return;v(!0),S("");try{let $f=await wf(K3(_,"/api/instances"),{method:"POST",body:JSON.stringify({name:lf})});z(""),await _f($f.id)}catch($f){S(Pf($f,"创建清单失败"))}finally{v(!1)}}async function Kf(I){if(!window.confirm("确认删除这个 Todo Note 清单?"))return;v(!0),S("");try{await wf(K3(_,`/api/instances/${encodeURIComponent(I)}`),{method:"DELETE"}),await _f(F===I?"":F)}catch(lf){S(Pf(lf,"删除清单失败"))}finally{v(!1)}}async function Gf(I){I.preventDefault();let lf=q.trim();if(!lf)return;Z(""),await s({type:"addTodo",title:lf})}async function jf(I){if(!F)return;S("");try{let lf=await wf(K3(_,`/api/instances/${encodeURIComponent(F)}/${I}`),{method:"POST",body:JSON.stringify({})});G(lf),await p(F)}catch(lf){S(Pf(lf,`${I} 失败`))}}function Wf(I){L(I.id),N(String(I.title||""))}async function Of(I){let lf=r.trim();if(L(""),N(""),lf)await s({type:"updateTodoTitle",todoId:I,title:lf})}async function Zf(I){let lf=window.prompt("新增子任务标题");if(lf&&lf.trim())await s({type:"addTodo",title:lf.trim(),parentId:I})}async function h(I,lf){if(!D)return;let $f={type:"moveTodo",todoId:D,targetIndex:lf};if(I)$f.targetParentId=I;x(""),await s($f)}if(lM(()=>{_f()},[y?.id,y?.runtime?.providerStatus]),!y)return yf(j2,{title:"Todo Note 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=todo-note"});let i=M.find((I)=>I.id===F)||null;return yf("div",{className:"todo-note-page","data-testid":"todo-note-page"},yf(AQ,{title:"Todo Note 工作台",eyebrow:"Main Server 用户服务",actions:yf("div",{className:"panel-actions"},yf("button",{type:"button",className:"ghost-btn",disabled:c,onClick:()=>_f(F),"data-testid":"todo-note-refresh-button"},c?"刷新中":"刷新"),yf(jE,{title:"Todo Note 用户服务",data:y,onOpen:u,testId:"raw-todo-note-service"}))},yf("div",{className:"todo-note-hero"},yf("div",null,yf("div",{className:"node-version-line"},yf($M,{status:Y.providerStatus==="online"?"online":"warn"},Y.providerStatus||"unknown"),yf("span",null,y.providerId),yf("span",null,k.public?"公网暴露":"仅 UniDesk frontend 代理访问"),yf("span",null,l?.ok?"Health OK":"Health --")),yf("p",{className:"muted paragraph"},y.description)),yf("div",{className:"microservice-ref-card"},yf("span",null,"Repo"),yf("strong",null,R.url||"--"),yf("code",null,R.commitId||"--")),yf("div",{className:"microservice-ref-card"},yf("span",null,"Main Server Docker"),yf("strong",null,`${k.nodeBindHost||"--"}:${k.nodePort||"--"}`),yf("code",null,`${R.composeService||"--"} / ${R.containerName||"--"}`))),yf(H0,{error:C,wide:!0})),yf("div",{className:"todo-note-layout"},yf(AQ,{title:"清单",eyebrow:`${M.length} Instances`,className:"todo-list-panel"},yf("form",{className:"todo-create-list",onSubmit:ff},yf("input",{placeholder:"新清单名称",value:O,onChange:(I)=>z(I.target.value),"aria-label":"新清单名称"}),yf("button",{type:"submit",className:"ghost-btn",disabled:c||!O.trim()},"创建")),M.length===0?yf(j2,{title:"暂无清单",text:"迁移或创建清单后会出现在这里"}):yf("div",{className:"todo-instance-list"},M.map((I)=>yf("button",{key:I.id,type:"button",className:`todo-instance-row ${F===I.id?"active":""}`,onClick:()=>{A(I.id),n(I.id)},"data-testid":`todo-instance-${FE(I.id)}`},yf("strong",null,I.name),yf("span",null,`${I.completedCount??0}/${I.todoCount??0} 完成`),yf("code",null,I.id))))),yf("div",{className:"todo-main-stack"},yf(AQ,{title:i?.name||"待选择清单",eyebrow:B?`Updated ${L0(B)}`:"Todo Tree",actions:U?yf("div",{className:"panel-actions"},yf("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"renameInstance",name:window.prompt("清单新名称",U.name)||U.name})},"重命名"),yf("button",{type:"button",className:"ghost-btn danger",onClick:()=>Kf(F)},"删除清单"),yf(jE,{title:`Todo Instance ${F}`,data:U,onOpen:u,testId:"raw-todo-instance"})):null},!U?yf(j2,{title:"未选择清单",text:"左侧选择一个 Todo Note 清单"}):yf("div",{className:"todo-workbench",style:{"--todo-font-size":`${E}px`}},yf("div",{className:"todo-toolbar"},yf("form",{className:"todo-add-form",onSubmit:Gf},yf("input",{placeholder:"新增根任务",value:q,onChange:(I)=>Z(I.target.value),"aria-label":"新增根任务"}),yf("button",{type:"submit",className:"ghost-btn",disabled:!q.trim()},"新增")),yf("div",{className:"todo-filter-strip"},["all","active","completed"].map((I)=>yf("button",{key:I,type:"button",className:`todo-filter ${W===I?"active":""}`,onClick:()=>K(I)},I==="all"?"全部":I==="active"?"未完成":"已完成"))),yf("div",{className:"todo-toolbar-actions"},yf("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"setAllTodosExpanded",expanded:!0})},"全部展开"),yf("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"setAllTodosExpanded",expanded:!1})},"全部收起"),yf("button",{type:"button",className:"ghost-btn",onClick:()=>jf("undo")},"撤销"),yf("button",{type:"button",className:"ghost-btn",onClick:()=>jf("redo")},"重做"),yf("label",{className:"todo-font-control"},"字号",yf("input",{type:"range",min:11,max:18,value:E,onChange:(I)=>H(Number(I.target.value))})))),yf("div",{className:"todo-stats-grid"},yf($2,{label:"总任务",value:w.total,hint:`${M.length} lists`}),yf($2,{label:"已完成",value:w.completed,hint:`${QM(w.total?w.completed/w.total*100:0)}`,tone:"ok"}),yf($2,{label:"未完成",value:w.active,hint:W==="active"?"当前筛选":"active tasks",tone:w.active>0?"warn":"ok"}),yf($2,{label:"历史指针",value:U.historyPointer??0,hint:"undo / redo"})),yf("div",{className:"todo-root-drop",onDragOver:(I)=>I.preventDefault(),onDrop:(I)=>{I.preventDefault(),h(null,(U.todos||[]).length)}},"拖到这里可移为根任务末尾"),yf("div",{className:"todo-tree","data-testid":"todo-note-tree"},(U.todos||[]).filter((I)=>J2(I,W)).length===0?yf(j2,{title:"没有匹配任务",text:"调整筛选或新增任务"}):(U.todos||[]).filter((I)=>J2(I,W)).map((I,lf)=>yf(UE,{key:I.id,todo:I,depth:0,parentId:null,index:lf,siblingCount:U.todos.length,filter:W,editingId:V,editingTitle:r,setEditingTitle:N,beginEdit:Wf,saveEdit:Of,applyTodoAction:s,addChild:Zf,dragTodoId:D,setDragTodoId:x,dropTodo:h}))))))))}function UE(f){let{todo:u,depth:_,parentId:y,index:l,siblingCount:$,filter:j,editingId:J,editingTitle:F,setEditingTitle:A,beginEdit:U,saveEdit:G,applyTodoAction:W,addChild:K,dragTodoId:E,setDragTodoId:H,dropTodo:O}=f,z=Array.isArray(u.children)?u.children:[],q=z.filter((L)=>J2(L,j)),Z=J===u.id,V=y||null;return yf("div",{className:"todo-row-wrap"},yf("article",{className:`todo-row ${u.completed?"completed":""} ${E===u.id?"dragging":""}`,style:{"--todo-depth":_},draggable:!0,onDragStart:(L)=>{H(u.id),L.dataTransfer.effectAllowed="move"},onDragOver:(L)=>L.preventDefault(),onDrop:(L)=>{L.preventDefault(),O(u.id,z.length)},"data-testid":`todo-row-${FE(u.id)}`},yf("button",{type:"button",className:"todo-expand",disabled:z.length===0,onClick:()=>W({type:"toggleTodoExpanded",todoId:u.id})},z.length===0?"·":u.expanded?"▾":"▸"),yf("input",{type:"checkbox",checked:Boolean(u.completed),onChange:()=>W({type:"toggleTodoCompleted",todoId:u.id}),"aria-label":`完成 ${u.title}`}),yf("div",{className:"todo-title-cell",onDoubleClick:()=>U(u)},Z?yf("div",{className:"todo-edit-inline"},yf("input",{value:F,autoFocus:!0,onChange:(L)=>A(L.target.value),onKeyDown:(L)=>{if(L.key==="Enter")G(u.id);if(L.key==="Escape")U({id:"",title:""})}}),yf("button",{type:"button",className:"ghost-btn",onClick:()=>G(u.id)},"保存")):yf("strong",null,u.title||"Untitled"),yf("div",{className:"todo-meta-line"},yf("span",null,`子项 ${z.length}`),yf("span",null,`更新 ${zf(u.updatedAt)}`),u.reminderAt?yf("span",{className:"todo-reminder"},`提醒 ${zf(u.reminderAt)}`):yf("span",null,"无提醒"))),yf("input",{className:"todo-reminder-input",type:"datetime-local",value:P2(u.reminderAt),onChange:(L)=>W({type:"setTodoReminder",todoId:u.id,reminderAt:cQ(L.target.value)})}),yf("div",{className:"todo-row-actions"},yf("button",{type:"button",className:"ghost-btn",onClick:()=>U(u)},"编辑"),yf("button",{type:"button",className:"ghost-btn",onClick:()=>K(u.id)},"子项"),yf("button",{type:"button",className:"ghost-btn",disabled:l<=0,onClick:()=>W({type:"moveTodo",todoId:u.id,...V?{targetParentId:V}:{},targetIndex:l-1})},"上移"),yf("button",{type:"button",className:"ghost-btn",disabled:l>=$-1,onClick:()=>W({type:"moveTodo",todoId:u.id,...V?{targetParentId:V}:{},targetIndex:l+1})},"下移"),yf("button",{type:"button",className:"ghost-btn",disabled:!y,onClick:()=>W({type:"moveTodo",todoId:u.id,targetIndex:9999})},"提升"),yf("button",{type:"button",className:"ghost-btn danger",onClick:()=>W({type:"deleteTodo",todoId:u.id})},"删除"))),u.expanded&&q.length>0?yf("div",{className:"todo-children"},q.map((L,r)=>yf(UE,{key:L.id,todo:L,depth:_+1,parentId:u.id,index:r,siblingCount:z.length,filter:j,editingId:J,editingTitle:F,setEditingTitle:A,beginEdit:U,saveEdit:G,applyTodoAction:W,addChild:K,dragTodoId:E,setDragTodoId:H,dropTodo:O}))):null)}var WE=Sf(c0(),1),yy=WE.default.createElement;function GE({title:f,items:u,actions:_,className:y,testId:l}){let $=Array.isArray(u)?u:[];return yy("section",{className:`top-status-bar ${y||""}`,"data-testid":l},yy("div",{className:"top-status-main"},f?yy("strong",{className:"top-status-title"},f):null,yy("div",{className:"top-status-chips"},$.map((j,J)=>yy("span",{key:j?.key||`${j?.label||"status"}-${J}`,className:`top-status-chip ${j?.tone||""}`,"data-testid":j?.testId},j?.label?yy("b",null,j.label):null,yy("span",null,j?.value??"--"))))),_?yy("div",{className:"top-status-actions"},_):null)}function LE(f,u){let _=document.getElementById("root")?.getAttribute(f);if(!_)return u;try{let y=JSON.parse(_);return typeof y==="object"&&y!==null&&!Array.isArray(y)?y:u}catch{return u}}var sf=LE("data-config",{apiBaseUrl:"/api",authUsername:"admin"}),AM=LE("data-codex-overview",null),Q=r6.default.createElement,{useEffect:h1,useMemo:M6}=r6.default,hf=r6.default.useState,mu=Uz(h4),UM={id:"codex-queue",name:"Codex Queue",providerId:"main-server",description:"Codex Queue",repository:{containerName:"codex-queue-backend"},backend:{nodeBaseUrl:"http://codex-queue:4222",nodeBindHost:"codex-queue",nodePort:4222,public:!1},runtime:{providerStatus:"loading",providerName:"main-server"}};function zE(){return typeof document>"u"||document.visibilityState!=="hidden"}function WM(f,u){if(f==="ops"&&u==="status")return 5000;if(f==="nodes"&&u==="monitor")return 5000;if(f==="tasks"&&(u==="dispatch"||u==="pending"))return 5000;if(f==="nodes"||f==="ops")return 1e4;if(f==="apps")return 15000;if(f==="tasks")return 15000;return 30000}async function GM(f){if(!f?._summaryOnly||!f?.id)return f;return(await wf(`${sf.apiBaseUrl}/tasks/${encodeURIComponent(String(f.id))}`))?.task||f}function P6(f){return f?._summaryOnly?{...f,_loadRaw:()=>GM(f)}:f}function E3(f){if(!Number.isFinite(f))return"--";let u=Math.max(0,f);if(u===0)return"0s";if(u<0.01)return"<0.01s";if(u<0.1)return`${u.toFixed(2)}s`;if(u<1)return`${u.toFixed(1)}s`;if(u<10&&!Number.isInteger(u))return`${u.toFixed(1)}s`;if(u<60)return`${Math.round(u)}s`;let _=Math.floor(u);if(_<3600)return`${Math.floor(_/60)}m ${_%60}s`;return`${Math.floor(_/3600)}h ${Math.floor(_%3600/60)}m`}function ku(f){let u=Number(f);if(!Number.isFinite(u))return"--";if(u<1)return`${Math.max(0,u).toFixed(1)}ms`;if(u<10)return`${u.toFixed(1)}ms`;if(u<1000)return`${Math.round(u)}ms`;return E3(u/1000)}function Fu(f){let u=Number(f);if(!Number.isFinite(u)||u<=0)return"--";let _=["B","KB","MB","GB","TB"],y=u,l=0;while(y>=1024&&l<_.length-1)y/=1024,l+=1;return`${y.toFixed(l===0?0:1)} ${_[l]}`}function ly(f){let u=Number(f);return Number.isFinite(u)?`${Math.max(0,Math.min(100,u)).toFixed(1)}%`:"--"}function zM(f){let u=Number(f);return Number.isFinite(u)?`${Math.max(0,u).toFixed(1)}%`:"--"}function UQ(f){let u=Number(f);if(!Number.isFinite(u)||u<=0)return"0 B/s";return`${Fu(u)}/s`}function Mf(f,u=0){let _=Number(f);return Number.isFinite(_)?_:u}function H3(f){return["queued","dispatched","running"].includes(String(f?.status||"").toLowerCase())}function zQ(f){if(!f)return"--";let u=new Date(f);if(Number.isNaN(u.getTime()))return"--";return E3(Math.max(0,Math.floor((Date.now()-u.getTime())/1000)))}function Z3(f){if(!f)return null;let u=new Date(f);return Number.isNaN(u.getTime())?null:u.getTime()}function YE(f){let u=Z3(f?.createdAt);if(u===null)return null;let y=["succeeded","failed"].includes(String(f?.status||"").toLowerCase())?Z3(f?.updatedAt):Date.now();if(y===null)return null;return Math.max(0,(y-u)/1000)}function BE(f){if(String(f?.status||"").toLowerCase()!=="failed")return"";let u=f?.result;if(typeof u==="string")return u;if(u&&typeof u==="object"&&!Array.isArray(u)){let _=u;for(let y of["error","reason","message","stderr","detail"])if(typeof _[y]==="string"&&_[y].length>0)return _[y]}return"任务失败但 provider 未返回明确原因"}function ty(f){if(f===null||f===void 0)return"--";if(typeof f==="boolean")return f?"是":"否";if(typeof f==="number")return String(f);if(typeof f==="string")return f.length>80?`${f.slice(0,77)}...`:f;if(Array.isArray(f))return`${f.length} 项`;if(typeof f==="object")return`${Object.keys(f).length} 字段`;return String(f)}function KM(f,u){let _=f.replace(/[-_\s]/g,"").toLowerCase(),y=_==="ts"||_.endsWith("at")||_.endsWith("timestamp")||_.endsWith("heartbeat");if((typeof u==="string"||typeof u==="number")&&y){let l=zf(u);if(l!=="--")return l}if(f==="bodyText"&&typeof u==="string")return`${/^\s*[{[]/.test(u)?"JSON":"HTTP"} body ${u.length} chars`;return ty(u)}function DE(f){if(!f||typeof f!=="object"||Array.isArray(f))return[];return Object.entries(f)}function X1(f){return String(f).replace(/[^a-zA-Z0-9_-]/g,"_")}function KQ(f,u){return f&&typeof f==="object"&&!Array.isArray(f)?f[u]:void 0}function A2(f,u,_="未知"){let y=KQ(f?.labels,u);return typeof y==="string"&&y.length>0?y:_}function wE(f){return A2(f,"providerGatewayVersion")}function T6(f){return A2(f,"providerGatewayUpgradePolicy")}function KE(f){return A2(f,"providerGatewayStartedAt","")}function TE(f){let u=KQ(f?.labels,"unideskCapabilities");if(typeof u==="string")return u.split(",").map((_)=>_.trim()).filter(Boolean);return Array.isArray(u)?u.filter((_)=>typeof _==="string"):[]}function rE(f,u){return TE(f).includes(u)}function ZE(f,u){let _=KQ(f?.labels,u);return _===!0||_==="true"||_==="1"}function ZM(f){if(!rE(f,"host.ssh"))return{tone:"fail",label:"不可用",detail:"未声明 host.ssh"};if(!ZE(f,"hostSshConfigured"))return{tone:"warn",label:"未配置",detail:"缺少 SSH 环境变量"};if(!ZE(f,"hostSshKeyPresent"))return{tone:"warn",label:"缺 key",detail:"私钥未挂载"};return{tone:"ok",label:"可用",detail:A2(f,"hostSshTarget","host.ssh ready")}}function qM(f){if(!rE(f,"provider.upgrade"))return{tone:"fail",label:"不可用",detail:"未声明 provider.upgrade"};let u=T6(f);if(u!=="always-enabled")return{tone:"warn",label:"待确认",detail:`策略 ${u}`};return{tone:"ok",label:"可用",detail:"always-enabled"}}function ZQ(f){let u=typeof f==="string"&&f.length>0?f:"未知";if(u==="未知")return"版本未知";return u.startsWith("v")?u:`v${u}`}function ME(f){return f?.payload&&typeof f.payload==="object"&&!Array.isArray(f.payload)?f.payload:{}}function U2(f){return f?.result&&typeof f.result==="object"&&!Array.isArray(f.result)?f.result:{}}function Q2(f){let u=ME(f),_=U2(f);return(u.mode??_.mode)==="schedule"?"schedule":"plan"}function EM(f){let u=ME(f).source;return typeof u==="string"&&u.length>0?u:"unknown"}function HM(f){let u=U2(f),_=u.plan&&typeof u.plan==="object"&&!Array.isArray(u.plan)?u.plan:{},y=u.policy??_.policy;return typeof y==="string"&&y.length>0?y:"--"}function PE(f){let u=U2(f),_=u.plan&&typeof u.plan==="object"&&!Array.isArray(u.plan)?u.plan:{},y=u.targetProviderGatewayVersion??u.providerGatewayVersion??_.targetProviderGatewayVersion??_.providerGatewayVersion;return typeof y==="string"&&y.length>0?ZQ(y):"版本未知"}function SE(f){if(String(f?.status||"").toLowerCase()==="failed")return BE(f);if(H3(f))return"等待 provider 回传升级终态";let _=U2(f);if(typeof _.updaterContainerId==="string"&&_.updaterContainerId.length>0)return`updater ${_.updaterContainerId.slice(0,18)}`;if(typeof _.message==="string"&&_.message.length>0)return _.message;if(_.plan)return"升级计划已生成";return"无升级结果摘要"}function CE(f,u){return f.filter((_)=>_?.providerId===u&&_?.command==="provider.upgrade").sort((_,y)=>(Z3(y.updatedAt)??0)-(Z3(_.updatedAt)??0))}function VM(f){return f.find((u)=>Q2(u)==="schedule")||f[0]||null}function RE(f){return f?.runtime&&typeof f.runtime==="object"&&!Array.isArray(f.runtime)?f.runtime:{}}function qE(f){return f?.backend&&typeof f.backend==="object"&&!Array.isArray(f.backend)?f.backend:{}}function OM(f){return f?.repository&&typeof f.repository==="object"&&!Array.isArray(f.repository)?f.repository:{}}function O0({status:f,children:u}){let _=String(f||"unknown").toLowerCase();return Q("span",{className:`status-badge ${_}`},u||f||"unknown")}function _0({label:f,value:u,hint:_,tone:y,onClick:l,testId:$}){let j=typeof l==="function";return Q("article",{className:`metric-card ${y||""} ${j?"clickable":""}`,role:j?"button":void 0,tabIndex:j?0:void 0,"data-testid":$,onClick:l,onKeyDown:j?(J)=>{if(J.key==="Enter"||J.key===" ")J.preventDefault(),l()}:void 0},Q("div",{className:"metric-label"},f),Q("div",{className:"metric-value"},u),Q("div",{className:"metric-hint"},_))}function mf({title:f,eyebrow:u,actions:_,children:y,className:l}){return Q("section",{className:`panel ${l||""}`},Q("div",{className:"panel-head"},Q("div",null,u?Q("p",{className:"panel-eyebrow"},u):null,Q("h2",null,f)),_?Q("div",{className:"panel-actions"},_):null),Q("div",{className:"panel-body"},y))}function m0({title:f,data:u,onOpen:_,testId:y}){let[l,$]=hf(!1),j=u&&typeof u==="object"&&typeof u._loadRaw==="function"?u._loadRaw:null;async function J(){if(!j){_(f,u);return}$(!0);try{_(f,await j())}catch(F){_(f,{ok:!1,error:Pf(F,"读取原始 JSON 失败"),fallback:u})}finally{$(!1)}}return Q("button",{type:"button",className:"ghost-btn","data-testid":y,disabled:l,onClick:()=>void J()},l?"读取中":"查看原始JSON")}function XM({raw:f,onClose:u}){if(!f)return null;return Q("div",{className:"modal-backdrop",role:"presentation"},Q("section",{className:"raw-dialog",role:"dialog","aria-modal":"true","aria-label":f.title},Q("div",{className:"raw-dialog-head"},Q("h2",null,f.title),Q("button",{type:"button",className:"ghost-btn",onClick:u},"关闭")),Q("pre",{className:"raw-json","data-testid":"raw-json"},JSON.stringify(f.data,null,2))))}function xE({labels:f,limit:u=8}){let _=DE(f).slice(0,u);if(_.length===0)return Q("span",{className:"muted"},"无标签");return Q("div",{className:"chip-row"},_.map(([y,l])=>Q("span",{key:y,className:"data-chip"},Q("b",null,y),Q("span",null,ty(l)))))}function q3({node:f}){let u=wE(f);return Q("span",{className:`version-chip ${u==="未知"?"unknown":""}`,"data-testid":`gateway-version-${X1(f?.providerId||"unknown")}`},ZQ(u))}function EE({title:f,state:u,testId:_}){return Q("span",{className:`capability-badge ${u.tone}`,title:u.detail,"data-testid":_},Q("b",null,f),Q("strong",null,u.label),Q("small",null,u.detail))}function qQ({node:f}){let u=X1(f?.providerId||"unknown");return Q("div",{className:"node-availability-strip"},Q(EE,{title:"SSH 透传",state:ZM(f),testId:`ssh-availability-${u}`}),Q(EE,{title:"远程更新",state:qM(f),testId:`upgrade-availability-${u}`}))}function sy({data:f,empty:u="无数据"}){if(f===null||f===void 0)return Q("span",{className:"muted"},u);if(typeof f!=="object")return Q("span",{className:"summary-value"},ty(f));if(Array.isArray(f))return Q("span",{className:"summary-value"},`${f.length} 项列表`);let _=Object.entries(f).slice(0,5);if(_.length===0)return Q("span",{className:"muted"},u);return Q("div",{className:"summary-grid"},_.map(([y,l])=>Q("span",{key:y,className:"summary-item"},Q("b",null,y),Q("span",null,KM(y,l)))))}function J0({title:f,text:u}){return Q("div",{className:"empty-state"},Q("strong",null,f),Q("span",null,u))}function NM({onLogin:f}){let[u,_]=hf(sf.authUsername||"admin"),[y,l]=hf(""),[$,j]=hf(""),[J,F]=hf(!1);async function A(U){U.preventDefault(),F(!0),j("");try{let G=await wf("/login",{method:"POST",body:JSON.stringify({username:u,password:y})});f(G)}catch(G){j(Pf(G,"登录失败"))}finally{F(!1)}}return Q("main",{className:"login-screen","data-testid":"login-screen"},Q("section",{className:"login-card"},Q("div",{className:"login-brand"},Q("span",{className:"brand-mark"},"UD"),Q("div",null,Q("h1",null,"UniDesk"),Q("p",null,"Control Plane Login"))),Q("form",{className:"login-form",onSubmit:A},Q("label",null,"账号",Q("input",{name:"username",autoComplete:"username",value:u,onChange:(U)=>_(U.target.value)})),Q("label",null,"密码",Q("input",{name:"password",type:"password",autoComplete:"current-password",value:y,onChange:(U)=>l(U.target.value)})),Q(H0,{error:$}),Q("button",{type:"submit",disabled:J},J?"登录中":"登录")),Q("div",{className:"login-note"},"默认账号由 config.json 注入;公网入口只暴露前端登录面。")))}function LM({connection:f,lastRefresh:u,onRefresh:_,onLogout:y,session:l,clock:$,activeStatusItems:j=[]}){let J=[{key:"core",label:"核心",value:f.text,tone:f.ok?"ok":"fail",testId:"conn-text"},...Array.isArray(j)?j:[],{key:"refresh",label:"刷新",value:u?L0(u):"未刷新"},{key:"clock",label:s6,value:L0($)},{key:"user",label:"用户",value:l?.user?.username||"--",tone:"user"}];return Q("header",{className:"topbar"},Q("div",null,Q("p",{className:"eyebrow"},"Distributed Work Platform"),Q("h1",null,"UniDesk 控制平面")),Q(GE,{className:"global-top-status",title:"状态",items:J,actions:[Q("button",{key:"refresh",type:"button",className:"ghost-btn",onClick:_},"刷新"),Q("button",{key:"logout",type:"button",className:"ghost-btn danger",onClick:y},"退出")]}))}function YM({activeModule:f,activeTabs:u,onNavigate:_,collapsed:y,onToggle:l}){return Q("aside",{className:`rail ${y?"collapsed":""}`,"aria-label":"主模块"},Q("div",{className:"brand"},Q("span",{className:"brand-mark"},"UD"),Q("span",{className:"brand-text"},"UniDesk"),Q("button",{type:"button",className:"rail-toggle",onClick:l,"aria-label":y?"展开左侧边栏":"收起左侧边栏","data-testid":"rail-toggle"},y?"»":"«")),h4.map(($)=>Q("button",{key:$.id,type:"button",className:`module ${f===$.id?"active":""}`,onClick:()=>_($.id,u[$.id]||kl[$.id]||$.tabs[0]?.id||""),title:$.label,"data-route":b$(mu,$.id,u[$.id]||kl[$.id]||$.tabs[0]?.id||"")},Q("span",{className:"module-code"},$.code),Q("span",null,$.label))))}function BM({module:f,activeTab:u,onNavigate:_}){return Q("nav",{className:"tabs","aria-label":`${f.label} 子功能`},f.tabs.map((y)=>Q("button",{key:y.id,type:"button",className:`tab ${u===y.id?"active":""}`,onClick:()=>_(f.id,y.id),"data-route":b$(mu,f.id,y.id)},y.label)))}function DM({data:f,onRaw:u,onNavigate:_}){let y=f.overview||{},l=f.nodes.filter((A)=>A.status==="online"),$=f.pendingTasks||f.tasks.filter(H3),j=y.pendingTaskCount??$.length,J=f.tasks.slice(0,5),F=y.pgdata||{};return Q("div",{className:"page-grid overview-grid","data-testid":"overview-page"},Q(mf,{title:"核心指标",eyebrow:"Control"},Q("div",{className:"metric-grid"},Q(_0,{label:"数据库",value:y.dbReady?"READY":"WAIT",hint:"PostgreSQL internal network",tone:y.dbReady?"ok":"warn"}),Q(_0,{label:"PGDATA",value:Fu(F.databaseBytes),hint:`${F.volumeName||"unidesk_pgdata_10gb"} / ${F.databasePretty||"--"}`,tone:"ok",testId:"pgdata-usage-card"}),Q(_0,{label:"在线节点",value:y.onlineNodeCount??0,hint:`${y.nodeCount??0} registered`,tone:"ok"}),Q(_0,{label:"WebSocket",value:y.activeSocketCount??0,hint:"Provider ingress sockets"}),Q(_0,{label:"待处理任务",value:j,hint:j>0?"点击查看具体任务":`timeout ${E3(Math.floor((y.taskPendingTimeoutMs??0)/1000))}`,tone:j>0?"warn":"ok",onClick:()=>_("tasks","pending"),testId:"pending-task-card"}))),Q(mf,{title:"本机 Provider",eyebrow:"Self Connected"},l.length===0?Q(J0,{title:"暂无在线节点",text:"provider-gateway 未完成自接入"}):Q("div",{className:"node-card-list"},l.slice(0,4).map((A)=>Q(wM,{key:A.providerId,node:A,onRaw:u})))),Q(mf,{title:"待处理任务明细",eyebrow:`${j} Pending`,actions:Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("tasks","pending"),"data-testid":"pending-task-detail-link"},"进入任务调度")},$.length===0?Q(J0,{title:"当前无待处理",text:"queued / dispatched / running 超时后会自动转为 failed,避免总览长期卡住"}):Q("div",{className:"compact-list"},$.slice(0,5).map((A)=>Q(XE,{key:A.id,task:A,onRaw:u})))),Q(mf,{title:"最近任务",eyebrow:"Dispatch"},J.length===0?Q(J0,{title:"暂无任务",text:"可以在任务调度模块发起 docker.ps 或 echo"}):Q("div",{className:"compact-list"},J.map((A)=>Q(XE,{key:A.id,task:A,onRaw:u})))))}function wM({node:f,onRaw:u}){return Q("article",{className:"node-card"},Q("div",{className:"node-card-head"},Q("div",null,Q("strong",null,f.name),Q("code",null,f.providerId)),Q(O0,{status:f.status})),Q("div",{className:"node-version-line"},Q(q3,{node:f}),Q("span",null,`升级策略 ${T6(f)}`)),Q(qQ,{node:f}),Q(xE,{labels:f.labels,limit:6}),Q("div",{className:"node-card-foot"},Q("span",null,`心跳 ${zf(f.lastHeartbeat)}`),Q(m0,{title:`Provider ${f.providerId}`,data:f,onOpen:u,testId:`raw-node-${X1(f.providerId)}`})))}function TM({events:f,onRaw:u}){return Q(mf,{title:"事件摘要",eyebrow:"Latest 100"},f.length===0?Q(J0,{title:"暂无事件",text:"Provider 注册、心跳超时和任务状态会写入事件流"}):Q("div",{className:"table-wrap"},Q("table",null,Q("thead",null,Q("tr",null,Q("th",null,"ID"),Q("th",null,"类型"),Q("th",null,"来源"),Q("th",null,"摘要"),Q("th",null,"时间"),Q("th",null,"操作"))),Q("tbody",null,f.map((_)=>Q("tr",{key:_.id},Q("td",null,Q("code",null,_.id)),Q("td",null,Q(O0,{status:_.type},_.type)),Q("td",null,Q("code",null,_.source)),Q("td",null,Q(sy,{data:_.payload})),Q("td",null,zf(_.createdAt)),Q("td",null,Q(m0,{title:`Event ${_.id}`,data:_,onOpen:u}))))))))}function rM({logs:f,onRaw:u}){return Q(mf,{title:"服务日志",eyebrow:"Core Recent"},f.length===0?Q(J0,{title:"暂无日志",text:"backend-core 内存日志会在请求和 provider 事件后出现"}):Q("div",{className:"log-list"},f.slice(-80).reverse().map((_,y)=>Q("article",{key:y,className:`log-row ${_.level||"info"}`},Q("span",null,zf(_.ts)),Q("b",null,_.level||"info"),Q("strong",null,_.message||"log"),Q(sy,{data:_.data,empty:"无附加字段"}),Q(m0,{title:`Log ${_.message||y}`,data:_,onOpen:u})))))}function MM({nodes:f,onRaw:u}){return Q(mf,{title:"节点清单",eyebrow:`${f.length} Providers`},f.length===0?Q(J0,{title:"暂无 Provider 节点",text:"确认 provider-gateway 已连接 provider ingress"}):Q("div",{className:"table-wrap"},Q("table",{className:"node-list-table"},Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"Provider"),Q("th",null,"网关版本"),Q("th",null,"运维可用性"),Q("th",null,"资源标签"),Q("th",null,"连接时间"),Q("th",null,"最后心跳"),Q("th",null,"操作"))),Q("tbody",null,f.map((_)=>Q("tr",{key:_.providerId},Q("td",null,Q(O0,{status:_.status})),Q("td",null,Q("strong",null,_.name),Q("code",null,_.providerId)),Q("td",null,Q("div",{className:"gateway-cell"},Q(q3,{node:_}),Q("span",null,T6(_)))),Q("td",null,Q(qQ,{node:_})),Q("td",null,Q(xE,{labels:_.labels,limit:5})),Q("td",null,zf(_.connectedAt)),Q("td",null,zf(_.lastHeartbeat)),Q("td",null,Q(m0,{title:`Provider ${_.providerId}`,data:_,onOpen:u,testId:`raw-node-table-${X1(_.providerId)}`}))))))))}function PM({nodes:f}){let u=M6(()=>{let _=[];for(let y of f)for(let[l,$]of DE(y.labels))_.push({providerId:y.providerId,name:y.name,key:l,value:$});return _},[f]);return Q(mf,{title:"资源标签",eyebrow:"Structured Labels"},u.length===0?Q(J0,{title:"暂无标签",text:"provider-gateway 注册消息会同步资源标签"}):Q("div",{className:"label-matrix"},u.map((_)=>Q("article",{key:`${_.providerId}-${_.key}`,className:"label-card"},Q("span",null,_.key),Q("strong",null,ty(_.value)),Q("code",null,_.providerId)))))}function SM({nodes:f}){return Q(mf,{title:"心跳状态",eyebrow:"Provider Liveness"},f.length===0?Q(J0,{title:"无心跳",text:"等待 provider 注册和 heartbeat"}):Q("div",{className:"heartbeat-list"},f.map((u)=>Q("article",{key:u.providerId,className:"heartbeat-row"},Q("span",{className:`pulse ${u.status}`}),Q("div",null,Q("strong",null,u.name),Q("code",null,u.providerId)),Q("div",null,Q("span",null,"connected"),Q("b",null,zf(u.connectedAt))),Q("div",null,Q("span",null,"last heartbeat"),Q("b",null,zf(u.lastHeartbeat)))))))}function CM({nodes:f,systemStatuses:u,tasks:_,onRaw:y,refresh:l}){let[$,j]=hf(""),J=M6(()=>f.map((H)=>{let O=u.find((z)=>z.providerId===H.providerId);return{...H,systemCurrent:O?.current||null,systemHistory:O?.history||[],systemUpdatedAt:O?.updatedAt||null}}),[f,u]),F=J.find((H)=>H.providerId===$)||J[0]||null;if(h1(()=>{if(!$&&J[0])j(J[0].providerId)},[J.length,$]),!F)return Q(J0,{title:"暂无资源监控",text:"等待 provider 上报 CPU、内存和硬盘指标"});let A=F.systemCurrent,U=F.systemHistory||[],G=A?.cpu||{},W=A?.memory||{},K=A?.disk||{},E=U.length>0?U:A?[{at:A.collectedAt,cpuPercent:Mf(G.percent),memoryPercent:Mf(W.percent),diskPercent:Mf(K.percent)}]:[];return Q("div",{className:"monitor-page","data-testid":"node-monitor-page"},Q("div",{className:"docker-node-strip"},J.map((H)=>Q("button",{key:H.providerId,type:"button",className:`docker-node-tile ${F.providerId===H.providerId?"active":""}`,onClick:()=>j(H.providerId)},Q("span",{className:`pulse ${H.status}`}),Q("strong",null,H.name),Q("code",null,H.providerId),Q("span",null,H.systemCurrent?`CPU ${ly(H.systemCurrent.cpu?.percent)} / MEM ${ly(H.systemCurrent.memory?.percent)}`:"等待指标")))),Q("div",{className:"monitor-layout"},Q(mf,{title:"任务管理器视图",eyebrow:F.name,className:"monitor-main-panel",actions:A?Q(m0,{title:`System ${F.providerId}`,data:{current:A,history:U},onOpen:y}):null},!A?Q(J0,{title:"系统指标未上报",text:"provider-gateway 会周期性采集 /proc 与 df,并保存历史曲线"}):Q("div",null,Q("div",{className:"monitor-hero"},Q("div",null,Q("p",{className:"panel-eyebrow"},"Node Performance"),Q("h3",null,F.name),Q("div",{className:"docker-meta"},Q("span",null,`${G.cores||0} CPU cores`),Q("span",null,`load ${Mf(G.load1).toFixed(2)} / ${Mf(G.load5).toFixed(2)} / ${Mf(G.load15).toFixed(2)}`),Q("span",null,`memory actual ${Fu(W.usedBytes)} / ${Fu(W.totalBytes)}`),Q("span",null,`disk ${Fu(K.usedBytes)} / ${Fu(K.totalBytes)}`))),Q(O0,{status:A.ok?"online":"warn"},A.ok?"METRICS READY":"METRICS DEGRADED")),Q("div",{className:"monitor-chart-grid"},Q(WQ,{title:"CPU",metricKey:"cpuPercent",current:G.percent,points:E,detail:`${G.cores||0} cores / load ${Mf(G.load1).toFixed(2)}`,tone:"cpu",testId:"metric-chart-cpu"}),Q(WQ,{title:"Memory",metricKey:"memoryPercent",current:W.percent,points:E,detail:`${Fu(W.usedBytes)} actual / ${Fu(W.cacheBytes)} cache excluded`,tone:"memory",testId:"metric-chart-memory"}),Q(WQ,{title:"Disk",metricKey:"diskPercent",current:K.percent,points:E,detail:`${K.path||"/"} mounted ${K.mount||"--"}`,tone:"disk",testId:"metric-chart-disk"})),Q("div",{className:"monitor-summary-grid"},Q(_0,{label:"CPU 当前",value:ly(G.percent),hint:`history ${E.length} samples`,tone:"ok"}),Q(_0,{label:"实际内存",value:Fu(W.usedBytes),hint:`${ly(W.percent)} 不含缓存`}),Q(_0,{label:"硬盘已用",value:Fu(K.usedBytes),hint:ly(K.percent)}),Q(_0,{label:"更新时间",value:zf(F.systemUpdatedAt||A.collectedAt),hint:F.providerId})),Q(RM,{current:A,onRaw:y}))),Q("div",{className:"monitor-side-stack"},Q(kM,{provider:F,refresh:l,onRaw:y}),Q(mM,{provider:F,tasks:_,onRaw:y,limit:5}),Q(mf,{title:"采样说明",eyebrow:"Retention"},Q("div",{className:"monitor-note-list"},Q("article",null,Q("b",null,"CPU"),Q("span",null,"从 /proc/stat 计算相邻采样差值,首个采样用 load/cores 近似")),Q("article",null,Q("b",null,"Memory"),Q("span",null,"实际内存 = MemTotal - MemFree - Buffers - Cached - SReclaimable + Shmem,不把 page cache / buffer 计入占用")),Q("article",null,Q("b",null,"Disk"),Q("span",null,"使用 df -PB1 对配置路径采样,默认监控根文件系统")),Q("article",null,Q("b",null,"Process"),Q("span",null,"从 /proc/[pid] 采集进程 CPU、实际内存 RSS、线程数和磁盘 I/O 速率;表格默认按内存占用降序")))))))}function HE(f,u){if(u==="memory")return Mf(f.rssBytes);if(u==="cpu")return Mf(f.cpuPercent);if(u==="disk")return Mf(f.readBytesPerSecond)+Mf(f.writeBytesPerSecond);if(u==="pid")return Mf(f.pid);if(u==="threads")return Mf(f.threads);if(u==="runtime")return Mf(f.elapsedSeconds);if(u==="user")return String(f.user||"");return String(f.name||f.command||"")}function VE({value:f,label:u,tone:_}){let y=Math.max(1,Math.min(100,Mf(f)));return Q("div",{className:`process-meter ${_||""}`},Q("span",{style:{width:`${y}%`}}),Q("b",null,u))}function RM({current:f,onRaw:u}){let[_,y]=hf({key:"memory",direction:"desc"}),l=f?.processSummary&&typeof f.processSummary==="object"?f.processSummary:{},$=Array.isArray(f?.processes)?f.processes:[],j=M6(()=>{let F=_.direction==="asc"?1:-1;return[...$].sort((A,U)=>{let G=HE(A,_.key),W=HE(U,_.key);if(typeof G==="string"||typeof W==="string")return String(G).localeCompare(String(W),"zh-CN")*F;return(G-W)*F||Mf(A.pid)-Mf(U.pid)})},[$,_.key,_.direction]),J=(F,A)=>{let U=_.key===A,G=U?_.direction==="asc"?"ascending":"descending":"none";return Q("th",{"aria-sort":G},Q("button",{type:"button",className:`process-sort-button ${U?"active":""}`,"data-testid":`process-sort-${A}`,onClick:()=>y((W)=>({key:A,direction:W.key===A&&W.direction==="desc"?"asc":"desc"}))},F,Q("span",null,U?_.direction==="desc"?"↓":"↑":"↕")))};return Q("section",{className:"process-resource-panel","data-testid":"process-resource-panel"},Q("div",{className:"process-resource-head"},Q("div",null,Q("p",{className:"panel-eyebrow"},"Windows Resource Monitor Style"),Q("h3",null,"进程资源占用")),Q("div",{className:"process-resource-actions"},Q("span",{className:"data-chip"},"默认按内存排序"),Q("span",{className:"data-chip"},`${Mf(l.visible,j.length)} / ${Mf(l.total,j.length)} 进程`),Q(m0,{title:"Process Resource Snapshot",data:{processSummary:l,processes:$},onOpen:u,testId:"raw-process-resources"}))),j.length===0?Q(J0,{title:"暂无进程资源数据",text:"等待 provider-gateway 上报 /proc/[pid] 采样;旧版 provider 需要先升级到支持进程资源表的版本"}):Q("div",{className:"process-table-wrap"},Q("table",{className:"process-resource-table","data-testid":"process-resource-table"},Q("thead",null,Q("tr",null,J("进程","name"),J("PID","pid"),J("用户","user"),Q("th",null,"状态"),J("CPU","cpu"),J("内存","memory"),Q("th",null,"RSS"),J("磁盘 I/O","disk"),J("线程","threads"),J("运行时长","runtime"))),Q("tbody",null,j.map((F)=>{let A=Mf(F.readBytesPerSecond)+Mf(F.writeBytesPerSecond);return Q("tr",{key:`${F.pid}-${F.startedAt}`,"data-testid":`process-row-${X1(F.pid)}`,"data-memory-bytes":String(Mf(F.rssBytes)),"data-cpu-percent":String(Mf(F.cpuPercent)),"data-disk-bps":String(A),"data-pid":String(Mf(F.pid))},Q("td",null,Q("div",{className:"process-name-cell"},Q("strong",null,F.name||"--"),Q("span",{className:"process-command"},F.command||"--"))),Q("td",null,Q("code",null,F.pid||"--")),Q("td",null,F.user||`uid:${F.uid??"--"}`),Q("td",null,Q("span",{className:`process-state state-${X1(F.state||"unknown")}`},F.state||"?")),Q("td",null,Q(VE,{value:F.cpuPercent,label:zM(F.cpuPercent),tone:"cpu"})),Q("td",null,Q(VE,{value:F.memoryPercent,label:ly(F.memoryPercent),tone:"memory"})),Q("td",null,Fu(F.rssBytes)),Q("td",null,Q("div",{className:"process-io-cell"},Q("strong",null,UQ(A)),Q("span",null,`R ${UQ(F.readBytesPerSecond)} / W ${UQ(F.writeBytesPerSecond)}`))),Q("td",null,F.threads||0),Q("td",null,E3(Mf(F.elapsedSeconds))))})))))}function WQ({title:f,metricKey:u,current:_,points:y,detail:l,tone:$,testId:j}){let J=y.map((W)=>Math.max(0,Math.min(100,Mf(W[u])))),F=J.length>1?J:[J[0]||0,J[0]||0],A=F.length<=1?100:100/(F.length-1),U=F.map((W,K)=>`${(K*A).toFixed(2)},${(46-W*0.42).toFixed(2)}`).join(" "),G=`0,48 ${U} 100,48`;return Q("article",{className:`metric-chart ${$}`,"data-testid":j},Q("div",{className:"metric-chart-head"},Q("div",null,Q("span",null,f),Q("strong",null,ly(_))),Q("code",null,`${y.length} pts`)),Q("svg",{viewBox:"0 0 100 48",preserveAspectRatio:"none",role:"img","aria-label":`${f} usage curve`},Q("polygon",{points:G}),Q("polyline",{points:U}),Q("line",{x1:"0",x2:"100",y1:"24",y2:"24"})),Q("div",{className:"metric-chart-foot"},Q("span",null,"0%"),Q("span",null,l),Q("span",null,"100%")))}function j_(f){return Array.isArray(f)?f:[]}function xM(f){let u=j_(f?.core?.requests?.componentSummary);return[...j_(f?.frontend?.requests?.componentSummary),...u].sort((y,l)=>Mf(l.requestCount)-Mf(y.requestCount))}function vM(f){let u=j_(f?.core?.operations?.summary);return[...j_(f?.frontend?.operations?.summary),...u].sort((y,l)=>Mf(l.count)-Mf(y.count))}function bM(f){let u=j_(f?.core?.requests?.recentFailures).map((y)=>({source:"backend",...y}));return[...j_(f?.frontend?.requests?.recentFailures).map((y)=>({source:"frontend",...y})),...u].sort((y,l)=>(Z3(l.at)??0)-(Z3(y.at)??0)).slice(0,20)}function hM(f){let u=j_(f?.core?.operations?.recentSlowOperations);return[...j_(f?.frontend?.operations?.recentSlowOperations),...u].sort((y,l)=>Mf(l.durationMs)-Mf(y.durationMs)).slice(0,20)}function IM(f){let u=performance.memory,_=Number(u?.usedJSHeapSize);if(Number.isFinite(_)&&_>0)return _;let y=Number(f?.appBundleBytes);if(Number.isFinite(y)&&y>0)return y;return Mf(f?.process?.heapUsedBytes)}function cM({points:f}){let u=j_(f),_=u.map((W)=>Mf(W.mb)),y=Math.max(1,..._),l=Math.max(0,Math.min(..._,0)),$=Math.max(1,y-l),j=u.length>1?u:[...u,...u],J=j.length<=1?100:100/(j.length-1),F=j.map((W,K)=>{let E=Mf(W.mb);return`${(K*J).toFixed(2)},${(48-(E-l)/$*42).toFixed(2)}`}).join(" "),A=`0,50 ${F} 100,50`,U=u.at(-1),G=u[0];return Q("article",{className:"performance-memory-card","data-testid":"performance-memory-chart"},Q("div",{className:"performance-memory-head"},Q("strong",null,`Bwebui: ${U?`${Mf(U.mb).toFixed(1)}MB`:"--"}`),Q("span",null,u.length>0?`${u.length} samples`:"等待采样")),Q("svg",{viewBox:"0 0 100 50",preserveAspectRatio:"none",role:"img","aria-label":"Bwebui memory trend"},Q("polygon",{points:A}),Q("polyline",{points:F}),Q("line",{x1:"0",x2:"100",y1:"25",y2:"25"})),Q("div",{className:"performance-axis-row"},Q("span",null,G?L0(new Date(G.at)):"--"),Q("span",null,"时间"),Q("span",null,U?L0(new Date(U.at)):"--")),Q("div",{className:"performance-axis-row"},Q("span",null,`${l.toFixed(1)}`),Q("span",null,"(MB)"),Q("span",null,`${y.toFixed(1)}`)))}function pM({onRaw:f}){let[u,_]=hf({core:null,frontend:null}),[y,l]=hf([]),[$,j]=hf(""),[J,F]=hf(!1),[A,U]=hf(null),[G,W]=hf(!1);async function K(){F(!0),j("");try{let[C,S]=await Promise.all([wf(`${sf.apiBaseUrl}/performance`,{cache:"no-store"}),wf(`${sf.apiBaseUrl}/frontend-performance`,{cache:"no-store"})]);_({core:C,frontend:S});let B=IM(S);l((P)=>[...P,{at:new Date().toISOString(),mb:B/1048576}].slice(-80))}catch(C){j(Pf(C,"性能指标加载失败"))}finally{F(!1)}}h1(()=>{K();let C=setInterval(()=>void K(),5000);return()=>clearInterval(C)},[]);async function E(){W(!0),j(""),U(null);try{let C=await wf(`${sf.apiBaseUrl}/codex-queue-load-test`,{method:"POST",body:JSON.stringify({targetMs:1000,timeoutMs:90000,url:sf.frontendPublicUrl||window.location.origin})});U(C),K()}catch(C){j(Pf(C,"Codex Queue Playwright 测量失败"))}finally{W(!1)}}let H=xM(u),O=bM(u),z=vM(u),q=hM(u),Z=u.core?.process||{},V=u.frontend?.process||{},L=u.core?.database?.codexQueueStorage||{},r=Mf(L.total),N=A?.result||{},D=Mf(N.wallMs,NaN),x=Mf(N.networkIdleMs,NaN),c=N.withinTarget===!0,v=G?"running":A===null?"idle":A.measurementOk===!0?c?"passed":"slow":"failed";return Q("div",{className:"performance-page","data-testid":"performance-page"},Q("div",{className:"performance-hero"},Q("div",null,Q("p",{className:"panel-eyebrow"},"Unified Performance"),Q("h2",null,"性能面板"),Q("p",null,"按组件统计 HTTP 请求、失败率、P95 延迟,并汇总 backend/frontend 内部操作耗时。")),Q("div",{className:"inline-actions"},Q("button",{type:"button",className:"ghost-btn",onClick:()=>void E(),disabled:G,"data-testid":"codex-queue-load-test-button"},G?"测试中...":"测试 Codex Queue 加载"),Q("button",{type:"button",className:"ghost-btn",onClick:()=>void K(),disabled:J,"data-testid":"performance-refresh-button"},J?"刷新中":"刷新"),Q(m0,{title:"Performance Snapshot",data:u,onOpen:f,testId:"raw-performance"}))),Q(H0,{error:$}),Q("div",{className:"performance-top-grid"},Q(cM,{points:y}),Q("div",{className:"performance-metric-stack"},Q(_0,{label:"backend RSS",value:Fu(Z.rssBytes),hint:`heap ${Fu(Z.heapUsedBytes)}`}),Q(_0,{label:"frontend RSS",value:Fu(V.rssBytes),hint:`bundle ${Fu(u.frontend?.appBundleBytes)}`}),Q(_0,{label:"Codex PG 任务",value:r||"--",hint:L.ok?"unidesk_codex_queue_tasks":"等待表初始化",tone:L.ok?"ok":"warn"}),Q(_0,{label:"请求样本",value:Mf(u.core?.requests?.sampleCount)+Mf(u.frontend?.requests?.sampleCount),hint:"rolling window 3000"}))),Q(mf,{title:"Codex Queue 加载基准",eyebrow:"Playwright / target <1s",className:"codex-load-test-panel",actions:Q("div",{className:"panel-actions"},Q("button",{type:"button",className:"primary-btn",onClick:()=>void E(),disabled:G,"data-testid":"codex-queue-load-test-panel-button"},G?"正在运行 Playwright...":"手动触发测试"),A?Q(m0,{title:"Codex Queue Load Test",data:A,onOpen:f,testId:"raw-codex-queue-load-test"}):null)},Q("div",{className:"codex-load-test-grid","data-testid":"codex-queue-load-test-result"},Q(_0,{label:"总耗时",value:G?"运行中":Number.isFinite(D)?ku(D):"--",hint:A===null?"点击按钮启动远端 Playwright":`目标 ${ku(N.targetMs||1000)} / ${N.url||"Codex Queue"}`,tone:v==="passed"?"ok":v==="failed"||v==="slow"?"warn":""}),Q(_0,{label:"判定",value:G?"RUNNING":v==="passed"?"PASS <1s":v==="slow"?"SLOW":v==="failed"?"FAILED":"--",hint:A?.measurementOk===!1?String(A.error||N.error||"measurement failed").slice(0,120):"导航开始 -> DOMContentLoaded -> data-load-state=complete",tone:v==="passed"?"ok":v==="idle"||v==="running"?"":"fail"}),Q(_0,{label:"Network idle",value:Number.isFinite(x)?ku(x):"--",hint:`DOMContentLoaded ${ku(N.domContentLoadedMs)} / ${N.networkIdleReached===!1?"未在 5s 内空闲":"已空闲"}`,tone:Number.isFinite(x)&&x<=1000?"ok":"warn"}),Q(_0,{label:"组件耗时",value:Number.isFinite(Mf(N.componentLoadMs,NaN))?ku(N.componentLoadMs):"--",hint:`queue ${ku(N.queueMs)} / detail ${ku(N.detailMs)}`,tone:Mf(N.componentLoadMs)>1000?"warn":"ok"}),Q(_0,{label:"Trace 规模",value:Number.isFinite(Mf(N.transcriptRows,NaN))?String(N.transcriptRows):"--",hint:`${N.visibleTaskCount??0} visible tasks / ${N.partial?"preview":"complete"}`})),G?Q("div",{className:"performance-empty-line"},"正在通过 main-server Host SSH 启动 Playwright,完成后会显示 wall time、组件耗时和最慢 API。"):null,A&&Array.isArray(N.slowestApi)&&N.slowestApi.length>0?Q("div",{className:"table-wrap performance-table-wrap compact codex-load-api-table"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["API","状态","耗时"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,N.slowestApi.slice(0,5).map((C,S)=>Q("tr",{key:`${C.url}-${S}`},Q("td",null,Q("code",null,C.url)),Q("td",null,C.status),Q("td",null,ku(C.durationMs))))))):null),Q("div",{className:"performance-grid"},Q(mf,{title:"组件汇总",eyebrow:"Requests"},H.length===0?Q(J0,{title:"暂无请求样本",text:"刷新几次或打开页面后会自动形成组件统计"}):Q("div",{className:"table-wrap performance-table-wrap"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["组件","请求数","失败数","失败率","平均延迟","P95"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,H.map((C)=>Q("tr",{key:C.component},Q("td",null,Q("code",null,C.component)),Q("td",null,C.requestCount),Q("td",null,C.failureCount),Q("td",null,ly(Mf(C.failureRate)*100)),Q("td",null,ku(C.averageLatencyMs)),Q("td",null,ku(C.p95LatencyMs)))))))),Q(mf,{title:"最近失败请求",eyebrow:"Failures"},O.length===0?Q("div",{className:"performance-empty-line"},"最近没有失败请求"):Q("div",{className:"table-wrap performance-table-wrap compact"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["时间","来源","组件","状态","路径"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,O.map((C,S)=>Q("tr",{key:`${C.at}-${S}`},Q("td",null,zf(C.at)),Q("td",null,C.source),Q("td",null,Q("code",null,C.component)),Q("td",null,Q(O0,{status:"failed"},C.status)),Q("td",null,Q("code",null,C.path)))))))),Q(mf,{title:"内部操作汇总",eyebrow:"Operations"},z.length===0?Q(J0,{title:"暂无内部操作样本",text:"API 查询和代理请求会自动记录内部操作耗时"}):Q("div",{className:"table-wrap performance-table-wrap"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["服务","操作","次数","平均延迟","P95"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,z.map((C)=>Q("tr",{key:`${C.service}-${C.operation}`},Q("td",null,C.service),Q("td",null,Q("code",null,C.operation)),Q("td",null,C.count),Q("td",null,ku(C.averageLatencyMs)),Q("td",null,ku(C.p95LatencyMs)))))))),Q(mf,{title:"最近慢操作",eyebrow:"Slowest"},q.length===0?Q(J0,{title:"暂无慢操作",text:"后端会记录最近窗口内耗时最高的内部操作"}):Q("div",{className:"table-wrap performance-table-wrap"},Q("table",{className:"performance-table"},Q("thead",null,Q("tr",null,["时间","操作","耗时","结果","细节"].map((C)=>Q("th",{key:C},C)))),Q("tbody",null,q.map((C,S)=>Q("tr",{key:`${C.at}-${C.operation}-${S}`},Q("td",null,zf(C.at)),Q("td",null,Q("code",null,C.operation)),Q("td",null,ku(C.durationMs)),Q("td",null,C.ok?"成功":"失败"),Q("td",null,C.detail||"-")))))))))}function kM({provider:f,refresh:u,onRaw:_}){let[y,l]=hf(""),[$,j]=hf(null),[J,F]=hf("");async function A(U){l(U),F("");try{let G=await wf(`${sf.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:f.providerId,command:"provider.upgrade",payload:{mode:U,source:"frontend-resource-monitor",requestedAt:new Date().toISOString()}})});j({mode:U,...G}),await u()}catch(G){F(Pf(G,"升级命令下发失败"))}finally{l("")}}return Q(mf,{title:"Provider Gateway 升级",eyebrow:"Remote Control"},Q("div",{className:"upgrade-control","data-testid":"provider-upgrade-control"},Q("p",null,"通过 UniDesk WebSocket 向当前计算节点下发 provider.upgrade;预检只生成升级计划,执行升级会调度节点本地 updater 容器。"),Q("div",{className:"upgrade-target-line"},Q("span",null,"指定 Provider"),Q("code",null,f.providerId),Q(q3,{node:f})),Q("div",{className:"upgrade-actions"},Q("button",{type:"button",className:"ghost-btn",disabled:Boolean(y),onClick:()=>A("plan"),"data-testid":"upgrade-plan-button"},y==="plan"?"预检中":"预检升级"),Q("button",{type:"button",className:"ghost-btn danger",disabled:Boolean(y),onClick:()=>A("schedule"),"data-testid":"upgrade-schedule-button"},y==="schedule"?"调度中":"执行升级")),Q(H0,{error:J}),$?Q("div",{className:"upgrade-result"},Q(O0,{status:$.status||"queued"},$.status||"queued"),Q("span",null,`${$.mode==="schedule"?"执行升级":"预检升级"} 已下发`),Q("span",null,`指定版本 ${ZQ(wE(f))}`),Q("code",null,$.taskId||"--"),Q(m0,{title:"Provider Upgrade Dispatch",data:$,onOpen:_})):Q("span",{className:"muted"},"升级任务结果会进入任务历史;执行升级可能导致 provider 短暂重连。")))}function vE({records:f,onRaw:u,compact:_=!1}){if(f.length===0)return Q(J0,{title:"暂无远程更新记录",text:"该节点还没有 provider.upgrade 任务;执行预检或升级后会在这里形成结构化记录"});return Q("div",{className:`upgrade-record-table-wrap table-wrap ${_?"compact":""}`},Q("table",{className:"upgrade-record-table"},Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"模式"),Q("th",null,"任务"),Q("th",null,"来源"),Q("th",null,"耗时"),Q("th",null,"策略"),Q("th",null,"Gateway 版本"),Q("th",null,"结果记录"),Q("th",null,"更新时间"),Q("th",null,"操作"))),Q("tbody",null,f.map((y)=>Q("tr",{key:y.id,"data-testid":`gateway-upgrade-record-${X1(y.id)}`},Q("td",null,Q(O0,{status:y.status})),Q("td",null,Q("span",{className:`mode-chip ${Q2(y)}`},Q2(y)==="schedule"?"执行升级":"预检")),Q("td",null,Q("strong",null,"provider.upgrade"),Q("code",null,y.id)),Q("td",null,EM(y)),Q("td",null,Q(hE,{task:y})),Q("td",null,HM(y)),Q("td",null,Q("span",{className:"version-chip"},PE(y))),Q("td",null,Q("span",{className:`upgrade-outcome ${String(y.status||"").toLowerCase()}`},SE(y))),Q("td",null,zf(y.updatedAt)),Q("td",null,Q(m0,{title:`Provider Upgrade Task ${y.id}`,data:P6(y),onOpen:u})))))))}function mM({provider:f,tasks:u,onRaw:_,limit:y=5}){let l=CE(u,f.providerId).slice(0,y);return Q(mf,{title:"远程更新记录",eyebrow:f.providerId,actions:Q(q3,{node:f}),className:"provider-upgrade-records-panel"},Q("div",{"data-testid":`provider-upgrade-records-${X1(f.providerId)}`},Q(vE,{records:l,onRaw:_,compact:!0})))}function iM({nodes:f,tasks:u,onRaw:_}){let y=M6(()=>f.map(($)=>{let j=CE(u,$.providerId);return{node:$,records:j,latest:VM(j),capabilities:TE($)}}),[f,u]),l=y.reduce(($,j)=>$+j.records.length,0);return Q("div",{className:"gateway-page","data-testid":"gateway-version-page"},Q(mf,{title:"Provider Gateway 版本",eyebrow:`${f.length} Providers / ${l} 更新记录`},f.length===0?Q(J0,{title:"暂无 Provider 节点",text:"等待 provider-gateway 注册后显示版本号和升级记录"}):Q("div",{className:"table-wrap gateway-version-table-wrap"},Q("table",{className:"gateway-version-table"},Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"Provider"),Q("th",null,"Gateway 版本"),Q("th",null,"升级策略"),Q("th",null,"运维可用性"),Q("th",null,"运行时间"),Q("th",null,"能力"),Q("th",null,"最近远程更新"),Q("th",null,"操作"))),Q("tbody",null,y.map(($)=>Q("tr",{key:$.node.providerId},Q("td",null,Q(O0,{status:$.node.status})),Q("td",null,Q("strong",null,$.node.name),Q("code",null,$.node.providerId)),Q("td",null,Q(q3,{node:$.node})),Q("td",null,T6($.node)),Q("td",null,Q(qQ,{node:$.node})),Q("td",null,KE($.node)?zf(KE($.node)):"待新版上报"),Q("td",null,Q("div",{className:"capability-row"},$.capabilities.length===0?Q("span",{className:"muted"},"未声明"):$.capabilities.slice(0,5).map((j)=>Q("span",{key:j,className:"data-chip"},j)))),Q("td",null,$.latest?Q("div",{className:"latest-upgrade-cell"},Q(O0,{status:$.latest.status}),Q("span",null,`${Q2($.latest)==="schedule"?"执行升级":"预检"} / ${zf($.latest.updatedAt)}`),Q("small",null,`Gateway ${PE($.latest)}`),Q("small",null,SE($.latest))):Q("span",{className:"muted"},"暂无记录")),Q("td",null,Q(m0,{title:`Provider ${$.node.providerId}`,data:$.node,onOpen:_})))))))),Q(mf,{title:"远程更新记录",eyebrow:"Structured provider.upgrade records"},f.length===0?Q(J0,{title:"暂无记录",text:"没有 provider 节点时不会生成远程更新记录"}):Q("div",{className:"gateway-record-grid"},y.map(($)=>Q("article",{key:$.node.providerId,className:"gateway-record-card","data-testid":`gateway-records-${X1($.node.providerId)}`},Q("div",{className:"gateway-record-head"},Q("div",null,Q("strong",null,$.node.name),Q("code",null,$.node.providerId)),Q(q3,{node:$.node})),Q("div",{className:"gateway-record-meta"},Q("span",null,`心跳 ${zf($.node.lastHeartbeat)}`),Q("span",null,`策略 ${T6($.node)}`),Q("span",null,`${$.records.length} 条记录`)),Q(vE,{records:$.records.slice(0,8),onRaw:_,compact:!0}))))))}function gM(f){if(f==="running")return"online";if(f==="paused"||f==="restarting")return"warn";if(f==="exited"||f==="dead")return"offline";return"internal"}function bE(f){return/^[a-f0-9]{48,64}$/i.test(f)}function w6(f){let u=String(f?.name||""),_=String(f?.labels||"");return u==="unidesk_pgdata_10gb"||_.includes("com.docker.compose.volume=unidesk_pgdata_10gb")||u.toLowerCase().includes("pgdata")}function OE(f){let u=String(f?.name||""),_=String(f?.labels||"");if(w6(f))return 0;if(_.includes("com.docker.compose.project=unidesk"))return 1;if(!bE(u))return 2;return 3}function nM(f){return[...f].sort((u,_)=>{let y=OE(u)-OE(_);if(y!==0)return y;return String(u.name||"").localeCompare(String(_.name||""))})}function tM({nodes:f,dockerStatuses:u,onRaw:_}){let[y,l]=hf(""),$=M6(()=>f.map((q)=>{let Z=u.find((V)=>V.providerId===q.providerId);return{...q,dockerStatus:Z?.dockerStatus||null,dockerUpdatedAt:Z?.updatedAt||null}}),[f,u]),j=$.find((q)=>q.providerId===y)||$[0]||null;if(h1(()=>{if(!y&&$[0])l($[0].providerId)},[$.length,y]),!j)return Q(J0,{title:"暂无 Docker 节点",text:"等待 provider 上报 Docker daemon 状态"});let J=j.dockerStatus,F=j.providerId==="main-server",A=J?.counts||{},U=J?.daemon||{},G=J?.containers||[],W=J?.images||[],K=nM(J?.volumes||[]),E=F?K.find(w6):null,H=J?.networks||[],O=G.filter((q)=>q.state==="running"),z=G.filter((q)=>q.state!=="running");return Q("div",{className:"docker-page","data-testid":"docker-status-page"},Q("div",{className:"docker-node-strip"},$.map((q)=>Q("button",{key:q.providerId,type:"button",className:`docker-node-tile ${j.providerId===q.providerId?"active":""}`,onClick:()=>l(q.providerId)},Q("span",{className:`pulse ${q.status}`}),Q("strong",null,q.name),Q("code",null,q.providerId),Q("span",null,q.dockerStatus?`Docker ${q.dockerStatus.ok?"ready":"degraded"}`:"等待上报")))),Q("div",{className:"docker-layout"},Q(mf,{title:"Docker Desktop 视图",eyebrow:j.name,className:"docker-main-panel",actions:J?Q(m0,{title:`Docker ${j.providerId}`,data:J,onOpen:_}):null},!J?Q(J0,{title:"Docker 状态未上报",text:"provider-gateway 会在连接后周期性采集 docker info / ps / images / volume / network"}):Q("div",null,Q("div",{className:"docker-hero"},Q("div",null,Q("p",{className:"panel-eyebrow"},"Daemon"),Q("h3",null,U.name||j.providerId),Q("div",{className:"docker-meta"},Q("span",null,U.serverVersion?`Engine ${U.serverVersion}`:"Engine --"),Q("span",null,U.operatingSystem||"OS --"),Q("span",null,U.architecture||"arch --"),Q("span",null,`${U.cpus||0} CPU / ${Fu(U.memoryBytes)}`))),Q(O0,{status:J.ok?"online":"warn"},J.ok?"Docker Ready":"Docker Degraded")),Q("div",{className:"docker-metrics"},Q(_0,{label:"Containers",value:A.containers??G.length,hint:`${A.running??O.length} running / ${A.stopped??z.length} stopped`,tone:"ok"}),Q(_0,{label:"Images",value:A.images??W.length,hint:`${A.daemonImages??A.images??W.length} daemon images`}),Q(_0,{label:"Volumes",value:A.volumes??K.length,hint:F?E?"database volume visible":"database volume missing":"node local volumes",tone:E?"ok":""}),Q(_0,{label:"Networks",value:A.networks??H.length,hint:U.driver?`driver ${U.driver}`:"docker networks"})),F?Q(sM,{volume:E,volumeCount:K.length}):null,Q("div",{className:"docker-section-head"},Q("h3",null,"Containers"),Q("span",null,`updated ${zf(j.dockerUpdatedAt||J.collectedAt)}`)),Q("div",{className:"docker-container-table table-wrap","data-testid":"docker-container-table"},Q("table",null,Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"容器"),Q("th",null,"镜像"),Q("th",null,"端口"),Q("th",null,"运行时间"),Q("th",null,"大小"))),Q("tbody",null,G.length===0?Q("tr",null,Q("td",{colSpan:6},"暂无容器")):G.map((q)=>Q("tr",{key:`${q.id}-${q.name}`},Q("td",null,Q(O0,{status:gM(q.state)},q.state||"unknown")),Q("td",null,Q("strong",null,q.name||"--"),Q("code",null,q.id||"--")),Q("td",null,q.image||"--"),Q("td",null,q.ports||Q("span",{className:"muted"},"未发布")),Q("td",null,q.runningFor||q.status||"--"),Q("td",null,q.size||"--")))))))),Q("div",{className:"docker-side-stack"},Q(GQ,{title:"Images",items:W,render:(q)=>Q("article",{key:`${q.id}-${q.repository}`,className:"docker-side-row"},Q("strong",null,`${q.repository}:${q.tag}`),Q("span",null,q.size||"--"),Q("code",null,q.id||"--"))}),Q(GQ,{title:"Volumes",items:K,limit:K.length,render:(q)=>Q("article",{key:q.name,className:`docker-side-row volume-row ${F&&w6(q)?"database-volume":""}`,"data-testid":F&&w6(q)?"database-volume-row":void 0},Q("strong",null,q.name),Q("span",null,F&&w6(q)?"PostgreSQL":bE(String(q.name||""))?"anonymous":"named"),Q("code",null,q.mountpoint||q.driver||q.scope||"--"))}),Q(GQ,{title:"Networks",items:H,render:(q)=>Q("article",{key:q.id||q.name,className:"docker-side-row"},Q("strong",null,q.name),Q("span",null,q.driver||"--"),Q("code",null,q.id||"--"))}))))}function sM({volume:f,volumeCount:u}){return Q("section",{className:`docker-volume-focus ${f?"ready":"missing"}`,"data-testid":"database-volume-card"},Q("div",{className:"volume-focus-head"},Q("span",{className:"panel-eyebrow"},"Database Named Volume"),Q(O0,{status:f?"online":"warn"},f?"FOUND":"MISSING")),f?Q("div",{className:"volume-focus-body"},Q("strong",null,f.name),Q("span",null,"PostgreSQL data volume for unidesk-database"),Q("div",{className:"volume-route"},Q("code",null,f.mountpoint||"/var/lib/docker/volumes/unidesk_pgdata_10gb/_data"),Q("span",null,"->"),Q("code",null,"unidesk-database:/var/lib/postgresql/data")),Q("div",{className:"docker-meta compact"},Q("span",null,`driver ${f.driver||"--"}`),Q("span",null,`scope ${f.scope||"--"}`),Q("span",null,`${u} volumes reported`))):Q("div",{className:"volume-focus-body"},Q("strong",null,"unidesk_pgdata_10gb"),Q("span",null,"当前 Docker 快照没有发现数据库命名卷;请检查 provider-gateway 的 Docker volume 上报。")))}function GQ({title:f,items:u,render:_,limit:y}){let l=u.slice(0,y??12),$=Math.max(0,u.length-l.length);return Q(mf,{title:f,eyebrow:`${u.length} items`,className:"docker-side-panel"},u.length===0?Q(J0,{title:`暂无 ${f}`,text:"等待 Docker 状态采集"}):Q("div",{className:"docker-side-list"},l.map(_),$>0?Q("div",{className:"docker-side-more"},`+ ${$} more`):null))}function oM({microservices:f,onRaw:u,onNavigate:_}){let y=f.filter((l)=>qE(l).public===!1);return Q("div",{className:"microservice-page","data-testid":"microservice-catalog-page"},Q(mf,{title:"用户服务目录",eyebrow:"Provider Mounted User Services"},Q("div",{className:"metric-grid"},Q(_0,{label:"服务总数",value:f.length,hint:"config.json 用户服务登记"}),Q(_0,{label:"私有后端",value:y.length,hint:"不直接暴露公网",tone:"ok"}),Q(_0,{label:"D601 服务",value:f.filter((l)=>l.providerId==="D601").length,hint:"compute-node docker"}),Q(_0,{label:"集成前端",value:f.filter((l)=>l.frontend?.integrated).length,hint:"UniDesk React 页面"}))),Q(mf,{title:"服务映射",eyebrow:"Repo Reference + Runtime"},f.length===0?Q(J0,{title:"暂无用户服务",text:"在 config.json 的 microservices 中登记用户服务的 provider、仓库引用和后端映射"}):Q("div",{className:"table-wrap"},Q("table",{className:"microservice-table"},Q("thead",null,Q("tr",null,Q("th",null,"服务"),Q("th",null,"Provider"),Q("th",null,"代码引用"),Q("th",null,"Docker 引用"),Q("th",null,"后端映射"),Q("th",null,"开发入口"),Q("th",null,"运行态"),Q("th",null,"操作"))),Q("tbody",null,f.map((l)=>{let $=RE(l),j=OM(l),J=qE(l);return Q("tr",{key:l.id,"data-testid":`microservice-row-${X1(l.id)}`},Q("td",null,Q("strong",null,l.name),Q("code",null,l.id)),Q("td",null,Q("strong",null,$.providerName||l.providerId),Q("code",null,l.providerId)),Q("td",null,Q("span",null,j.url||"--"),Q("code",null,j.commitId||"--")),Q("td",null,Q("span",null,j.composeFile||"--"),Q("code",null,`${j.composeService||"--"} / ${j.containerName||"--"}`)),Q("td",null,Q(O0,{status:J.public?"warn":"online"},J.public?"public":"private"),Q("code",null,`${J.nodeBindHost||"--"}:${J.nodePort||"--"} -> ${J.proxyMode||"--"}`)),Q("td",null,Q("span",null,l.development?.sshPassthrough?"SSH 透传":"未配置"),Q("code",null,l.development?.worktreePath||"--")),Q("td",null,Q(O0,{status:$.providerStatus==="online"?"online":"warn"},$.providerStatus||"unknown"),Q(sy,{data:$.container,empty:"容器快照未上报"})),Q("td",null,Q("div",{className:"microservice-actions"},l.id==="findjob"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","findjob"),"data-testid":"open-findjob-button"},"打开"):null,l.id==="pipeline"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","pipeline"),"data-testid":"open-pipeline-button"},"打开"):null,l.id==="todo-note"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","todo-note"),"data-testid":"open-todo-note-button"},"打开"):null,l.id==="met-nonlinear"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","met-nonlinear"),"data-testid":"open-met-nonlinear-button"},"打开"):null,l.id==="claudeqq"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","claudeqq"),"data-testid":"open-claudeqq-button"},"打开"):null,l.id==="codex-queue"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","codex-queue"),"data-testid":"open-codex-queue-button"},"打开"):null,l.id==="project-manager"?Q("button",{type:"button",className:"ghost-btn",onClick:()=>_("apps","project-manager"),"data-testid":"open-project-manager-button"},"打开"):null,Q(m0,{title:`用户服务 ${l.id}`,data:l,onOpen:u}))))}))))))}function aM({nodes:f,onDispatched:u,onRaw:_}){let y=f.filter((v)=>v.status==="online"),[l,$]=hf(y[0]?.providerId||f[0]?.providerId||""),[j,J]=hf("docker.ps"),[F,A]=hf("frontend"),[U,G]=hf("operator-check"),[W,K]=hf("normal"),[E,H]=hf(!1),[O,z]=hf(""),[q,Z]=hf(!1),[V,L]=hf(null),[r,N]=hf("");h1(()=>{if(!l&&(y[0]?.providerId||f[0]?.providerId))$(y[0]?.providerId||f[0].providerId)},[f.length,y.length,l]);function D(){return{source:F,note:U,priority:W}}function x(){z(JSON.stringify(D(),null,2)),H(!0)}async function c(v){v.preventDefault(),Z(!0),N("");try{let C=E?JSON.parse(O||"{}"):D(),S=await wf(`${sf.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:l,command:j,payload:C})});L(S),await u()}catch(C){N(Pf(C,"下发失败"))}finally{Z(!1)}}return Q("div",{className:"page-grid dispatch-grid"},Q(mf,{title:"下发任务",eyebrow:"Real WebSocket Dispatch"},Q("form",{className:"dispatch-form",onSubmit:c},Q("label",null,"Provider",Q("select",{value:l,onChange:(v)=>$(v.target.value)},f.map((v)=>Q("option",{key:v.providerId,value:v.providerId},`${v.name} / ${v.providerId}`)))),Q("label",null,"Command",Q("select",{value:j,onChange:(v)=>J(v.target.value)},Q("option",{value:"docker.ps"},"docker.ps"),Q("option",{value:"host.ssh"},"host.ssh"),Q("option",{value:"microservice.http"},"microservice.http"),Q("option",{value:"echo"},"echo"))),Q("label",null,"来源",Q("input",{value:F,onChange:(v)=>A(v.target.value)})),Q("label",null,"备注",Q("input",{value:U,onChange:(v)=>G(v.target.value)})),Q("label",null,"优先级",Q("select",{value:W,onChange:(v)=>K(v.target.value)},Q("option",{value:"normal"},"normal"),Q("option",{value:"low"},"low"),Q("option",{value:"urgent"},"urgent"))),Q("div",{className:"dispatch-actions"},Q("button",{type:"button",className:"ghost-btn",onClick:x},"查看原始JSON"),Q("button",{type:"submit",disabled:q||!l},q?"下发中":"下发任务")),E?Q("label",{className:"raw-editor-label"},"高级 Payload",Q("textarea",{className:"raw-editor",value:O,onChange:(v)=>z(v.target.value)})):null,Q(H0,{error:r,wide:!0}))),Q(mf,{title:"下发结果",eyebrow:"Response"},V?Q("div",{className:"result-card"},Q(O0,{status:V.status||"queued"},V.status||"queued"),Q("dl",null,Q("dt",null,"Task ID"),Q("dd",null,Q("code",null,V.taskId||"--")),Q("dt",null,"Provider 在线"),Q("dd",null,ty(V.providerOnline))),Q(m0,{title:"Dispatch Response",data:V,onOpen:_})):Q(J0,{title:"等待操作",text:"任务响应会以结构化结果卡展示"})))}function XE({task:f,onRaw:u}){return Q("article",{className:"compact-row"},Q(O0,{status:f.status}),Q("div",null,Q("strong",null,f.command),Q("code",null,f.id)),Q("span",null,H3(f)?`已等待 ${zQ(f.updatedAt)}`:`耗时 ${E3(YE(f)??0)}`),Q(m0,{title:`Task ${f.id}`,data:P6(f),onOpen:u}))}function hE({task:f}){let u=YE(f),_=H3(f);return Q("div",{className:"task-duration"},Q("strong",null,u===null?"--":E3(u)),Q("span",null,_?`已运行 / 创建 ${zf(f.createdAt)}`:`创建 ${zf(f.createdAt)}`))}function dM({task:f}){let u=String(f?.status||"").toLowerCase(),_=f?.result,y=_&&typeof _==="object"&&!Array.isArray(_)?_:{},$=["exitCode","code","signal","timeoutMs","previousStatus","mode"].filter((j)=>y[j]!==void 0&&y[j]!==null);if(u==="failed"){let j=BE(f);return Q("div",{className:"task-diagnostic failed"},Q("b",null,"失败原因"),Q("span",{className:"diagnostic-reason"},ty(j)),$.length>0?Q("div",{className:"diagnostic-meta"},$.map((J)=>Q("span",{key:J,className:"data-chip"},Q("b",null,J),Q("span",null,ty(y[J]))))):null)}if(H3(f))return Q("div",{className:"task-diagnostic warn"},Q("b",null,"等待终态"),Q("span",null,`最后更新 ${zQ(f.updatedAt)} 前`));return Q("div",{className:"task-diagnostic ok"},Q("b",null,"完成摘要"),Q(sy,{data:_,empty:"无执行输出"}))}function eM({tasks:f,onRaw:u}){let _=f.filter(H3);return Q("div",{"data-testid":"pending-task-page"},Q(mf,{title:"待处理任务",eyebrow:`${_.length} Pending`},_.length===0?Q(J0,{title:"当前无待处理任务",text:"queued / dispatched / running 会在超时后自动转为 failed;历史记录仍可在任务历史中查看"}):Q("div",{className:"table-wrap","data-testid":"pending-task-table"},Q("table",null,Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"任务"),Q("th",null,"Provider"),Q("th",null,"已等待"),Q("th",null,"载荷摘要"),Q("th",null,"操作"))),Q("tbody",null,_.map((y)=>Q("tr",{key:y.id},Q("td",null,Q(O0,{status:y.status})),Q("td",null,Q("strong",null,y.command),Q("code",null,y.id)),Q("td",null,Q("code",null,y.providerId)),Q("td",null,zQ(y.updatedAt)),Q("td",null,Q(sy,{data:y.payload})),Q("td",null,Q(m0,{title:`Pending Task ${y.id}`,data:P6(y),onOpen:u})))))))))}function fP({tasks:f,onRaw:u}){return Q("div",{"data-testid":"task-history-page"},Q(mf,{title:"任务历史",eyebrow:`${f.length} Tasks`},f.length===0?Q(J0,{title:"暂无任务",text:"下发任务后会在这里看到生命周期"}):Q("div",{className:"table-wrap"},Q("table",{className:"task-history-table"},Q("thead",null,Q("tr",null,Q("th",null,"状态"),Q("th",null,"任务"),Q("th",null,"Provider"),Q("th",null,"任务耗时"),Q("th",null,"载荷摘要"),Q("th",null,"诊断信息"),Q("th",null,"更新时间"),Q("th",null,"操作"))),Q("tbody",null,f.map((_)=>Q("tr",{key:_.id,"data-testid":`task-row-${X1(_.id)}`},Q("td",null,Q(O0,{status:_.status})),Q("td",null,Q("strong",null,_.command),Q("code",null,_.id)),Q("td",null,Q("code",null,_.providerId)),Q("td",null,Q(hE,{task:_})),Q("td",null,Q(sy,{data:_.payload})),Q("td",null,Q(dM,{task:_})),Q("td",null,zf(_.updatedAt)),Q("td",null,Q(m0,{title:`Task ${_.id}`,data:P6(_),onOpen:u})))))))))}function uP({tasks:f,onRaw:u}){let _=f.filter((y)=>["succeeded","failed"].includes(y.status));return Q(mf,{title:"执行结果",eyebrow:"Finished Tasks"},_.length===0?Q(J0,{title:"暂无结果",text:"任务完成后展示 provider 返回的结构化摘要"}):Q("div",{className:"result-grid"},_.map((y)=>Q("article",{key:y.id,className:"result-card"},Q("div",{className:"node-card-head"},Q("strong",null,y.command),Q(O0,{status:y.status})),Q("code",null,y.id),Q(sy,{data:y.result,empty:"无执行输出"}),Q(m0,{title:`Task Result ${y.id}`,data:P6(y),onOpen:u})))))}function _P({data:f}){let u=f.overview||{};return Q("div",{className:"page-grid topology-grid"},Q(mf,{title:"公开入口",eyebrow:"Public"},Q("div",{className:"endpoint-list"},Q("article",null,Q("b",null,"Frontend"),Q("span",null,sf.frontendPublicUrl||window.location.origin),Q(O0,{status:"online"},"public")),Q("article",null,Q("b",null,"Provider Ingress"),Q("span",null,sf.providerIngressPublicUrl||"ws://public/ws/provider"),Q(O0,{status:"online"},"public")))),Q(mf,{title:"内部服务",eyebrow:"Docker Network Only"},Q("div",{className:"endpoint-list"},Q("article",null,Q("b",null,"backend-core API"),Q("span",null,"http://backend-core:8080"),Q(O0,{status:"internal"},"internal")),Q("article",null,Q("b",null,"database"),Q("span",null,"postgres://database:5432/unidesk"),Q(O0,{status:"internal"},"internal")))),Q(mf,{title:"运行态",eyebrow:"Runtime"},Q("div",{className:"metric-grid"},Q(_0,{label:"DB Ready",value:u.dbReady?"YES":"NO",hint:"internal health"}),Q(_0,{label:"Online Nodes",value:u.onlineNodeCount??0,hint:"provider-gateway self-link"}))))}function yP({session:f}){return Q(mf,{title:"认证策略",eyebrow:"Frontend Login"},Q("div",{className:"policy-grid"},Q("article",null,Q("span",null,"默认账号"),Q("strong",null,sf.authUsername||"admin")),Q("article",null,Q("span",null,"当前会话"),Q("strong",null,f?.user?.username||"--")),Q("article",null,Q("span",null,"Session TTL"),Q("strong",null,`${sf.sessionTtlSeconds||0}s`)),Q("article",null,Q("span",null,"API 访问"),Q("strong",null,"同源 Cookie 保护"))),Q("p",{className:"muted paragraph"},"浏览器只访问 frontend 同源接口;frontend 容器使用 Docker 内网代理 backend-core API。"))}function lP(){return Q(mf,{title:"安全边界",eyebrow:"Exposure Rule"},Q("div",{className:"security-board"},Q("article",{className:"allow"},Q("b",null,"允许公网"),Q("span",null,"frontend 登录入口"),Q("span",null,"provider ingress WebSocket/health")),Q("article",{className:"deny"},Q("b",null,"禁止公网"),Q("span",null,"backend-core REST API"),Q("span",null,"PostgreSQL database")),Q("article",null,Q("b",null,"数据库卷"),Q("span",null,"named volume unidesk_pgdata_10gb"),Q("span",null,"CLI stop/start 不删除数据卷"))))}function $P({activeModule:f,activeTab:u,data:_,session:y,refresh:l,onRaw:$,onNavigate:j}){if(f==="ops"&&u==="status")return Q(DM,{data:_,onRaw:$,onNavigate:j});if(f==="ops"&&u==="performance")return Q(pM,{onRaw:$});if(f==="ops"&&u==="events")return Q(TM,{events:_.events,onRaw:$});if(f==="ops"&&u==="logs")return Q(rM,{logs:_.logs,onRaw:$});if(f==="nodes"&&u==="list")return Q(MM,{nodes:_.nodes,onRaw:$});if(f==="nodes"&&u==="monitor")return Q(CM,{nodes:_.nodes,systemStatuses:_.systemStatuses,tasks:_.tasks,onRaw:$,refresh:l});if(f==="nodes"&&u==="docker")return Q(tM,{nodes:_.nodes,dockerStatuses:_.dockerStatuses,onRaw:$});if(f==="nodes"&&u==="gateway")return Q(iM,{nodes:_.nodes,tasks:_.tasks,onRaw:$});if(f==="nodes"&&u==="labels")return Q(PM,{nodes:_.nodes});if(f==="nodes"&&u==="heartbeats")return Q(SM,{nodes:_.nodes});if(f==="tasks"&&u==="dispatch")return Q(aM,{nodes:_.nodes,onDispatched:l,onRaw:$});if(f==="tasks"&&u==="pending")return Q(eM,{tasks:_.pendingTasks,onRaw:$});if(f==="tasks"&&u==="history")return Q(fP,{tasks:_.tasks,onRaw:$});if(f==="tasks"&&u==="results")return Q(uP,{tasks:_.tasks,onRaw:$});if(f==="apps"&&u==="catalog")return Q(oM,{microservices:_.microservices,onRaw:$,onNavigate:j});if(f==="apps"&&u==="todo-note")return Q(AE,{microservices:_.microservices,onRaw:$,apiBaseUrl:sf.apiBaseUrl});if(f==="apps"&&u==="findjob")return Q(yz,{microservices:_.microservices,onRaw:$,apiBaseUrl:sf.apiBaseUrl});if(f==="apps"&&u==="pipeline")return Q(_E,{microservices:_.microservices,onRaw:$,apiBaseUrl:sf.apiBaseUrl});if(f==="apps"&&u==="met-nonlinear")return Q(Fz,{microservices:_.microservices,onRaw:$,apiBaseUrl:sf.apiBaseUrl});if(f==="apps"&&u==="claudeqq")return Q(WG,{microservices:_.microservices,onRaw:$,apiBaseUrl:sf.apiBaseUrl});if(f==="apps"&&u==="codex-queue")return Q(_z,{microservices:_.microservices,onRaw:$,apiBaseUrl:sf.apiBaseUrl,initialTasksData:AM});if(f==="apps"&&u==="project-manager")return Q($E,{microservices:_.microservices,onRaw:$,apiBaseUrl:sf.apiBaseUrl});if(f==="config"&&u==="topology")return Q(_P,{data:_});if(f==="config"&&u==="auth")return Q(yP,{session:y});if(f==="config"&&u==="security")return Q(lP);return Q(J0,{title:"未找到页面",text:"请选择左侧主模块和顶部子功能标签"})}function jP({session:f,onLogout:u}){let _=rj(mu,window.location.pathname),[y,l]=hf(_.moduleId),[$,j]=hf({...kl,[_.moduleId]:_.tabId}),[J,F]=hf({overview:null,nodes:[],systemStatuses:[],dockerStatuses:[],microservices:[],events:[],tasks:[],pendingTasks:[],logs:[]}),[A,U]=hf({ok:!1,text:"连接中"}),[G,W]=hf(null),[K,E]=hf(new Date),[H,O]=hf(null),[z,q]=hf(!1),Z=r6.default.useRef(!1),V=mu.moduleById[y]||mu.modules[0],L=$[y]||kl[y]||V.tabs[0].id,r=Array.isArray(J.microservices)?J.microservices:[],N=r.length===0&&y==="apps"&&L==="codex-queue"?[UM]:r,D=N===r?J:{...J,microservices:N},x=y==="apps"?N.find((M)=>String(M?.id||"")===L):null,c=x?RE(x):{},v=V.tabs.find((M)=>M.id===L)?.label||L,C=x?[{key:"microservice",label:"用户服务",value:`${v} ${c.providerStatus==="online"?"在线":c.providerStatus||"未知"}`,tone:c.providerStatus==="online"?"ok":"warn",testId:"active-microservice-status"}]:[];async function S(){if(Z.current)return;Z.current=!0;try{let M=[],w=(n,_f)=>{M.push([n,wf(_f)])},Y=y==="ops"&&L==="status",R=Y||y==="config"&&L==="topology",k=Y||y==="nodes"||y==="tasks"&&L==="dispatch",p=y==="apps"&&L!=="codex-queue";if(R)w("overview",`${sf.apiBaseUrl}/overview`);if(k)w("nodes",`${sf.apiBaseUrl}/nodes`);if(y==="nodes"&&L==="monitor")w("systemStatuses",`${sf.apiBaseUrl}/nodes/system-status?limit=60`),w("tasks",`${sf.apiBaseUrl}/tasks?limit=120&summary=1`);else if(y==="nodes"&&L==="docker")w("dockerStatuses",`${sf.apiBaseUrl}/nodes/docker-status`);else if(y==="nodes"&&L==="gateway")w("tasks",`${sf.apiBaseUrl}/tasks?limit=300&summary=1`);else if(y==="tasks"&&L==="pending")w("pendingTasks",`${sf.apiBaseUrl}/tasks?status=pending&limit=100&summary=1`);else if(y==="tasks"&&(L==="history"||L==="results"))w("tasks",`${sf.apiBaseUrl}/tasks?limit=300&summary=1`);else if(Y)w("tasks",`${sf.apiBaseUrl}/tasks?limit=8&lite=1`),w("pendingTasks",`${sf.apiBaseUrl}/tasks?status=pending&limit=20&lite=1`);if(p)w("microservices",`${sf.apiBaseUrl}/microservices`);if(y==="ops"&&L==="events")w("events",`${sf.apiBaseUrl}/events?limit=100`);if(y==="ops"&&L==="logs")w("logs","/logs?limit=100");await Promise.all(M.map(async([n,_f])=>{let s=await _f,ff={};if(n==="overview")ff.overview=s;if(n==="nodes")ff.nodes=s.nodes||[];if(n==="systemStatuses")ff.systemStatuses=s.systemStatuses||[];if(n==="dockerStatuses")ff.dockerStatuses=s.dockerStatuses||[];if(n==="microservices")ff.microservices=s.microservices||[];if(n==="events")ff.events=s.events||[];if(n==="tasks")ff.tasks=s.tasks||[];if(n==="pendingTasks")ff.pendingTasks=s.tasks||[];if(n==="logs")ff.logs=s.logs||[];F((Kf)=>({...Kf,...ff}))})),U({ok:!0,text:"核心在线"}),W(new Date)}catch(M){if(U({ok:!1,text:Pf(M,"连接失败")}),M.status===401)u(!1)}finally{Z.current=!1}}h1(()=>{let M=()=>{if(!zE())return;S()};M();let w=setInterval(M,WM(y,L)),Y=()=>{if(zE())M()};return document.addEventListener("visibilitychange",Y),()=>{clearInterval(w),document.removeEventListener("visibilitychange",Y)}},[y,L]),h1(()=>{let M=setInterval(()=>E(new Date),1000);return()=>clearInterval(M)},[]),h1(()=>{let M=Wz(mu,window.location.pathname);if(M&&window.location.pathname!==M)window.history.replaceState(null,"",M)},[]),h1(()=>{let M=()=>{let w=rj(mu,window.location.pathname);l(w.moduleId),j((Y)=>({...Y,[w.moduleId]:w.tabId})),O(null)};return window.addEventListener("popstate",M),()=>window.removeEventListener("popstate",M)},[]),h1(()=>{window.scrollTo({top:0,left:0,behavior:"auto"})},[y,L]);function B(M,w,Y="push"){let R=mu.moduleById[M]?M:mu.fallbackTarget.moduleId,k=mu.moduleById[R]?.tabs.some((n)=>n.id===w)?w:kl[R]||mu.moduleById[R]?.tabs[0]?.id||mu.fallbackTarget.tabId;l(R),j((n)=>({...n,[R]:k}));let p=b$(mu,R,k);if(window.location.pathname!==p){let n=Y==="replace"?"replaceState":"pushState";window.history[n](null,"",p)}}function P(M,w){O({title:M,data:w})}return Q("div",{className:`shell ${z?"rail-collapsed":""}`,"data-testid":"app-shell"},Q(YM,{activeModule:y,activeTabs:$,onNavigate:B,collapsed:z,onToggle:()=>q((M)=>!M)}),Q("main",{className:"workspace"},Q(LM,{connection:A,lastRefresh:G,onRefresh:S,onLogout:()=>u(!0),session:f,clock:K,activeStatusItems:C}),Q(BM,{module:V,activeTab:L,onNavigate:B}),Q($P,{activeModule:y,activeTab:L,data:D,session:f,refresh:S,onRaw:P,onNavigate:B})),Q(XM,{raw:H,onClose:()=>O(null)}))}function JP(){let[f,u]=hf(!0),[_,y]=hf(null);async function l(){u(!0);try{let j=await wf("/api/session");y(j.authenticated?j:null)}catch{y(null)}finally{u(!1)}}async function $(j){if(j)try{await wf("/logout",{method:"POST"})}catch{}y(null)}if(h1(()=>{l()},[]),f)return Q("main",{className:"loading-screen"},Q("div",{className:"brand-mark"},"UD"),Q("span",null,"加载会话"));if(!_)return Q(NM,{onLogin:y});return Q(jP,{session:_,onLogout:$})}var IE=document.getElementById("root");if(IE===null)throw Error("root element not found");NE.createRoot(IE).render(Q(JP));})(); diff --git a/src/components/frontend/public/style.css b/src/components/frontend/public/style.css index 2c646818..d8b587bc 100644 --- a/src/components/frontend/public/style.css +++ b/src/components/frontend/public/style.css @@ -1767,8 +1767,7 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent-2); } min-height: 0; max-height: calc(100vh - 318px); } -.codex-task-pagination, -.codex-lazy-detail-callout { +.codex-task-pagination { display: flex; flex-wrap: wrap; align-items: center; @@ -1782,17 +1781,6 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent-2); } color: var(--muted); font-size: 12px; } -.codex-lazy-detail-callout { - margin: 8px 0; -} -.codex-lazy-detail-callout > div { - display: grid; - gap: 2px; - min-width: min(100%, 280px); -} -.codex-lazy-detail-callout strong { - color: var(--text); -} .codex-task-pagination code { color: var(--accent-2); } @@ -1862,17 +1850,6 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent-2); } } .codex-task-card.unread-terminal { padding-right: 23px; - border-color: rgba(215, 161, 58, 0.32); - background: - linear-gradient(135deg, rgba(78, 183, 168, 0.09), #0a1015 42%), - #0a1015; -} -.codex-task-card.unread-terminal.selected, -.codex-task-card.unread-terminal:hover { - border-color: rgba(215, 161, 58, 0.62); - background: - linear-gradient(135deg, rgba(78, 183, 168, 0.18), #0c181c 42%), - #0c181c; } .codex-task-card:focus-visible { outline: 2px solid var(--accent); @@ -2561,30 +2538,6 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent-2); } .codex-detail-grid { grid-template-columns: minmax(320px, 1fr) minmax(320px, 1fr); } -.codex-prompt-panel { - grid-column: 1 / -1; -} -.codex-prompt-detail { - display: grid; - gap: 9px; - min-width: 0; -} -.codex-prompt-meta { - display: flex; - flex-wrap: wrap; - gap: 6px; - align-items: center; - min-width: 0; -} -.codex-prompt-meta span:not(.status-badge) { - max-width: 100%; - padding: 3px 7px; - border: 1px solid var(--line-soft); - color: var(--muted); - background: rgba(255,255,255,0.025); - font-size: 11px; - overflow-wrap: anywhere; -} .codex-prompt-full { max-height: 360px; margin: 0; @@ -2629,14 +2582,6 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent-2); } flex: 0 0 auto; color: var(--muted); } -.codex-prompt-reference-full { - max-height: 460px; - border-color: rgba(78, 183, 168, 0.28); - border-left-color: rgba(78, 183, 168, 0.62); - background: - linear-gradient(90deg, rgba(78, 183, 168, 0.08), transparent 34%), - rgba(6, 10, 13, 0.86); -} .codex-prompt-final-full { max-height: 560px; border-color: rgba(215, 161, 58, 0.34); diff --git a/src/components/frontend/src/app.tsx b/src/components/frontend/src/app.tsx index 18c8cd09..f0ff44ba 100644 --- a/src/components/frontend/src/app.tsx +++ b/src/components/frontend/src/app.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { BEIJING_TIME_LABEL, fmtClock, fmtDate } from "./time"; import { createRoot } from "react-dom/client"; import { ClaudeQqPage } from "./claudeqq"; import { CodexQueuePage } from "./codex-queue"; @@ -73,16 +74,6 @@ function taskRawButtonData(task: any): any { return task?._summaryOnly ? { ...task, _loadRaw: () => loadTaskRawData(task) } : task; } -function fmtDate(value: any): string { - if (!value) return "--"; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return "--"; - return date.toLocaleString("zh-CN", { hour12: false }); -} - -function fmtClock(value: Date): string { - return value.toLocaleTimeString("zh-CN", { hour12: false }); -} function fmtDuration(seconds: number): string { if (!Number.isFinite(seconds)) return "--"; @@ -191,6 +182,12 @@ function summarizeValue(value: any): string { } function summarizeFieldValue(key: string, value: any): string { + const normalizedKey = key.replace(/[-_\s]/g, "").toLowerCase(); + const looksLikeTimeKey = normalizedKey === "ts" || normalizedKey.endsWith("at") || normalizedKey.endsWith("timestamp") || normalizedKey.endsWith("heartbeat"); + if ((typeof value === "string" || typeof value === "number") && looksLikeTimeKey) { + const formatted = fmtDate(value); + if (formatted !== "--") return formatted; + } if (key === "bodyText" && typeof value === "string") { const kind = /^\s*[{[]/.test(value) ? "JSON" : "HTTP"; return `${kind} body ${value.length} chars`; @@ -504,7 +501,7 @@ function TopBar({ connection, lastRefresh, onRefresh, onLogout, session, clock, { key: "core", label: "核心", value: connection.text, tone: connection.ok ? "ok" : "fail", testId: "conn-text" }, ...(Array.isArray(activeStatusItems) ? activeStatusItems : []), { key: "refresh", label: "刷新", value: lastRefresh ? fmtClock(lastRefresh) : "未刷新" }, - { key: "clock", label: "时间", value: fmtClock(clock) }, + { key: "clock", label: BEIJING_TIME_LABEL, value: fmtClock(clock) }, { key: "user", label: "用户", value: session?.user?.username || "--", tone: "user" }, ]; return h("header", { className: "topbar" }, diff --git a/src/components/frontend/src/claudeqq.tsx b/src/components/frontend/src/claudeqq.tsx index e7d38ee2..43ca04b0 100644 --- a/src/components/frontend/src/claudeqq.tsx +++ b/src/components/frontend/src/claudeqq.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { fmtClock, fmtDate } from "./time"; import { errorMessage, requestJson as requestUniDeskJson } from "./unidesk-error"; import { UniDeskErrorBanner } from "./unidesk-error-banner"; @@ -9,16 +10,6 @@ const { useEffect } = React; const useState: any = React.useState; const PRIMARY_PRIVATE_CHAT = { label: "主用户私聊账号", userId: 645275593 }; -function fmtDate(value: any): string { - if (!value) return "--"; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return "--"; - return date.toLocaleString("zh-CN", { hour12: false }); -} - -function fmtClock(value: Date): string { - return value.toLocaleTimeString("zh-CN", { hour12: false }); -} function numberText(value: any): string { const number = Number(value); diff --git a/src/components/frontend/src/codex-queue.tsx b/src/components/frontend/src/codex-queue.tsx index 60871a74..8382c062 100644 --- a/src/components/frontend/src/codex-queue.tsx +++ b/src/components/frontend/src/codex-queue.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { fmtClock, fmtDate } from "./time"; import { TraceView, codexTracePort } from "./trace"; import { errorMessage, requestJson as requestUniDeskJson } from "./unidesk-error"; import { UniDeskErrorBanner } from "./unidesk-error-banner"; @@ -11,7 +12,6 @@ const useState: any = React.useState; const codexTranscriptChunkLimit = 120; const codexInitialTaskLimit = 24; const codexMoreTaskLimit = 48; -const codexLocalReadRetention = 300; const queueErrorPreviewLength = 1200; function isDocumentVisible(): boolean { @@ -22,16 +22,6 @@ function errorText(error: unknown, fallback = "操作失败"): string { return errorMessage(error, fallback); } -function fmtDate(value: any): string { - if (!value) return "--"; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return "--"; - return date.toLocaleString("zh-CN", { hour12: false }); -} - -function fmtClock(value: Date): string { - return value.toLocaleTimeString("zh-CN", { hour12: false }); -} function fmtDuration(ms: any): string { const value = Number(ms); @@ -45,6 +35,44 @@ function fmtDuration(ms: any): string { return `${seconds}s`; } +function timestampMs(value: any): number | null { + if (value === null || value === undefined || value === "") return null; + const ms = value instanceof Date ? value.getTime() : new Date(value).getTime(); + return Number.isFinite(ms) ? ms : null; +} + +function fmtRelativeAge(value: any, nowMs = Date.now()): string { + const atMs = timestampMs(value); + if (atMs === null) return "--"; + const totalSeconds = Math.max(0, Math.floor((nowMs - atMs) / 1000)); + if (totalSeconds < 1) return "刚刚"; + const days = Math.floor(totalSeconds / 86400); + const hours = Math.floor((totalSeconds % 86400) / 3600); + const minutes = Math.floor((totalSeconds % 3600) / 60); + const seconds = totalSeconds % 60; + if (days > 0) return `${days}天${hours > 0 ? `${hours}小时` : ""}前`; + if (hours > 0) return `${hours}小时${minutes > 0 ? `${minutes}分钟` : ""}前`; + if (minutes > 0) return `${minutes}分钟${seconds}秒前`; + return `${seconds}秒前`; +} + +function latestTimestampValue(...values: any[]): string { + let best = ""; + let bestMs = -Infinity; + for (const value of values) { + const text = String(value || ""); + if (text.length === 0) continue; + const ms = timestampMs(value); + if (ms !== null && ms >= bestMs) { + best = text; + bestMs = ms; + } else if (best.length === 0) { + best = text; + } + } + return best; +} + function fmtPreciseMs(ms: any): string { const value = Number(ms); if (!Number.isFinite(value) || value < 0) return "--"; @@ -174,7 +202,6 @@ function activeTaskIds(queue: any): string[] { const allQueuesId = "__all__"; const queueMobileMediaQuery = "(max-width: 760px)"; const queueDesktopMediaQuery = "(min-width: 761px)"; -const codexReadAtStorageKey = "unidesk:codex-queue:read-at:v1"; function isAllQueues(queueId: string): boolean { return !queueId || queueId === allQueuesId; @@ -571,6 +598,25 @@ function attemptExecutionSummary(task: any, attempt: any): AnyRecord { return objectRecord(attempt?.execution) || taskExecutionSummary(task); } +function attemptExecutionUpdatedAt(task: any, attempt: any, attemptIndex: any, execution: AnyRecord): string { + const summary = taskTraceSummary(task); + const currentAttempt = Number(summary?.currentAttempt || task?.currentAttempt || 0); + const numericAttempt = Number(attemptIndex); + const isCurrentAttempt = Number.isFinite(numericAttempt) && numericAttempt > 0 && numericAttempt === currentAttempt; + const activeTaskUpdatedAt = latestTimestampValue(task?.updatedAt, summary?.updatedAt); + if (isCurrentAttempt && !attempt?.finishedAt && activeTaskUpdatedAt.length > 0) return activeTaskUpdatedAt; + return String( + attempt?.updatedAt + || attempt?.finishedAt + || execution.effectiveEndAt + || (isCurrentAttempt ? activeTaskUpdatedAt : "") + || activeTaskUpdatedAt + || task?.finishedAt + || task?.startedAt + || "", + ); +} + function attemptFinalResponseText(task: any, attempt: any): string { const text = String(attempt?.finalResponse || attempt?.finalResponsePreview || ""); if (Object.prototype.hasOwnProperty.call(attempt || {}, "finalResponse") || Object.prototype.hasOwnProperty.call(attempt || {}, "finalResponsePreview")) return text.trimEnd(); @@ -632,6 +678,104 @@ function taskTraceSteps(task: any, attemptIndex: any = null): any[] { return Array.isArray(task?._traceSteps) ? task._traceSteps : []; } +function traceStepSummaryLines(step: any): string[] { + return (Array.isArray(step?.summaryLines) ? step.summaryLines : []).map((line: any) => String(line || "")); +} + +function traceStepFileChangeMethod(step: any): string { + const status = String(step?.status || "").trim(); + if (status.length > 0) return status; + const text = traceStepSummaryLines(step).join("\n"); + return /^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(text)?.[1] || ""; +} + +function isFileChangeLifecycleSummaryLine(line: string): boolean { + return /^item\/(?:started|completed): file changes status=/u.test(String(line || "").trim()); +} + +function fileChangeStatusFromStep(step: any): string { + const lines = traceStepSummaryLines(step); + for (let index = lines.length - 1; index >= 0; index -= 1) { + const status = /file changes status=([A-Za-z0-9_-]+)/u.exec(lines[index] || "")?.[1]; + if (status) return status; + } + const method = traceStepFileChangeMethod(step); + if (method === "item/fileChange/outputDelta") return "updated"; + if (method === "item/started") return "started"; + if (method === "item/completed") return "completed"; + return method.replace(/^item\//u, "") || String(step?.status || "changed"); +} + +function isFileChangeTraceStep(step: any): boolean { + if (String(step?.kind || "") !== "edited") return false; + const title = String(step?.title || ""); + const status = String(step?.status || ""); + const text = traceStepSummaryLines(step).join("\n"); + if (title === "Edited files") return true; + if (/^item\/fileChange\//u.test(status)) return true; + if ((status === "item/started" || status === "item/completed") && /file changes status=/u.test(text)) return true; + if (/^Success\. Updated the following files:/mu.test(text)) return true; + if (/^diff --git /mu.test(text)) return true; + return /^([AMDRCU?]{1,2})\s+\S+/mu.test(text); +} + +function mergeFileChangeTraceStepGroup(group: any[]): any { + if (group.length <= 1) return group[0]; + const outputStep = group.find((step) => traceStepFileChangeMethod(step) === "item/fileChange/outputDelta") || group.find((step) => traceStepSummaryLines(step).some((line) => !isFileChangeLifecycleSummaryLine(line))) || group.at(-1) || group[0]; + const rawSeqs = group.flatMap((step) => Array.isArray(step?.rawSeqs) ? step.rawSeqs : [step?.seq]).filter((seq) => seq !== undefined); + const summaryLines = group + .flatMap(traceStepSummaryLines) + .filter((line) => line.trim().length > 0 && !isFileChangeLifecycleSummaryLine(line)); + const finalStep = group[group.length - 1] || outputStep; + return { + ...outputStep, + at: outputStep?.at || finalStep?.at, + title: String(outputStep?.title || "Edited files"), + status: fileChangeStatusFromStep(finalStep), + summaryLines: summaryLines.length > 0 ? summaryLines : traceStepSummaryLines(outputStep), + rawSeqs, + }; +} + +function coalesceFileChangeTraceSteps(steps: any[]): any[] { + const rows = Array.isArray(steps) ? steps : []; + const merged: any[] = []; + let group: any[] = []; + const flush = () => { + if (group.length > 0) merged.push(mergeFileChangeTraceStepGroup(group)); + group = []; + }; + for (const step of rows) { + if (isFileChangeTraceStep(step)) { + if (traceStepFileChangeMethod(step) === "item/started" && group.length > 0) flush(); + group.push(step); + if (traceStepFileChangeMethod(step) === "item/completed") flush(); + continue; + } + flush(); + merged.push(step); + } + flush(); + return merged; +} + +function executionSummaryWithDisplayedSteps(execution: AnyRecord, steps: any[]): AnyRecord { + if (steps.length === 0) return execution; + const counts = steps.reduce((memo: AnyRecord, step: any) => { + const kind = String(step?.kind || ""); + if (kind === "explored") memo.readCount += 1; + else if (kind === "edited") memo.editCount += 1; + else if (kind === "ran") memo.runCount += 1; + return memo; + }, { readCount: 0, editCount: 0, runCount: 0 }); + return { + ...execution, + ...counts, + toolCallCount: counts.readCount + counts.editCount + counts.runCount, + stepCount: steps.length, + }; +} + function taskTraceStepsLoaded(task: any, attemptIndex: any = null): boolean { if (attemptIndex !== null && attemptIndex !== undefined) { const byAttempt = objectRecord(task?._traceStepsLoadedByAttempt) || {}; @@ -644,6 +788,20 @@ function taskTraceStepDetails(task: any): AnyRecord { return task?._traceStepDetails && typeof task._traceStepDetails === "object" && !Array.isArray(task._traceStepDetails) ? task._traceStepDetails : {}; } +function attemptSegmentIndex(attempt: any, position: number): number { + const raw = Number(attempt?.index); + return Number.isFinite(raw) ? raw : position + 1; +} + +function isSyntheticAttemptSegment(attempt: any, attemptIndex: any): boolean { + return Boolean(attempt?.synthetic) || Number(attemptIndex) <= 0; +} + +function attemptDataIndex(attemptIndex: any): string | undefined { + const value = Number(attemptIndex); + return Number.isFinite(value) ? String(value) : undefined; +} + function taskDurationLabel(task: any): string { const timing = task?.timing && typeof task.timing === "object" ? task.timing : {}; const status = String(task?.status || ""); @@ -685,46 +843,6 @@ function taskIsUnreadTerminal(task: any): boolean { return !task?.readAt; } -function loadLocalReadAt(): AnyRecord { - if (typeof window === "undefined") return {}; - try { - const parsed = JSON.parse(window.localStorage.getItem(codexReadAtStorageKey) || "{}"); - return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? trimLocalReadAt(parsed) : {}; - } catch { - return {}; - } -} - -function trimLocalReadAt(readAtByTask: AnyRecord): AnyRecord { - const entries = Object.entries(readAtByTask || {}) - .filter(([, value]) => typeof value === "string" && value.length > 0) - .sort((left, right) => { - const leftTime = Date.parse(String(left[1] || "")); - const rightTime = Date.parse(String(right[1] || "")); - return (Number.isFinite(rightTime) ? rightTime : 0) - (Number.isFinite(leftTime) ? leftTime : 0); - }) - .slice(0, codexLocalReadRetention); - return Object.fromEntries(entries); -} - -function saveLocalReadAt(readAtByTask: AnyRecord): AnyRecord { - const retained = trimLocalReadAt(readAtByTask); - if (typeof window === "undefined") return retained; - try { - window.localStorage.setItem(codexReadAtStorageKey, JSON.stringify(retained)); - } catch { - // Best-effort fallback only; backend readAt remains authoritative when deployed. - } - return retained; -} - -function applyLocalReadState(task: any, readAtByTask: AnyRecord): any { - const taskId = String(task?.id || ""); - const localReadAt = String(readAtByTask?.[taskId] || ""); - if (!taskIsTerminal(task) || localReadAt.length === 0) return task; - return { ...task, readAt: task?.readAt || localReadAt, terminalUnread: false }; -} - function countNumber(value: any): number { const number = Number(value || 0); return Number.isFinite(number) ? number : 0; @@ -1035,18 +1153,21 @@ function ProgressivePromptBlock({ task, loading, onLoadPromptPart, testId = "cod } function ProgressiveExecutionSummary({ task, attempt, attemptIndex, loading, onLoadSteps, onLoadStep, testId = "codex-execution-summary" }: AnyRecord) { - const execution = attemptExecutionSummary(task, attempt); - const steps = taskTraceSteps(task, attemptIndex); + const steps = coalesceFileChangeTraceSteps(taskTraceSteps(task, attemptIndex)); + const execution = executionSummaryWithDisplayedSteps(attemptExecutionSummary(task, attempt), steps); const stepDetails = taskTraceStepDetails(task); const stepsLoaded = taskTraceStepsLoaded(task, attemptIndex); const toolCount = Number(execution.toolCallCount || 0); const editedFiles = Array.isArray(execution.editedFiles) ? execution.editedFiles : []; const commands = Array.isArray(execution.commands) ? execution.commands : []; - const labelSuffix = attemptIndex ? ` #${attemptIndex}` : ""; + const synthetic = isSyntheticAttemptSegment(attempt, attemptIndex); + const labelSuffix = synthetic ? ` · ${String(attempt?.label || "recovered thread execution")}` : attemptIndex ? ` #${attemptIndex}` : ""; + const updatedAt = attemptExecutionUpdatedAt(task, attempt, attemptIndex, execution); + const recentUpdateLabel = `最近更新: ${fmtRelativeAge(updatedAt)}`; return h("details", { className: "codex-progressive-card codex-execution-summary", "data-testid": testId, - "data-attempt-index": attemptIndex ? String(attemptIndex) : undefined, + "data-attempt-index": attemptDataIndex(attemptIndex), onToggle: (event: any) => { if (event.currentTarget?.open && !stepsLoaded) onLoadSteps?.(attemptIndex); }, @@ -1055,7 +1176,8 @@ function ProgressiveExecutionSummary({ task, attempt, attemptIndex, loading, onL h("div", { className: "codex-progressive-card-head" }, h("span", { className: "codex-output-channel" }, "Summary"), h("strong", null, `执行过程摘要${labelSuffix}`), - h("code", null, `${fmtDuration(execution.durationMs ?? execution.totalElapsedMs)} / ${toolCount} tools`), + h("code", { title: updatedAt ? `最近更新: ${fmtDate(updatedAt)}` : recentUpdateLabel }, + `${fmtDuration(execution.durationMs ?? execution.totalElapsedMs)} / ${toolCount} tools / ${recentUpdateLabel}`), ), h("div", { className: "codex-execution-digest" }, h("span", null, `read ${Number(execution.readCount || 0)}`), @@ -1122,7 +1244,7 @@ function ProgressiveFinalResponse({ task, attempt, attemptIndex, testId = "codex const text = attemptFinalResponseText(task, attempt); const chars = Number(attempt?.finalResponseChars || text.length); const labelSuffix = attemptIndex ? ` #${attemptIndex}` : ""; - return h("section", { className: "codex-progressive-card codex-final-response", "data-testid": testId, "data-attempt-index": attemptIndex ? String(attemptIndex) : undefined }, + return h("section", { className: "codex-progressive-card codex-final-response", "data-testid": testId, "data-attempt-index": attemptDataIndex(attemptIndex) }, h("div", { className: "codex-progressive-card-head" }, h("span", { className: "codex-output-channel" }, "Final"), h("strong", null, `最终 response${labelSuffix}`), @@ -1135,7 +1257,7 @@ function ProgressiveFinalResponse({ task, attempt, attemptIndex, testId = "codex function ProgressiveJudge({ task, attempt, attemptIndex, testId = "codex-progressive-judge" }: AnyRecord) { const judge = attemptJudge(task, attempt); const labelSuffix = attemptIndex ? ` #${attemptIndex}` : ""; - return h("section", { className: "codex-progressive-card codex-progressive-judge", "data-testid": testId, "data-attempt-index": attemptIndex ? String(attemptIndex) : undefined }, + return h("section", { className: "codex-progressive-card codex-progressive-judge", "data-testid": testId, "data-attempt-index": attemptDataIndex(attemptIndex) }, h("div", { className: "codex-progressive-card-head" }, h("span", { className: "codex-output-channel" }, "Judge"), h("strong", null, `完成判定${labelSuffix}`), @@ -1165,7 +1287,7 @@ function ProgressiveJudgeFeedbackPrompt({ task, attempt, attemptIndex, loading, return h("details", { className: "codex-progressive-card codex-judge-feedback-prompt", "data-testid": testId, - "data-attempt-index": attemptIndex ? String(attemptIndex) : undefined, + "data-attempt-index": attemptDataIndex(attemptIndex), onToggle: (event: any) => { if (event.currentTarget?.open && !detailText) onLoadPromptPart?.("feedback", attemptIndex); }, @@ -1184,11 +1306,13 @@ function ProgressiveJudgeFeedbackPrompt({ task, attempt, attemptIndex, loading, } function ProgressiveAttemptCycle({ task, attempt, position, loading, onLoadPromptPart, onLoadSteps, onLoadStep }: AnyRecord) { - const attemptIndex = Number(attempt?.index || position + 1); + const attemptIndex = attemptSegmentIndex(attempt, position); const first = position === 0; + const synthetic = isSyntheticAttemptSegment(attempt, attemptIndex); + const title = synthetic ? String(attempt?.label || "Recovered thread execution") : `Attempt ${attemptIndex}`; return h("section", { className: "codex-attempt-cycle", "data-testid": `codex-attempt-cycle-${attemptIndex}` }, h("div", { className: "codex-attempt-cycle-head" }, - h("span", { className: "codex-output-channel" }, `Attempt ${attemptIndex}`), + h("span", { className: "codex-output-channel" }, title), h("strong", null, String(attempt?.mode || (attemptIndex <= 1 ? "initial" : "retry"))), attempt?.terminalStatus ? h(StatusBadge, { status: attempt.terminalStatus }, attempt.terminalStatus) : null, h("code", null, `${fmtDate(attempt?.startedAt)} -> ${fmtDate(attempt?.finishedAt)}`), @@ -1202,19 +1326,19 @@ function ProgressiveAttemptCycle({ task, attempt, position, loading, onLoadPromp onLoadStep, testId: first ? "codex-execution-summary" : `codex-execution-summary-attempt-${attemptIndex}`, }), - h(ProgressiveFinalResponse, { + synthetic ? null : h(ProgressiveFinalResponse, { task, attempt, attemptIndex, testId: first ? "codex-final-response" : `codex-final-response-attempt-${attemptIndex}`, }), - h(ProgressiveJudge, { + synthetic ? null : h(ProgressiveJudge, { task, attempt, attemptIndex, testId: first ? "codex-progressive-judge" : `codex-progressive-judge-attempt-${attemptIndex}`, }), - h(ProgressiveJudgeFeedbackPrompt, { + synthetic ? null : h(ProgressiveJudgeFeedbackPrompt, { task, attempt, attemptIndex, @@ -1242,63 +1366,6 @@ function ProgressiveTrace({ task, loading, onLoadPromptPart, onLoadSteps, onLoad } -function PromptDetail({ task, loading, onLoadPromptPart }: AnyRecord) { - if (!task) return h(EmptyState, { title: "未选择任务", text: "选择队列或历史 session 后,这里显示完整 prompt、模型和工作目录。" }); - const promptSummary = taskPromptSummary(task); - const promptDetails = taskPromptDetails(task); - const visiblePrompt = taskBasePromptText(task).trimEnd(); - const promptText = String(promptDetails.full?.text || ""); - const hasReference = taskHasReferencePrompt(task); - const visibleLines = Number(promptSummary.basePromptLines || promptLineCount(visiblePrompt)); - const totalLines = Number(promptSummary.promptLines || promptLineCount(promptText)); - const referenceLines = Number(promptSummary.referencePromptLines || 0); - const fullChars = Number(promptSummary.promptChars || task?.promptChars || promptText.length); - return h("div", { className: "codex-prompt-detail", "data-testid": "codex-task-prompt-detail" }, - h("div", { className: "codex-prompt-meta" }, - h(StatusBadge, { status: task?.status }, task?.status || "unknown"), - h("span", null, `model=${task?.model || "--"}`), - h("span", null, `cwd=${task?.cwd || "--"}`), - h("span", null, `created=${fmtDate(task?.createdAt)}`), - h("span", null, hasReference - ? `task ${visibleLines} lines / total ${Number.isFinite(totalLines) && totalLines > 0 ? totalLines : "--"} lines` - : `${visibleLines} lines / ${visiblePrompt.length} chars`), - ), - h("div", { className: "codex-lazy-detail-callout", "data-testid": "codex-task-summary-callout" }, - h("div", null, - h("strong", null, "渐进式 Trace"), - h("span", null, "首屏使用后端 Summary;展开 prompt / 步骤时只按需拉取对应片段,不一次性拉取完整 transcript。"), - ), - ), - hasReference ? h("details", { - className: "codex-reference-injection codex-final-prompt-injection", - "data-testid": "codex-final-prompt-full", - onToggle: (event: any) => { - if (event.currentTarget?.open && !promptText) onLoadPromptPart?.("full"); - }, - }, - h("summary", null, - h("span", null, "最终传入 Codex 的真实完整 prompt"), - h("code", null, promptText ? `${totalLines || promptLineCount(promptText)} lines / ${promptText.length} chars` : `${Number.isFinite(fullChars) && fullChars > 0 ? fullChars : "--"} chars`), - ), - h("pre", { className: "codex-prompt-full codex-prompt-final-full", "data-testid": "codex-task-final-prompt-full" }, promptText || (loading ? "正在按需拉取完整 prompt..." : "展开后将只请求完整 prompt。")), - ) : null, - hasReference ? h("details", { - className: "codex-reference-injection", - "data-testid": "codex-reference-injection", - onToggle: (event: any) => { - if (event.currentTarget?.open && !promptDetails.reference?.text) onLoadPromptPart?.("reference"); - }, - }, - h("summary", null, - h("span", null, "引用注入已折叠"), - h("code", null, promptDetails.reference?.text ? `${promptLineCount(String(promptDetails.reference.text || ""))} lines / ${String(promptDetails.reference.text || "").length} chars` : `${referenceLines || "--"} lines`), - ), - h("pre", { className: "codex-prompt-full codex-prompt-reference-full", "data-testid": "codex-task-reference-full" }, String(promptDetails.reference?.text || "") || (loading ? "正在按需拉取引用注入..." : "展开后将只请求引用注入片段。")), - ) : null, - h("pre", { className: "codex-prompt-full", "data-testid": "codex-task-prompt-full" }, visiblePrompt || "空 prompt"), - ); -} - function RawTranscript({ task }: AnyRecord) { const output = taskOutput(task); if (!task || output.length === 0) return h(EmptyState, { title: "暂无原始消息", text: "原始 Codex app-server 消息会保留在任务 JSON 中。" }); @@ -1395,7 +1462,6 @@ export function CodexQueuePage({ microservices, onRaw, apiBaseUrl = "/api", init const [copiedTaskId, setCopiedTaskId] = useState(""); const [markingReadTaskId, setMarkingReadTaskId] = useState(""); const [markingAllRead, setMarkingAllRead] = useState(false); - const [localReadAt, setLocalReadAt] = useState(loadLocalReadAt); const [loadStats, setLoadStats] = useState(initialTasksData ? { phase: "complete", taskId: initialSelectedId, @@ -1410,7 +1476,7 @@ export function CodexQueuePage({ microservices, onRaw, apiBaseUrl = "/api", init const [refreshedAt, setRefreshedAt] = useState(initialTasksData ? new Date() : null); const [loadingMoreTasks, setLoadingMoreTasks] = useState(false); - const tasks = taskRows(tasksData).map((task: any) => applyLocalReadState(task, localReadAt)); + const tasks = taskRows(tasksData); const unreadTerminalTasks = tasks.filter(taskIsUnreadTerminal); const queuedTasks = tasks.filter((task: any) => !taskIsTerminal(task)); const historyTasks = tasks.filter((task: any) => taskIsTerminal(task) && !taskIsUnreadTerminal(task)); @@ -1429,7 +1495,7 @@ export function CodexQueuePage({ microservices, onRaw, apiBaseUrl = "/api", init const globalCounts = queueCounts(queue); const overallQueuedCount = queueWaitingCount(globalCounts); const overallRunningCount = Math.max(queueRunningCount(globalCounts), globalActiveIds.length); - const overallUnreadTerminalCount = countNumber(queue?.unreadTerminal ?? unreadTerminalTasks.length); + const overallUnreadTerminalCount = countNumber((isAllQueues(selectedQueueId) ? queue?.unreadTerminal : viewQueueRow?.unreadTerminal) ?? unreadTerminalTasks.length); const selectedQueueName = isAllQueues(selectedQueueId) ? "All queues" : selectedQueueId; const runtime = service ? microserviceRuntime(service) : {}; const repository = service ? microserviceRepository(service) : {}; @@ -1478,16 +1544,6 @@ export function CodexQueuePage({ microservices, onRaw, apiBaseUrl = "/api", init } } - function rememberLocalRead(taskIds: string[], readAt: string): void { - const ids = taskIds.map((id) => String(id || "")).filter(Boolean); - if (ids.length === 0) return; - setLocalReadAt((previous: AnyRecord) => { - const next = { ...(previous || {}) }; - for (const id of ids) next[id] = readAt; - return saveLocalReadAt(next); - }); - } - useEffect(() => { setBatchConfirmed(false); }, [prompt, repeatCount, referenceTaskId]); @@ -1867,6 +1923,11 @@ export function CodexQueuePage({ microservices, onRaw, apiBaseUrl = "/api", init } setRefreshedAt(new Date()); if (trackLoad) trackedLoadInFlightRef.current = false; + // Overview is intentionally small and may only contain the latest attempt. + // Load the canonical Trace Summary as a follow-up so retry/judge feedback + // cards are shown for historical multi-attempt sessions too. + void ensureTraceSummary(nextId, false, trackLoad ? startedAt : undefined, trackLoad ? queueMs : undefined) + .catch((err) => setError(errorText(err, "加载 Codex Trace Summary 失败"))); return; } if (trackLoad) { @@ -1993,18 +2054,11 @@ export function CodexQueuePage({ microservices, onRaw, apiBaseUrl = "/api", init if (!service || !taskId) return; setMarkingReadTaskId(taskId); await guarded(async () => { - let result: any = null; - let localOnly = false; - try { - result = await markTaskReadRequest(apiBaseUrl, taskId); - } catch { - localOnly = true; - } + const result = await markTaskReadRequest(apiBaseUrl, taskId); const task = result?.task || { id: taskId, readAt: new Date().toISOString(), terminalUnread: false }; const readAt = String(task?.readAt || new Date().toISOString()); - rememberLocalRead([taskId], readAt); patchLoadedReadState([taskId], readAt, result?.queue || null, task); - setNotice(localOnly ? `已在本浏览器将任务 ${taskId} 标为已读;后端升级后会同步持久化` : `已将任务 ${taskId} 标为已读`); + setNotice(`已将任务 ${taskId} 标为已读`); }, "标记 Codex task 已读失败"); setMarkingReadTaskId((value: string) => value === taskId ? "" : value); } @@ -2013,27 +2067,19 @@ export function CodexQueuePage({ microservices, onRaw, apiBaseUrl = "/api", init if (!service || markingAllRead) return; setMarkingAllRead(true); await guarded(async () => { - let result: any = null; - let localOnly = false; - try { - result = await markAllTerminalReadRequest(apiBaseUrl); - } catch { - localOnly = true; - } + const result = await markAllTerminalReadRequest(apiBaseUrl); const readAt = String(result?.readAt || new Date().toISOString()); const loadedUnreadIds = taskRows(tasksDataRef.current) - .map((task: any) => applyLocalReadState(task, localReadAt)) .filter(taskIsUnreadTerminal) .map((task: any) => String(task?.id || "")) .filter(Boolean); const cachedUnreadIds = Array.from(sessionCacheRef.current.entries()) - .filter(([, value]) => taskIsUnreadTerminal(applyLocalReadState(value?.task, localReadAt))) + .filter(([, value]) => taskIsUnreadTerminal(value?.task)) .map(([id]) => id); const readIds = Array.from(new Set([...loadedUnreadIds, ...cachedUnreadIds])); - rememberLocalRead(readIds, readAt); patchLoadedReadState(readIds, readAt, result?.queue || null); - const markedCount = localOnly ? readIds.length : Number(result?.count || readIds.length); - setNotice(localOnly ? `已在本浏览器将 ${markedCount} 个已结束未读任务标为已读;后端升级后会同步持久化` : `已将 ${markedCount} 个已结束未读任务标为已读`); + const markedCount = Number(result?.count || readIds.length); + setNotice(`已将 ${markedCount} 个已结束未读任务标为已读`); }, "全部标为已读失败"); setMarkingAllRead(false); } @@ -2446,9 +2492,6 @@ export function CodexQueuePage({ microservices, onRaw, apiBaseUrl = "/api", init ), h("div", { className: "codex-main-stage" }, h("div", { className: "codex-detail-grid" }, - h(Panel, { title: "Prompt 全量", eyebrow: selectedTask ? String(selectedTask.id) : "selected task", className: "codex-prompt-panel" }, - h(PromptDetail, { task: selectedTask, loading: selectedDetailLoading, onLoadPromptPart: ensurePromptPart }), - ), h(Panel, { title: "运行控制", eyebrow: selectedCanSteer ? "Active turn steer" : "Steer when running" }, h("div", { className: "codex-run-control-stack" }, h(TaskQueueMoveControl, { task: selectedTask, queueRows, busy, onMove: moveSelectedTaskQueue }), diff --git a/src/components/frontend/src/findjob.tsx b/src/components/frontend/src/findjob.tsx index 13559f0e..32ece78e 100644 --- a/src/components/frontend/src/findjob.tsx +++ b/src/components/frontend/src/findjob.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { fmtClock, fmtDate } from "./time"; import { errorMessage, requestJson } from "./unidesk-error"; import { UniDeskErrorBanner } from "./unidesk-error-banner"; @@ -8,16 +9,6 @@ const h = React.createElement; const { useEffect } = React; const useState: any = React.useState; -function fmtDate(value: any): string { - if (!value) return "--"; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return "--"; - return date.toLocaleString("zh-CN", { hour12: false }); -} - -function fmtClock(value: Date): string { - return value.toLocaleTimeString("zh-CN", { hour12: false }); -} function StatusBadge({ status, children }: AnyRecord) { const normalized = String(status || "unknown").toLowerCase(); diff --git a/src/components/frontend/src/met-nonlinear.tsx b/src/components/frontend/src/met-nonlinear.tsx index 2871648f..43d2389c 100644 --- a/src/components/frontend/src/met-nonlinear.tsx +++ b/src/components/frontend/src/met-nonlinear.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { fmtClock, fmtDate } from "./time"; import { errorMessage, requestJson } from "./unidesk-error"; import { UniDeskErrorBanner } from "./unidesk-error-banner"; @@ -8,16 +9,6 @@ const h = React.createElement; const { useEffect } = React; const useState: any = React.useState; -function fmtDate(value: any): string { - if (!value) return "--"; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return "--"; - return date.toLocaleString("zh-CN", { hour12: false }); -} - -function fmtClock(value: Date): string { - return value.toLocaleTimeString("zh-CN", { hour12: false }); -} function fmtPercent(value: any): string { const number = Number(value); diff --git a/src/components/frontend/src/pipeline.tsx b/src/components/frontend/src/pipeline.tsx index da08f16f..6b74886b 100644 --- a/src/components/frontend/src/pipeline.tsx +++ b/src/components/frontend/src/pipeline.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { fmtClock, fmtDate } from "./time"; import { Background, BaseEdge, Controls, Handle, MarkerType, Position, ReactFlow, type Edge, type Node } from "@xyflow/react"; import { TraceView, opencodeTracePort } from "./trace"; import { errorMessage, requestJson as requestUniDeskJson } from "./unidesk-error"; @@ -192,16 +193,6 @@ function PipelineCurveEdge({ id, sourceX, sourceY, targetX, targetY, targetPosit const pipelineEdgeTypes: any = { pipelineCurve: PipelineCurveEdge }; const pipelineNodeTypes: any = { pipelineNode: PipelineFlowNode }; -function fmtDate(value: any): string { - if (!value) return "--"; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return "--"; - return date.toLocaleString("zh-CN", { hour12: false }); -} - -function fmtClock(value: Date): string { - return value.toLocaleTimeString("zh-CN", { hour12: false }); -} function fmtClockValue(value: any): string { if (!value) return "--"; diff --git a/src/components/frontend/src/project-manager.tsx b/src/components/frontend/src/project-manager.tsx index fda54773..55448822 100644 --- a/src/components/frontend/src/project-manager.tsx +++ b/src/components/frontend/src/project-manager.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { beijingDateStamp, fmtClock, fmtDate } from "./time"; import { errorMessage, requestBlob, requestJson } from "./unidesk-error"; import { UniDeskErrorBanner } from "./unidesk-error-banner"; @@ -19,16 +20,6 @@ const EMPTY_FORM = { notes: "", }; -function fmtDate(value: any): string { - if (!value) return "--"; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return "--"; - return date.toLocaleString("zh-CN", { hour12: false }); -} - -function fmtClock(value: Date): string { - return value.toLocaleTimeString("zh-CN", { hour12: false }); -} function StatusBadge({ status, children }: AnyRecord) { const normalized = String(status || "unknown").toLowerCase(); @@ -230,7 +221,7 @@ export function ProjectManagerPage({ microservices, onRaw, apiBaseUrl = "/api" } const href = URL.createObjectURL(blob); const anchor = document.createElement("a"); anchor.href = href; - anchor.download = `project-manager-${new Date().toISOString().slice(0, 10)}.xlsx`; + anchor.download = `project-manager-${beijingDateStamp()}.xlsx`; document.body.appendChild(anchor); anchor.click(); anchor.remove(); diff --git a/src/components/frontend/src/time.ts b/src/components/frontend/src/time.ts new file mode 100644 index 00000000..61284beb --- /dev/null +++ b/src/components/frontend/src/time.ts @@ -0,0 +1,77 @@ +export const BEIJING_TIME_ZONE = "Asia/Shanghai"; +export const BEIJING_TIME_LABEL = "北京时间"; + +const BEIJING_UTC_OFFSET_HOURS = 8; +const DATE_TIME_OPTIONS: Intl.DateTimeFormatOptions = { + timeZone: BEIJING_TIME_ZONE, + hour12: false, +}; +const CLOCK_OPTIONS: Intl.DateTimeFormatOptions = { + timeZone: BEIJING_TIME_ZONE, + hour12: false, +}; +const INPUT_PARTS_FORMATTER = new Intl.DateTimeFormat("en-CA", { + timeZone: BEIJING_TIME_ZONE, + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + hourCycle: "h23", +}); + +function coerceDate(value: any): Date | null { + if (value === null || value === undefined || value === "") return null; + const date = value instanceof Date ? value : new Date(value); + return Number.isNaN(date.getTime()) ? null : date; +} + +function beijingInputParts(value: any): Record | null { + const date = coerceDate(value); + if (!date) return null; + return INPUT_PARTS_FORMATTER.formatToParts(date).reduce((parts: Record, part) => { + if (part.type !== "literal") parts[part.type] = part.value; + return parts; + }, {}); +} + +export function fmtDate(value: any): string { + const date = coerceDate(value); + return date ? date.toLocaleString("zh-CN", DATE_TIME_OPTIONS) : "--"; +} + +export function fmtClock(value: any): string { + const date = coerceDate(value); + return date ? date.toLocaleTimeString("zh-CN", CLOCK_OPTIONS) : "--"; +} + +export function fmtDateTimeLocalInput(value: any): string { + const parts = beijingInputParts(value); + if (!parts) return ""; + const hour = parts.hour === "24" ? "00" : parts.hour; + return `${parts.year}-${parts.month}-${parts.day}T${hour}:${parts.minute}`; +} + +export function beijingDateStamp(value: any = new Date()): string { + const parts = beijingInputParts(value); + if (!parts) return ""; + return `${parts.year}-${parts.month}-${parts.day}`; +} + +export function localDateTimeInputToBeijingIso(value: string): string | null { + if (!value) return null; + const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(value); + if (!match) return null; + const [, year, month, day, hour, minute, second = "00"] = match; + const utcMs = Date.UTC( + Number(year), + Number(month) - 1, + Number(day), + Number(hour) - BEIJING_UTC_OFFSET_HOURS, + Number(minute), + Number(second), + ); + const date = new Date(utcMs); + const normalized = fmtDateTimeLocalInput(date); + return Number.isNaN(date.getTime()) || normalized !== `${year}-${month}-${day}T${hour}:${minute}` ? null : date.toISOString(); +} diff --git a/src/components/frontend/src/todo-note.tsx b/src/components/frontend/src/todo-note.tsx index a09b1069..56ab7d19 100644 --- a/src/components/frontend/src/todo-note.tsx +++ b/src/components/frontend/src/todo-note.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { fmtClock, fmtDate, fmtDateTimeLocalInput, localDateTimeInputToBeijingIso } from "./time"; import { errorMessage, requestJson } from "./unidesk-error"; import { UniDeskErrorBanner } from "./unidesk-error-banner"; @@ -9,17 +10,6 @@ const h = React.createElement; const { useEffect } = React; const useState: any = React.useState; -function fmtDate(value: any): string { - if (!value) return "--"; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return "--"; - return date.toLocaleString("zh-CN", { hour12: false }); -} - -function fmtClock(value: Date): string { - return value.toLocaleTimeString("zh-CN", { hour12: false }); -} - function StatusBadge({ status, children }: AnyRecord) { const normalized = String(status || "unknown").toLowerCase(); return h("span", { className: `status-badge ${normalized}` }, children || status || "unknown"); @@ -102,20 +92,6 @@ function todoVisible(todo: any, filter: string): boolean { return selfVisible || children.some((child: any) => todoVisible(child, filter)); } -function todoReminderLocal(value: any): string { - if (!value) return ""; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return ""; - const local = new Date(date.getTime() - date.getTimezoneOffset() * 60_000); - return local.toISOString().slice(0, 16); -} - -function localReminderIso(value: string): string | null { - if (!value) return null; - const date = new Date(value); - return Number.isNaN(date.getTime()) ? null : date.toISOString(); -} - function todoRegistryRows(registry: any): any[] { return Array.isArray(registry?.instances) ? registry.instances : []; } @@ -430,7 +406,7 @@ function TodoRow(props: AnyRecord): ReactNode { todo.reminderAt ? h("span", { className: "todo-reminder" }, `提醒 ${fmtDate(todo.reminderAt)}`) : h("span", null, "无提醒"), ), ), - h("input", { className: "todo-reminder-input", type: "datetime-local", value: todoReminderLocal(todo.reminderAt), onChange: (event: any) => applyTodoAction({ type: "setTodoReminder", todoId: todo.id, reminderAt: localReminderIso(event.target.value) }) }), + h("input", { className: "todo-reminder-input", type: "datetime-local", value: fmtDateTimeLocalInput(todo.reminderAt), onChange: (event: any) => applyTodoAction({ type: "setTodoReminder", todoId: todo.id, reminderAt: localDateTimeInputToBeijingIso(event.target.value) }) }), h("div", { className: "todo-row-actions" }, h("button", { type: "button", className: "ghost-btn", onClick: () => beginEdit(todo) }, "编辑"), h("button", { type: "button", className: "ghost-btn", onClick: () => addChild(todo.id) }, "子项"), diff --git a/src/components/frontend/src/trace.tsx b/src/components/frontend/src/trace.tsx index f3abc83f..4de1f5a5 100644 --- a/src/components/frontend/src/trace.tsx +++ b/src/components/frontend/src/trace.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { fmtDate } from "./time"; type AnyRecord = Record; @@ -73,13 +74,6 @@ export function traceFromPort(port: TracePort, input: Input): Trac return normalizeTraceItems(port.toTrace(input)); } -function fmtDate(value: any): string { - if (!value) return "--"; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return "--"; - return date.toLocaleString("zh-CN", { hour12: false }); -} - function fmtDuration(ms: any): string { const value = Number(ms); if (!Number.isFinite(value) || value < 0) return "--"; diff --git a/src/components/frontend/src/unidesk-error.ts b/src/components/frontend/src/unidesk-error.ts index f4d2f46f..f41f6871 100644 --- a/src/components/frontend/src/unidesk-error.ts +++ b/src/components/frontend/src/unidesk-error.ts @@ -1,3 +1,5 @@ +import { BEIJING_TIME_LABEL, fmtDate } from "./time"; + type AnyRecord = Record; export type UniDeskFailureField = string | false; @@ -231,7 +233,7 @@ function fmtDateTime(value: string | undefined): string { if (!value) return ""; const date = new Date(value); if (Number.isNaN(date.getTime())) return value; - return `${date.toLocaleString("zh-CN", { hour12: false })} / ${date.toISOString()}`; + return `${fmtDate(date)} ${BEIJING_TIME_LABEL}`; } export function describeUniDeskError(error: unknown, fallback = "操作失败"): UniDeskErrorView { diff --git a/src/components/microservices/codex-queue/src/index.ts b/src/components/microservices/codex-queue/src/index.ts index 84b7e935..f1c08c69 100644 --- a/src/components/microservices/codex-queue/src/index.ts +++ b/src/components/microservices/codex-queue/src/index.ts @@ -1,5 +1,5 @@ import { spawn, spawnSync, type ChildProcessWithoutNullStreams } from "node:child_process"; -import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync, type Dirent } from "node:fs"; +import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, type Dirent } from "node:fs"; import { dirname, resolve } from "node:path"; import * as readline from "node:readline"; import postgres from "postgres"; @@ -15,7 +15,7 @@ type TranscriptKind = "ran" | "explored" | "edited" | "plan" | "message" | "syst interface RuntimeConfig { host: string; port: number; - statePath: string; + dataDir: string; outputArchiveDir: string; logFile: string; defaultWorkdir: string; @@ -34,7 +34,7 @@ interface RuntimeConfig { judgeTimeoutMs: number; judgeRepairAttempts: number; turnNoActivityTimeoutMs: number; - databaseUrl: string | null; + databaseUrl: string; databaseFlushIntervalMs: number; notifyClaudeQqEnabled: boolean; notifyClaudeQqBaseUrl: string; @@ -44,6 +44,8 @@ interface RuntimeConfig { notifyClaudeQqMaxResponseChars: number; notifyClaudeQqTimeoutMs: number; notifyClaudeQqSendAttempts: number; + notifyClaudeQqRetryIntervalMs: number; + notifyClaudeQqMaxOutboxItems: number; maxInMemoryOutputRecords: number; maxInMemoryEventRecords: number; } @@ -202,6 +204,7 @@ interface PromptHistoryItem { interface QueueTask { id: string; queueId: string; + queueEnteredAt: string; prompt: string; basePrompt: string; referenceTaskIds: string[]; @@ -241,6 +244,40 @@ interface PersistedState { tasks: QueueTask[]; } +interface ClaudeQqNotificationItem { + id: string; + kind: string; + dedupKey: string; + target: string; + message: string; + createdAt: string; + updatedAt: string; + attempts: number; + nextAttemptAt: string; + lastError: string | null; + sentAt: string | null; +} + +interface ClaudeQqNotificationOutboxState { + version: 1; + updatedAt: string; + items: ClaudeQqNotificationItem[]; +} + +interface ClaudeQqNotificationRow { + id: string; + kind: string; + dedup_key: string; + target: string; + message: string; + created_at: Date | string; + updated_at: Date | string; + attempts: number; + next_attempt_at: Date | string; + last_error: string | null; + sent_at: Date | string | null; +} + interface QueueRecord { id: string; createdAt: string; @@ -286,6 +323,7 @@ interface JudgeProbeCase { prompt: string; finalResponse: string; expected: JudgeDecision; + expectedContinuePromptIncludes?: string[]; terminalStatus: TerminalStatus; cancelRequested?: boolean; transportClosedBeforeTerminal?: boolean; @@ -310,7 +348,7 @@ const recentLogs: JsonValue[] = []; const serviceStartedAt = new Date().toISOString(); const defaultQueueId = "default"; const judgeFailRetryLimit = 3; -const fallbackJudgeRetryLimit = 1; +const fallbackJudgeRetryLimit = 3; const maxTaskAttempts = 99; const referenceInjectionMaxRounds: number | null = null; const retryBackoffBaseMs = 1000; @@ -318,7 +356,7 @@ const retryBackoffMaxMs = 10 * 60 * 1000; const queueIdPattern = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/u; const config = readConfig(); const logger = createLogger("codex-queue", config.logFile); -const state = readState(config.statePath); +const state = emptyState(); let processing = false; const processingQueues = new Set(); const activeRuns = new Map(); @@ -332,20 +370,24 @@ const codexSessionPathCache = new Map(); const codexSessionFileChangeCache = new Map }>(); const codexSessionCommandOutputCache = new Map }>(); const outputArchiveSeededTasks = new Set(); -const sql: SqlClient | null = config.databaseUrl === null ? null : postgres(config.databaseUrl, { +const sql: SqlClient = postgres(config.databaseUrl, { max: 4, idle_timeout: 20, connect_timeout: 10, }); +let claudeQqNotificationOutbox = emptyClaudeQqNotificationOutbox(); let databaseReady = false; let databaseLastError: string | null = null; let databaseFlushTimer: ReturnType | null = null; let databaseFlushInFlight = false; const dirtyDatabaseTaskIds = new Set(); +const dirtyDatabaseQueueIds = new Set(); const sentTaskNotificationKeys = new Set(); const inFlightTaskNotificationKeys = new Set(); let idleNotificationSent = true; let idleNotificationInFlight = false; +let claudeQqNotificationDrainTimer: ReturnType | null = null; +let claudeQqNotificationDrainInFlight = false; function envString(name: string, fallback: string): string { const value = process.env[name]; @@ -357,6 +399,12 @@ function envNullableString(name: string): string | null { return value === undefined || value.length === 0 ? null : value; } +function envRequiredString(name: string): string { + const value = process.env[name]; + if (value === undefined || value.trim().length === 0) throw new Error(`${name} is required`); + return value; +} + function envNumber(name: string, fallback: number): number { const raw = process.env[name]; if (raw === undefined || raw.length === 0) return fallback; @@ -413,13 +461,13 @@ function approvalValue(raw: string): RuntimeConfig["approvalPolicy"] { function readConfig(): RuntimeConfig { const defaultModel = envString("CODEX_QUEUE_DEFAULT_MODEL", "gpt-5.5"); - const statePath = envString("CODEX_QUEUE_STATE_PATH", "/var/lib/unidesk/codex-queue/state.json"); + const dataDir = envString("CODEX_QUEUE_DATA_DIR", "/var/lib/unidesk/codex-queue"); const notifyTargetTypeRaw = envString("CODEX_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE", "private").toLowerCase(); return { host: envString("HOST", "0.0.0.0"), port: envNumber("PORT", 4222), - statePath, - outputArchiveDir: envString("CODEX_QUEUE_OUTPUT_ARCHIVE_DIR", resolve(dirname(statePath), "output-archive")), + dataDir, + outputArchiveDir: envString("CODEX_QUEUE_OUTPUT_ARCHIVE_DIR", resolve(dataDir, "output-archive")), logFile: envString("LOG_FILE", "/var/log/unidesk/codex-queue.jsonl"), defaultWorkdir: envString("CODEX_QUEUE_WORKDIR", "/root/unidesk"), codexHome: envString("CODEX_QUEUE_CODEX_HOME", "/var/lib/unidesk/codex-queue/codex-home"), @@ -437,7 +485,7 @@ function readConfig(): RuntimeConfig { judgeTimeoutMs: envNumber("MINIMAX_JUDGE_TIMEOUT_MS", 60_000), judgeRepairAttempts: Math.max(0, Math.min(5, envNumber("MINIMAX_JUDGE_REPAIR_ATTEMPTS", 2))), turnNoActivityTimeoutMs: Math.max(60_000, Math.min(30 * 60_000, envNumber("CODEX_TURN_NO_ACTIVITY_TIMEOUT_MS", 6 * 60_000))), - databaseUrl: envNullableString("DATABASE_URL"), + databaseUrl: envRequiredString("DATABASE_URL"), databaseFlushIntervalMs: Math.max(100, Math.min(10_000, envNumber("CODEX_QUEUE_DATABASE_FLUSH_INTERVAL_MS", 1000))), notifyClaudeQqEnabled: envBool("CODEX_QUEUE_NOTIFY_CLAUDEQQ_ENABLED", false), notifyClaudeQqBaseUrl: envString("CODEX_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL", "http://backend-core:8080/api/microservices/claudeqq/proxy").replace(/\/+$/u, ""), @@ -447,6 +495,8 @@ function readConfig(): RuntimeConfig { notifyClaudeQqMaxResponseChars: Math.max(500, Math.min(50_000, envNumber("CODEX_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS", 12_000))), notifyClaudeQqTimeoutMs: Math.max(1000, Math.min(60_000, envNumber("CODEX_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS", 15_000))), notifyClaudeQqSendAttempts: Math.max(1, Math.min(10, envNumber("CODEX_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS", 3))), + notifyClaudeQqRetryIntervalMs: Math.max(5_000, Math.min(10 * 60_000, envNumber("CODEX_QUEUE_NOTIFY_CLAUDEQQ_RETRY_INTERVAL_MS", 60_000))), + notifyClaudeQqMaxOutboxItems: Math.max(100, Math.min(10_000, envNumber("CODEX_QUEUE_NOTIFY_CLAUDEQQ_MAX_OUTBOX_ITEMS", 2000))), maxInMemoryOutputRecords: envNonNegativeNumber("CODEX_QUEUE_IN_MEMORY_OUTPUT_RECORDS", 600), maxInMemoryEventRecords: envNonNegativeNumber("CODEX_QUEUE_IN_MEMORY_EVENT_RECORDS", 400), }; @@ -502,13 +552,105 @@ function emptyState(): PersistedState { return { version: 1, updatedAt: at, nextSeq: 1, queues: [{ id: defaultQueueId, createdAt: at, updatedAt: at }], tasks: [] }; } -function normalizeQueueRecord(value: unknown): QueueRecord | null { - if (typeof value !== "object" || value === null || Array.isArray(value)) return null; - const record = value as Partial; - const id = safeQueueId(record.id); - const createdAt = typeof record.createdAt === "string" && record.createdAt.length > 0 ? record.createdAt : nowIso(); - const updatedAt = typeof record.updatedAt === "string" && record.updatedAt.length > 0 ? record.updatedAt : createdAt; - return { id, createdAt, updatedAt }; +function emptyClaudeQqNotificationOutbox(): ClaudeQqNotificationOutboxState { + return { version: 1, updatedAt: nowIso(), items: [] }; +} + +function notificationItemFromRow(row: ClaudeQqNotificationRow): ClaudeQqNotificationItem { + const createdAt = taskTimestamp(String(row.created_at)) ?? nowIso(); + const updatedAt = taskTimestamp(String(row.updated_at)) ?? createdAt; + return { + id: row.id, + kind: row.kind || "unknown", + dedupKey: row.dedup_key || row.id, + target: row.target || "-", + message: row.message || "", + createdAt, + updatedAt, + attempts: Number.isInteger(row.attempts) && row.attempts >= 0 ? row.attempts : 0, + nextAttemptAt: taskTimestamp(String(row.next_attempt_at)) ?? updatedAt, + lastError: typeof row.last_error === "string" && row.last_error.length > 0 ? row.last_error : null, + sentAt: row.sent_at === null ? null : taskTimestamp(String(row.sent_at)), + }; +} + +async function loadClaudeQqNotificationOutboxFromDatabase(client: SqlExecutor = sql): Promise { + const rows = await client` + SELECT id, kind, dedup_key, target, message, created_at, updated_at, attempts, next_attempt_at, last_error, sent_at + FROM unidesk_codex_queue_notifications + ORDER BY created_at ASC, id ASC + `; + claudeQqNotificationOutbox = { + version: 1, + updatedAt: nowIso(), + items: rows.map(notificationItemFromRow).filter((item) => item.id.length > 0 && item.message.length > 0), + }; + pruneClaudeQqNotificationOutbox(); +} + +async function upsertClaudeQqNotificationToDatabase(client: SqlExecutor, item: ClaudeQqNotificationItem): Promise { + await client` + INSERT INTO unidesk_codex_queue_notifications ( + id, + kind, + dedup_key, + target, + message, + created_at, + updated_at, + attempts, + next_attempt_at, + last_error, + sent_at + ) VALUES ( + ${item.id}, + ${item.kind}, + ${item.dedupKey}, + ${item.target}, + ${item.message}, + ${taskTimestamp(item.createdAt) ?? nowIso()}, + ${taskTimestamp(item.updatedAt) ?? nowIso()}, + ${item.attempts}, + ${taskTimestamp(item.nextAttemptAt) ?? nowIso()}, + ${item.lastError}, + ${taskTimestamp(item.sentAt)} + ) + ON CONFLICT (id) DO UPDATE SET + kind = EXCLUDED.kind, + dedup_key = EXCLUDED.dedup_key, + target = EXCLUDED.target, + message = EXCLUDED.message, + updated_at = EXCLUDED.updated_at, + attempts = EXCLUDED.attempts, + next_attempt_at = EXCLUDED.next_attempt_at, + last_error = EXCLUDED.last_error, + sent_at = EXCLUDED.sent_at + `; +} + +async function persistClaudeQqNotificationItem(item: ClaudeQqNotificationItem): Promise { + if (!databaseReady) throw new Error("PostgreSQL is not ready for ClaudeQQ notification outbox"); + claudeQqNotificationOutbox.updatedAt = nowIso(); + const deletedIds = pruneClaudeQqNotificationOutbox(); + const stillPresent = claudeQqNotificationOutbox.items.some((candidate) => candidate.id === item.id); + await sql.begin(async (client) => { + if (stillPresent) await upsertClaudeQqNotificationToDatabase(client, item); + for (const id of deletedIds) await client`DELETE FROM unidesk_codex_queue_notifications WHERE id = ${id}`; + }); + if (stillPresent && !claudeQqNotificationOutbox.items.some((candidate) => candidate.id === item.id)) { + claudeQqNotificationOutbox.items.push(item); + pruneClaudeQqNotificationOutbox(); + } +} + +async function persistClaudeQqNotificationOutbox(): Promise { + if (!databaseReady) throw new Error("PostgreSQL is not ready for ClaudeQQ notification outbox"); + claudeQqNotificationOutbox.updatedAt = nowIso(); + const deletedIds = pruneClaudeQqNotificationOutbox(); + await sql.begin(async (client) => { + for (const item of claudeQqNotificationOutbox.items) await upsertClaudeQqNotificationToDatabase(client, item); + for (const id of deletedIds) await client`DELETE FROM unidesk_codex_queue_notifications WHERE id = ${id}`; + }); } function ensureQueue(queueId: string): QueueRecord { @@ -519,6 +661,7 @@ function ensureQueue(queueId: string): QueueRecord { const queue = { id, createdAt: at, updatedAt: at }; state.queues.push(queue); state.queues.sort((left, right) => left.id.localeCompare(right.id)); + markQueueDirty(id); return queue; } @@ -526,6 +669,19 @@ function queueIdOf(task: QueueTask): string { return safeQueueId(task.queueId); } +function taskQueueEnteredAt(task: QueueTask): string { + const raw = (task as QueueTask & { queueEnteredAt?: unknown }).queueEnteredAt; + const existing = taskTimestamp(typeof raw === "string" ? raw : null); + if (existing !== null) return existing; + const output = Array.isArray(task.output) ? task.output : []; + const entryEvents = output + .filter((item) => item.method === "queue/move" || item.method === "manual-retry") + .map((item) => taskTimestamp(item.at)) + .filter((at): at is string => at !== null) + .sort((left, right) => (timestampMs(right) ?? 0) - (timestampMs(left) ?? 0)); + return entryEvents[0] ?? taskTimestamp(task.createdAt) ?? taskTimestamp(task.updatedAt) ?? nowIso(); +} + function normalizeSteerPromptText(text: string): string { return text.replace(/^\s*\[steer\]\s*/u, "").trimEnd(); } @@ -563,8 +719,18 @@ function fallbackJudgeRetryCount(task: QueueTask): number { return Math.max(attemptCount, outputCount); } +function pruneTaskHotState(task: QueueTask): void { + if (config.maxInMemoryOutputRecords > 0 && task.output.length > config.maxInMemoryOutputRecords) { + task.output.splice(0, task.output.length - config.maxInMemoryOutputRecords); + } + if (config.maxInMemoryEventRecords > 0 && task.events.length > config.maxInMemoryEventRecords) { + task.events.splice(0, task.events.length - config.maxInMemoryEventRecords); + } +} + function normalizeTask(task: QueueTask): QueueTask { task.queueId = safeQueueId(task.queueId); + task.queueEnteredAt = taskQueueEnteredAt(task); task.output ??= []; task.events ??= []; task.attempts ??= []; @@ -579,46 +745,18 @@ function normalizeTask(task: QueueTask): QueueTask { task.judgeFailCount = Number.isInteger(task.judgeFailCount) && task.judgeFailCount >= 0 ? task.judgeFailCount : judgeFailCountFromOutput(task); const persistedPromptHistory = Array.isArray(task.promptHistory) ? task.promptHistory : []; task.promptHistory = mergePromptHistory([...persistedPromptHistory, ...outputPromptHistory(task)]); + pruneTaskHotState(task); return task; } -function readState(path: string): PersistedState { - mkdirSync(dirname(path), { recursive: true }); - if (!existsSync(path)) return emptyState(); - try { - const parsed = JSON.parse(readFileSync(path, "utf8")) as unknown; - if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return emptyState(); - const record = parsed as Partial; - const tasks = Array.isArray(record.tasks) ? (record.tasks as QueueTask[]).map(normalizeTask) : []; - const queueMap = new Map(); - for (const queue of Array.isArray(record.queues) ? record.queues : []) { - const normalized = normalizeQueueRecord(queue); - if (normalized !== null) queueMap.set(normalized.id, normalized); - } - const at = String(record.updatedAt ?? nowIso()); - if (!queueMap.has(defaultQueueId)) queueMap.set(defaultQueueId, { id: defaultQueueId, createdAt: at, updatedAt: at }); - for (const task of tasks) { - const id = queueIdOf(task); - if (!queueMap.has(id)) queueMap.set(id, { id, createdAt: task.createdAt, updatedAt: task.updatedAt }); - } - const queues = Array.from(queueMap.values()).sort((left, right) => left.id.localeCompare(right.id)); - return { version: 1, updatedAt: at, nextSeq: Number(record.nextSeq ?? 1), queues, tasks }; - } catch { - return emptyState(); - } -} - function persistState(markAllDatabaseTasks = true): void { persistDirty = false; if (persistTimer !== null) { clearTimeout(persistTimer); persistTimer = null; } + for (const task of state.tasks) pruneTaskHotState(task); state.updatedAt = nowIso(); - mkdirSync(dirname(config.statePath), { recursive: true }); - const tmp = `${config.statePath}.tmp`; - writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\n`, "utf8"); - renameSync(tmp, config.statePath); if (markAllDatabaseTasks) markAllDatabaseTasksDirty(); scheduleDatabaseFlush(); } @@ -653,18 +791,22 @@ function databaseErrorMessage(error: unknown): string { } function markTaskDirty(taskId: string): void { - if (sql === null) return; dirtyDatabaseTaskIds.add(taskId); scheduleDatabaseFlush(); } +function markQueueDirty(queueId: string): void { + dirtyDatabaseQueueIds.add(queueId); + scheduleDatabaseFlush(); +} + function markAllDatabaseTasksDirty(): void { - if (sql === null) return; for (const task of state.tasks) dirtyDatabaseTaskIds.add(task.id); + for (const queue of state.queues) dirtyDatabaseQueueIds.add(queue.id); } function scheduleDatabaseFlush(delayMs = config.databaseFlushIntervalMs): void { - if (sql === null || !databaseReady || dirtyDatabaseTaskIds.size === 0 || shutdownRequested) return; + if (!databaseReady || (dirtyDatabaseTaskIds.size === 0 && dirtyDatabaseQueueIds.size === 0) || shutdownRequested) return; if (databaseFlushTimer !== null) return; databaseFlushTimer = setTimeout(() => { databaseFlushTimer = null; @@ -779,19 +921,42 @@ async function upsertTaskToDatabase(client: SqlExecutor, task: QueueTask): Promi `; } +async function upsertQueueToDatabase(client: SqlExecutor, queue: QueueRecord): Promise { + await client` + INSERT INTO unidesk_codex_queue_queues ( + id, + created_at, + updated_at + ) VALUES ( + ${queue.id}, + ${taskTimestamp(queue.createdAt) ?? nowIso()}, + ${taskTimestamp(queue.updatedAt) ?? nowIso()} + ) + ON CONFLICT (id) DO UPDATE SET + updated_at = EXCLUDED.updated_at + `; +} + async function flushDirtyTasksToDatabase(force = false): Promise { - if (sql === null || !databaseReady) return; + if (!databaseReady) return; if (databaseFlushInFlight && !force) { scheduleDatabaseFlush(); return; } const ids = Array.from(dirtyDatabaseTaskIds); - if (ids.length === 0) return; + const queueIds = Array.from(dirtyDatabaseQueueIds); + if (ids.length === 0 && queueIds.length === 0) return; dirtyDatabaseTaskIds.clear(); + dirtyDatabaseQueueIds.clear(); databaseFlushInFlight = true; try { const byId = new Map(state.tasks.map((task) => [task.id, task])); + const queuesById = new Map(state.queues.map((queue) => [queue.id, queue])); await sql.begin(async (client) => { + for (const id of queueIds) { + const queue = queuesById.get(id); + if (queue !== undefined) await upsertQueueToDatabase(client, queue); + } for (const id of ids) { const task = byId.get(id); if (task !== undefined) await upsertTaskToDatabase(client, task); @@ -800,19 +965,16 @@ async function flushDirtyTasksToDatabase(force = false): Promise { databaseLastError = null; } catch (error) { for (const id of ids) dirtyDatabaseTaskIds.add(id); + for (const id of queueIds) dirtyDatabaseQueueIds.add(id); throw error; } finally { databaseFlushInFlight = false; - if (dirtyDatabaseTaskIds.size > 0) scheduleDatabaseFlush(); + if (dirtyDatabaseTaskIds.size > 0 || dirtyDatabaseQueueIds.size > 0) scheduleDatabaseFlush(); } } async function initDatabasePersistence(): Promise { - if (sql === null) { - logger("warn", "database_persistence_disabled", { reason: "DATABASE_URL is not configured" }); - return; - } - logger("info", "database_persistence_init_start", { databaseUrl: config.databaseUrl === null ? null : redactDatabaseUrl(config.databaseUrl) }); + logger("info", "database_persistence_init_start", { databaseUrl: redactDatabaseUrl(config.databaseUrl) }); await sql` CREATE TABLE IF NOT EXISTS unidesk_codex_queue_tasks ( id TEXT PRIMARY KEY, @@ -843,6 +1005,28 @@ async function initDatabasePersistence(): Promise { task_json JSONB NOT NULL ) `; + await sql` + CREATE TABLE IF NOT EXISTS unidesk_codex_queue_queues ( + id TEXT PRIMARY KEY, + created_at TIMESTAMPTZ NOT NULL, + updated_at TIMESTAMPTZ NOT NULL + ) + `; + await sql` + CREATE TABLE IF NOT EXISTS unidesk_codex_queue_notifications ( + id TEXT PRIMARY KEY, + kind TEXT NOT NULL, + dedup_key TEXT NOT NULL, + target TEXT NOT NULL, + message TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL, + updated_at TIMESTAMPTZ NOT NULL, + attempts INTEGER NOT NULL DEFAULT 0, + next_attempt_at TIMESTAMPTZ NOT NULL, + last_error TEXT, + sent_at TIMESTAMPTZ + ) + `; await sql`ALTER TABLE unidesk_codex_queue_tasks ADD COLUMN IF NOT EXISTS queue_id TEXT NOT NULL DEFAULT 'default'`; await sql`ALTER TABLE unidesk_codex_queue_tasks ADD COLUMN IF NOT EXISTS base_prompt TEXT NOT NULL DEFAULT ''`; await sql`ALTER TABLE unidesk_codex_queue_tasks ADD COLUMN IF NOT EXISTS reference_task_ids JSONB NOT NULL DEFAULT '[]'::jsonb`; @@ -851,12 +1035,19 @@ async function initDatabasePersistence(): Promise { await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_codex_queue_tasks_queue_status_updated ON unidesk_codex_queue_tasks(queue_id, status, updated_at DESC)`; await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_codex_queue_tasks_created ON unidesk_codex_queue_tasks(created_at DESC)`; await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_codex_queue_tasks_model_updated ON unidesk_codex_queue_tasks(model, updated_at DESC)`; + await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_codex_queue_notifications_pending ON unidesk_codex_queue_notifications(sent_at, next_attempt_at)`; + await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_codex_queue_notifications_created ON unidesk_codex_queue_notifications(created_at DESC)`; const rows = await sql>` SELECT id, updated_at, task_json FROM unidesk_codex_queue_tasks ORDER BY created_at ASC, id ASC `; + const queueRows = await sql>` + SELECT id, created_at, updated_at + FROM unidesk_codex_queue_queues + ORDER BY id ASC + `; const merged = new Map(); for (const row of rows) { try { @@ -866,32 +1057,49 @@ async function initDatabasePersistence(): Promise { logger("warn", "database_task_row_ignored", { id: String(row.id), error: errorToJson(error) }); } } - let fileTaskWins = 0; - for (const task of state.tasks) { - const existing = merged.get(task.id); - const fileUpdated = timestampMs(task.updatedAt) ?? 0; - const databaseUpdated = timestampMs(existing?.updatedAt) ?? 0; - if (existing === undefined || fileUpdated >= databaseUpdated) { - merged.set(task.id, normalizeTask(task)); - fileTaskWins += 1; - } - } if (merged.size > 0) { const tasks = Array.from(merged.values()).sort((left, right) => (timestampMs(left.createdAt) ?? 0) - (timestampMs(right.createdAt) ?? 0) || left.id.localeCompare(right.id)); state.tasks.splice(0, state.tasks.length, ...tasks); updateNextSeqFromTasks(); state.updatedAt = nowIso(); } + const queueMap = new Map(); + for (const row of queueRows) { + queueMap.set(row.id, { + id: safeQueueId(row.id), + createdAt: taskTimestamp(String(row.created_at)) ?? nowIso(), + updatedAt: taskTimestamp(String(row.updated_at)) ?? nowIso(), + }); + } + if (!queueMap.has(defaultQueueId)) queueMap.set(defaultQueueId, { id: defaultQueueId, createdAt: state.updatedAt, updatedAt: state.updatedAt }); + for (const task of state.tasks) { + const id = queueIdOf(task); + const existing = queueMap.get(id); + if (existing === undefined) { + queueMap.set(id, { id, createdAt: task.createdAt, updatedAt: task.updatedAt }); + } else if ((timestampMs(task.updatedAt) ?? 0) > (timestampMs(existing.updatedAt) ?? 0)) { + existing.updatedAt = task.updatedAt; + } + } + state.queues.splice(0, state.queues.length, ...Array.from(queueMap.values()).sort((left, right) => left.id.localeCompare(right.id))); + await loadClaudeQqNotificationOutboxFromDatabase(); databaseReady = true; markAllDatabaseTasksDirty(); await flushDirtyTasksToDatabase(true); - logger("info", "database_persistence_init_complete", { databaseTaskCount: rows.length, mergedTaskCount: state.tasks.length, fileTaskWins }); + await persistClaudeQqNotificationOutbox(); + logger("info", "database_persistence_init_complete", { + databaseTaskCount: rows.length, + databaseQueueCount: queueRows.length, + databaseNotificationCount: claudeQqNotificationOutbox.items.length, + taskCount: state.tasks.length, + queueCount: state.queues.length, + }); } async function initDatabasePersistenceWithRetry(): Promise { - if (sql === null) return; const started = Date.now(); let attempt = 0; + let reportedLongWait = false; while (!databaseReady) { attempt += 1; try { @@ -901,11 +1109,11 @@ async function initDatabasePersistenceWithRetry(): Promise { databaseLastError = databaseErrorMessage(error); const elapsedMs = Date.now() - started; logger("warn", "database_persistence_init_retry", { attempt, elapsedMs, error: errorToJson(error) }); - if (elapsedMs > 90_000) { - logger("error", "database_persistence_init_failed_falling_back_to_file", { attempt, elapsedMs, error: errorToJson(error) }); - return; + if (elapsedMs > 90_000 && !reportedLongWait) { + reportedLongWait = true; + logger("error", "database_persistence_required_still_waiting", { attempt, elapsedMs, error: errorToJson(error) }); } - await Bun.sleep(Math.min(1000 * attempt, 5000)); + await Bun.sleep(Math.min(1000 * attempt, 10_000)); } } } @@ -1510,6 +1718,7 @@ function createTask(request: QueueTaskRequest): QueueTask { return { id: makeTaskId(), queueId, + queueEnteredAt: at, prompt: request.prompt, basePrompt, referenceTaskIds, @@ -2021,6 +2230,7 @@ function taskForMetaResponse(task: QueueTask): JsonValue { return { id: task.id, queueId: queueIdOf(task), + queueEnteredAt: taskQueueEnteredAt(task), prompt: task.prompt, basePrompt: task.basePrompt, displayPrompt, @@ -2073,6 +2283,7 @@ function taskForCompactMetaResponse(task: QueueTask): JsonValue { return { id: task.id, queueId: queueIdOf(task), + queueEnteredAt: taskQueueEnteredAt(task), prompt: prefixPreview(task.prompt, 900), basePrompt: prefixPreview(task.basePrompt, 900), displayPrompt: prefixPreview(displayPrompt, 900), @@ -2370,14 +2581,24 @@ function attemptTimingSummary(attempt: AttemptSummary | null, lines: TranscriptL }; } -function traceAttemptWindows(task: QueueTask, transcript: TranscriptLine[]): Array<{ index: number; attempt: AttemptSummary | null; startSeq: number | null; endSeq: number | null; lines: TranscriptLine[] }> { +interface TraceAttemptWindow { + index: number; + attempt: AttemptSummary | null; + startSeq: number | null; + endSeq: number | null; + lines: TranscriptLine[]; + synthetic?: boolean; + label?: string; +} + +function traceAttemptWindows(task: QueueTask, transcript: TranscriptLine[]): TraceAttemptWindow[] { const starts = transcript .map((line, position) => ({ line, position, index: line.title === "Attempt started" ? traceAttemptIndexFromLine(line) : null })) .filter((item): item is { line: TranscriptLine; position: number; index: number } => item.index !== null) .sort((left, right) => Number(left.line.seq) - Number(right.line.seq)); const maxStartIndex = starts.reduce((max, item) => Math.max(max, item.index), 0); const maxIndex = Math.max(task.attempts.length, task.currentAttempt || 0, maxStartIndex); - const windows: Array<{ index: number; attempt: AttemptSummary | null; startSeq: number | null; endSeq: number | null; lines: TranscriptLine[] }> = []; + const windows: TraceAttemptWindow[] = []; for (let index = 1; index <= maxIndex; index += 1) { const attempt = task.attempts.find((item) => Number(item.index) === index) ?? task.attempts[index - 1] ?? null; const start = starts.find((item) => item.index === index) ?? starts[index - 1] ?? null; @@ -2402,7 +2623,44 @@ function traceAttemptWindows(task: QueueTask, transcript: TranscriptLine[]): Arr } windows.push({ index, attempt, startSeq, endSeq, lines }); } - return windows; + const coveredSeqs = new Set(); + for (const window of windows) { + for (const line of window.lines) coveredSeqs.add(Number(line.seq)); + } + const orphanedGroups: TranscriptLine[][] = []; + let group: TranscriptLine[] = []; + const flushGroup = (): void => { + if (group.length > 0 && executionLinesForAttempt(group).length > 0) orphanedGroups.push(group); + group = []; + }; + for (const line of transcript) { + const seq = Number(line.seq); + if (line.title === "Submitted prompt" || coveredSeqs.has(seq)) { + flushGroup(); + continue; + } + group.push(line); + } + flushGroup(); + + let syntheticIndex = -1; + for (const lines of orphanedGroups) { + const hasSteer = lines.some((line) => line.title === "Steer prompt" || line.status === "turn/steer"); + const startSeq = Number(lines[0]?.seq ?? NaN); + const endSeq = Number(lines.at(-1)?.seq ?? NaN); + windows.push({ + index: syntheticIndex, + attempt: null, + startSeq: Number.isFinite(startSeq) ? startSeq : null, + endSeq: Number.isFinite(endSeq) ? endSeq : null, + lines, + synthetic: true, + label: hasSteer ? "Recovered thread execution with steer prompt" : "Recovered thread execution", + }); + syntheticIndex -= 1; + } + + return windows.sort((left, right) => Number(left.lines[0]?.seq ?? left.startSeq ?? 0) - Number(right.lines[0]?.seq ?? right.startSeq ?? 0)); } function executionLinesForAttempt(lines: TranscriptLine[]): TranscriptLine[] { @@ -2415,15 +2673,18 @@ function taskTraceAttemptSummaries(task: QueueTask, transcript: TranscriptLine[] const attempt = window.attempt; const parsedJudge = judgeFromAttemptLines(window.lines); const storedJudge = attempt?.judge ?? null; - const judge = storedJudge ?? parsedJudge?.judge ?? (window.index === task.attempts.length && task.lastJudge !== null ? task.lastJudge : null); - const finalResponse = String(attempt?.finalResponse ?? attempt?.finalResponsePreview ?? (window.index === task.attempts.length ? task.finalResponse : "")); + const synthetic = window.synthetic === true; + const judge = synthetic ? null : storedJudge ?? parsedJudge?.judge ?? (window.index === task.attempts.length && task.lastJudge !== null ? task.lastJudge : null); + const finalResponse = synthetic ? "" : String(attempt?.finalResponse ?? attempt?.finalResponsePreview ?? (window.index === task.attempts.length ? task.finalResponse : "")); const finalResponseChars = Number(attempt?.finalResponseChars ?? finalResponse.length); const executionLines = executionLinesForAttempt(window.lines); - const feedbackPrompt = attemptFeedbackPromptRecord(task, window.index, attempt, judge); + const feedbackPrompt = synthetic ? null : attemptFeedbackPromptRecord(task, window.index, attempt, judge); const inputPrompt = promptSnapshot(String(attempt?.inputPrompt ?? ""), 1200); return { ...(attempt ?? {}), index: attempt?.index ?? window.index, + synthetic, + label: window.label ?? null, mode: attempt?.mode ?? (window.index <= 1 ? "initial" : "retry"), startedAt: attempt?.startedAt ?? window.lines[0]?.at ?? task.startedAt, finishedAt: attempt?.finishedAt ?? null, @@ -3009,6 +3270,7 @@ function taskForListResponse(task: QueueTask, lite = false): JsonValue { return { id: task.id, queueId: queueIdOf(task), + queueEnteredAt: taskQueueEnteredAt(task), prompt: prefixPreview(displayPrompt, 360), basePrompt: prefixPreview(task.basePrompt, 360), displayPrompt: prefixPreview(displayPrompt, 360), @@ -3059,6 +3321,7 @@ function taskForListResponse(task: QueueTask, lite = false): JsonValue { return { id: task.id, queueId: queueIdOf(task), + queueEnteredAt: taskQueueEnteredAt(task), prompt: safePreview(displayPrompt, 2000), basePrompt: safePreview(task.basePrompt, 2000), displayPrompt: safePreview(displayPrompt, 2000), @@ -3136,8 +3399,12 @@ function perQueueSummaries(): JsonValue[] { summary.total += 1; summary.counts[task.status] = (summary.counts[task.status] ?? 0) + 1; if (terminalTaskUnread(task)) summary.unreadTerminal += 1; - if (summary.activeTaskId === null && (task.status === "running" || task.status === "judging")) summary.activeTaskId = task.id; - if (summary.runnableTaskId === null && (task.status === "queued" || task.status === "retry_wait")) summary.runnableTaskId = task.id; + } + for (const [queueId, summary] of summaries) { + const activeRun = activeRuns.get(queueId); + const head = queueHeadTask(queueId); + summary.activeTaskId = activeRun?.taskId ?? (head !== null && (head.status === "running" || head.status === "judging") ? head.id : null); + summary.runnableTaskId = head !== null && queueTaskIsRunnable(head) ? head.id : null; } const rows = Array.from(summaries.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([queueId, summary]) => { return { @@ -3198,15 +3465,16 @@ function queueSummary(includeDevReady = true): JsonValue { maxResponseChars: config.notifyClaudeQqMaxResponseChars, timeoutMs: config.notifyClaudeQqTimeoutMs, sendAttempts: config.notifyClaudeQqSendAttempts, + retryIntervalMs: config.notifyClaudeQqRetryIntervalMs, + outbox: claudeQqNotificationOutboxStats(), }, }, storage: { - primary: databaseReady ? "postgres" : "file", - postgresConfigured: sql !== null, + primary: "postgres", + postgresConfigured: true, postgresReady: databaseReady, dirtyTaskCount: dirtyDatabaseTaskIds.size, lastError: databaseLastError, - statePath: config.statePath, outputArchiveDir: config.outputArchiveDir, inMemoryOutputRecords: config.maxInMemoryOutputRecords, inMemoryEventRecords: config.maxInMemoryEventRecords, @@ -3317,6 +3585,150 @@ function rememberTaskNotificationKey(key: string): void { } } +function claudeQqNotificationId(kind: string, dedupKey: string): string { + return `${kind}:${dedupKey}`; +} + +function claudeQqNotificationOutboxStats(): Record { + const pending = claudeQqNotificationOutbox.items.filter((item) => item.sentAt === null); + const failed = pending.filter((item) => item.lastError !== null); + const oldestPending = pending.reduce((oldest, item) => { + if (oldest === null) return item.createdAt; + return (timestampMs(item.createdAt) ?? 0) < (timestampMs(oldest) ?? 0) ? item.createdAt : oldest; + }, null); + return { + storage: "postgres", + total: claudeQqNotificationOutbox.items.length, + pending: pending.length, + failed: failed.length, + sent: claudeQqNotificationOutbox.items.length - pending.length, + inFlight: claudeQqNotificationDrainInFlight, + nextDueAt: pending + .map((item) => item.nextAttemptAt) + .sort((left, right) => (timestampMs(left) ?? 0) - (timestampMs(right) ?? 0))[0] ?? null, + oldestPendingAt: oldestPending, + }; +} + +function pruneClaudeQqNotificationOutbox(): string[] { + const beforeIds = new Set(claudeQqNotificationOutbox.items.map((item) => item.id)); + const pending = claudeQqNotificationOutbox.items.filter((item) => item.sentAt === null); + const sent = claudeQqNotificationOutbox.items + .filter((item) => item.sentAt !== null) + .sort((left, right) => (timestampMs(right.sentAt) ?? 0) - (timestampMs(left.sentAt) ?? 0)); + const sentBudget = Math.max(0, config.notifyClaudeQqMaxOutboxItems - pending.length); + claudeQqNotificationOutbox.items = [...pending, ...sent.slice(0, sentBudget)] + .sort((left, right) => (timestampMs(left.createdAt) ?? 0) - (timestampMs(right.createdAt) ?? 0)); + const afterIds = new Set(claudeQqNotificationOutbox.items.map((item) => item.id)); + return Array.from(beforeIds).filter((id) => !afterIds.has(id)); +} + +function claudeQqNotificationRetryDelayMs(attempts: number): number { + const exponent = Math.max(0, Math.min(8, attempts - 1)); + return Math.min(30 * 60_000, config.notifyClaudeQqRetryIntervalMs * (2 ** exponent)); +} + +function scheduleClaudeQqNotificationDrain(delayMs = config.notifyClaudeQqRetryIntervalMs): void { + if (!notificationTargetConfigured() || shutdownRequested) return; + if (claudeQqNotificationOutbox.items.every((item) => item.sentAt !== null)) return; + if (claudeQqNotificationDrainTimer !== null) return; + claudeQqNotificationDrainTimer = setTimeout(() => { + claudeQqNotificationDrainTimer = null; + void drainClaudeQqNotificationOutbox("timer").catch((error) => logger("warn", "claudeqq_notify_outbox_drain_failed", { trigger: "timer", error: errorToJson(error) })); + }, Math.max(1000, delayMs)); +} + +async function enqueueClaudeQqNotification(kind: string, dedupKey: string, message: string): Promise { + if (!notificationTargetConfigured()) return false; + const id = claudeQqNotificationId(kind, dedupKey); + const existing = claudeQqNotificationOutbox.items.find((item) => item.id === id); + if (existing !== undefined && existing.sentAt !== null) return false; + const at = nowIso(); + let item: ClaudeQqNotificationItem; + if (existing !== undefined) { + existing.message = message; + existing.target = notificationTargetLabel(); + existing.updatedAt = at; + existing.nextAttemptAt = at; + existing.lastError = null; + item = existing; + } else { + item = { + id, + kind, + dedupKey, + target: notificationTargetLabel(), + message, + createdAt: at, + updatedAt: at, + attempts: 0, + nextAttemptAt: at, + lastError: null, + sentAt: null, + }; + claudeQqNotificationOutbox.items.push(item); + } + await persistClaudeQqNotificationItem(item); + void drainClaudeQqNotificationOutbox(`enqueue:${kind}`).catch((error) => logger("warn", "claudeqq_notify_outbox_drain_failed", { trigger: `enqueue:${kind}`, error: errorToJson(error) })); + return true; +} + +function dueClaudeQqNotificationItems(limit = 3): ClaudeQqNotificationItem[] { + const nowMs = Date.now(); + return claudeQqNotificationOutbox.items + .filter((item) => item.sentAt === null && (timestampMs(item.nextAttemptAt) ?? 0) <= nowMs) + .sort((left, right) => (timestampMs(left.nextAttemptAt) ?? 0) - (timestampMs(right.nextAttemptAt) ?? 0)) + .slice(0, limit); +} + +async function drainClaudeQqNotificationOutbox(trigger = "manual"): Promise> { + if (!notificationTargetConfigured()) return { ok: true, trigger, skipped: "not_configured" }; + if (claudeQqNotificationDrainInFlight) return { ok: true, trigger, skipped: "in_flight" }; + claudeQqNotificationDrainInFlight = true; + let sent = 0; + let failed = 0; + try { + await loadClaudeQqNotificationOutboxFromDatabase(); + const due = dueClaudeQqNotificationItems(); + for (const item of due) { + item.attempts += 1; + item.updatedAt = nowIso(); + await persistClaudeQqNotificationItem(item); + try { + await postClaudeQqText(item.kind, item.message); + item.sentAt = nowIso(); + item.updatedAt = item.sentAt; + item.lastError = null; + sent += 1; + if (item.kind === "task_terminal") rememberTaskNotificationKey(item.dedupKey); + logger("info", "claudeqq_notify_outbox_sent", { id: item.id, kind: item.kind, target: item.target, attempts: item.attempts, trigger }); + } catch (error) { + failed += 1; + const message = error instanceof Error ? error.message : String(error); + item.lastError = safePreview(message, 1000); + item.updatedAt = nowIso(); + item.nextAttemptAt = new Date(Date.now() + claudeQqNotificationRetryDelayMs(item.attempts)).toISOString(); + logger("warn", "claudeqq_notify_outbox_retry_scheduled", { + id: item.id, + kind: item.kind, + target: item.target, + attempts: item.attempts, + nextAttemptAt: item.nextAttemptAt, + trigger, + error: errorToJson(error), + }); + } finally { + await persistClaudeQqNotificationItem(item); + } + } + } finally { + claudeQqNotificationDrainInFlight = false; + await persistClaudeQqNotificationOutbox(); + if (claudeQqNotificationOutbox.items.some((item) => item.sentAt === null)) scheduleClaudeQqNotificationDrain(); + } + return { ok: true, trigger, sent, failed, outbox: claudeQqNotificationOutboxStats() }; +} + async function postClaudeQqText(kind: string, message: string): Promise { if (!notificationTargetConfigured()) return; const url = `${config.notifyClaudeQqBaseUrl}/api/push/text`; @@ -3363,31 +3775,33 @@ async function postClaudeQqText(kind: string, message: string): Promise { } } +function taskTerminalNotificationMessage(task: QueueTask): string { + const stats = queueNotificationStats(); + const totalElapsed = formatDurationMs(durationMsBetween(task.createdAt, task.finishedAt ?? task.updatedAt)); + const runElapsed = formatDurationMs(durationMsBetween(task.startedAt ?? task.createdAt, task.finishedAt ?? task.updatedAt)); + const response = truncateNotificationText(taskFinalResponseForNotification(task), config.notifyClaudeQqMaxResponseChars); + return [ + "Codex Queue 任务结束", + `task: ${task.id}`, + `queue: ${queueIdOf(task)}`, + `status: ${task.status}`, + `model: ${task.model}${task.reasoningEffort ? ` (${task.reasoningEffort})` : ""}`, + `attempts: ${task.attempts.length}/${task.maxAttempts}`, + `elapsed: total=${totalElapsed}, run=${runElapsed}`, + `current queue: running=${stats.running}, queued=${stats.queued}, retry_wait=${stats.retryWait}`, + "", + "Final response:", + response, + ].join("\n"); +} + async function notifyTaskTerminal(task: QueueTask): Promise { if (!terminalTask(task) || !notificationTargetConfigured()) return; const key = taskNotificationKey(task); if (sentTaskNotificationKeys.has(key) || inFlightTaskNotificationKeys.has(key)) return; inFlightTaskNotificationKeys.add(key); try { - const stats = queueNotificationStats(); - const totalElapsed = formatDurationMs(durationMsBetween(task.createdAt, task.finishedAt ?? task.updatedAt)); - const runElapsed = formatDurationMs(durationMsBetween(task.startedAt ?? task.createdAt, task.finishedAt ?? task.updatedAt)); - const response = truncateNotificationText(taskFinalResponseForNotification(task), config.notifyClaudeQqMaxResponseChars); - const message = [ - "Codex Queue 任务结束", - `task: ${task.id}`, - `queue: ${queueIdOf(task)}`, - `status: ${task.status}`, - `model: ${task.model}${task.reasoningEffort ? ` (${task.reasoningEffort})` : ""}`, - `attempts: ${task.attempts.length}/${task.maxAttempts}`, - `elapsed: total=${totalElapsed}, run=${runElapsed}`, - `current queue: running=${stats.running}, queued=${stats.queued}, retry_wait=${stats.retryWait}`, - "", - "Final response:", - response, - ].join("\n"); - await postClaudeQqText("task_terminal", message); - rememberTaskNotificationKey(key); + await enqueueClaudeQqNotification("task_terminal", key, taskTerminalNotificationMessage(task)); } catch (error) { logger("warn", "claudeqq_task_notify_failed", { taskId: task.id, status: task.status, target: notificationTargetLabel(), error: errorToJson(error) }); } finally { @@ -3395,6 +3809,31 @@ async function notifyTaskTerminal(task: QueueTask): Promise { } } +async function backfillClaudeQqTaskNotifications(since: string | null, limit: number, dryRun: boolean): Promise> { + if (!notificationTargetConfigured()) return { ok: true, skipped: "not_configured" }; + await loadClaudeQqNotificationOutboxFromDatabase(); + const sinceMs = timestampMs(since); + const candidates = state.tasks + .filter((task) => terminalTask(task)) + .filter((task) => sinceMs === null || (timestampMs(task.finishedAt ?? task.updatedAt) ?? 0) > sinceMs) + .sort((left, right) => (timestampMs(left.finishedAt ?? left.updatedAt) ?? 0) - (timestampMs(right.finishedAt ?? right.updatedAt) ?? 0)) + .slice(0, limit); + const items = candidates.map((task) => ({ + taskId: task.id, + status: task.status, + queueId: queueIdOf(task), + finishedAt: task.finishedAt ?? task.updatedAt, + dedupKey: taskNotificationKey(task), + alreadyInOutbox: claudeQqNotificationOutbox.items.some((item) => item.id === claudeQqNotificationId("task_terminal", taskNotificationKey(task))), + })); + if (dryRun) return { ok: true, dryRun, since: since ?? null, scanned: candidates.length, enqueued: 0, items }; + let enqueued = 0; + for (const task of candidates) { + if (await enqueueClaudeQqNotification("task_terminal", taskNotificationKey(task), taskTerminalNotificationMessage(task))) enqueued += 1; + } + return { ok: true, dryRun, since: since ?? null, scanned: candidates.length, enqueued, outbox: claudeQqNotificationOutboxStats(), items }; +} + function armIdleNotification(): void { if (notificationTargetConfigured()) idleNotificationSent = false; } @@ -3411,7 +3850,7 @@ async function maybeNotifyQueueIdle(triggerTaskId: string | null = null): Promis `total tasks=${stats.total}, queues=${stats.queueCount}`, triggerTaskId === null ? "" : `last task=${triggerTaskId}`, ].filter((line) => line.length > 0).join("\n"); - await postClaudeQqText("queue_idle", message); + await enqueueClaudeQqNotification("queue_idle", `queue_idle:${triggerTaskId ?? "unknown"}:${stats.total}`, message); idleNotificationSent = true; } catch (error) { logger("warn", "claudeqq_idle_notify_failed", { triggerTaskId: triggerTaskId ?? "", target: notificationTargetLabel(), error: errorToJson(error) }); @@ -3792,24 +4231,24 @@ async function runCodexTurn(task: QueueTask, prompt: string): Promise { if (explicitUserInterrupt(task, result)) return fallbackJudge(result); - if (config.minimaxApiKey.length === 0) return fallbackJudge(result); + if (config.minimaxApiKey.length === 0) return applyFallbackSafetyOverrides(task, result, fallbackJudge(result)); const messages: Array<{ role: "system" | "user" | "assistant"; content: string }> = [ - { role: "system", content: "You are a strict task-state classifier. Return compact JSON only. Never wrap JSON in Markdown fences." }, + { role: "system", content: "你是严格的任务状态分类器。只能返回紧凑 JSON,不得使用 Markdown fence。所有自然语言字段必须使用中文,尤其是 reason 和 continuePrompt。" }, { role: "user", content: judgePrompt(task, result) }, ]; try { @@ -3999,7 +4563,7 @@ async function judgeTask(task: QueueTask, result: CodexRunResult): Promise 0 ? parsed.continuePrompt : undefined, + continuePrompt: typeof parsed.continuePrompt === "string" && parsed.continuePrompt.trim().length > 0 ? boundedContinuationPrompt(parsed.continuePrompt) : undefined, source: "minimax", raw: { ...(parsed as Record), _parseSource: parsedResult.source, _repairAttempt: repairAttempt }, }; @@ -4017,9 +4581,9 @@ async function judgeTask(task: QueueTask, result: CodexRunResult): Promise 执行过程 Summary 1 -> finalresponse1 -> judge1 -> 执行过程 Summary 2 -> finalresponse2 judge2 还不够,还要有 judge feedback prompt,例如 originprompt -> 执行过程 Summary 1 -> finalresponse1 -> judge1 -> judge feedback prompt -> 执行过程 Summary 2 -> finalresponse2 judge2", + finalResponse: "已把 Trace 顶级链路补成:origin prompt -> Summary 1 -> final response 1 -> judge 1 -> judge feedback prompt -> Summary 2 -> final response 2 -> judge 2。后端扩展 attempt 数据,trace-summary 现在返回 feedback prompt preview/chars/lines/source,/api/tasks/:id/prompt?part=feedback&attempt=N 支持按需拉取完整内容,前端显示 feedback prompt cards。验证已通过:bun run --cwd src/components/microservices/codex-queue check、bun run --cwd src/components/frontend check、bun scripts/cli.ts check、git diff --check。当前 git diff clean。我没有重建运行中的容器。若要上线验证:1. bun scripts/cli.ts server rebuild codex-queue 2. bun scripts/cli.ts server rebuild frontend。", + expected: "retry", + terminalStatus: "completed", + outputs: [ + { + channel: "user", + text: "originprompt -> 执行过程 Summary 1 -> finalresponse1 -> judge1 -> 执行过程 Summary 2 -> finalresponse2 judge2 还不够,还要有 judge feedback prompt,例如 originprompt -> 执行过程 Summary 1 -> finalresponse1 -> judge1 -> judge feedback prompt -> 执行过程 Summary 2 -> finalresponse2 judge2\n", + method: "enqueue", + }, + { channel: "diff", text: "item/completed: file changes status=completed; M src/components/microservices/codex-queue/src/index.ts M src/components/frontend/src/codex-queue.tsx", method: "item/completed" }, + { channel: "command", text: "item/completed: bun run --cwd src/components/microservices/codex-queue check status=completed; ok=true", method: "item/completed" }, + { channel: "command", text: "item/completed: bun run --cwd src/components/frontend check status=completed; ok=true", method: "item/completed" }, + { + channel: "assistant", + text: "已把 Trace 顶级链路补成 judge feedback prompt。验证已通过 type/check;我没有重建运行中的容器。若要上线验证可重建 codex-queue 和 frontend。", + method: "item/agentMessage/delta", + }, + { channel: "system", text: "turn completed status=completed\n", method: "turn/completed" }, + ], + events: [{ at: nowIso(), method: "turn/completed", status: "completed" }], + }, + { + id: "beijing_time_deployed_after_prior_retry_feedback_should_complete", + prompt: "unidesk 的所有 frontend 时间显示必须采用北京时间,要修改 unidesk 的前端,并在长期参考文档中要求这一点", + finalResponse: "已完成北京时间任务并已上线验证。源码新增统一北京时间工具并替换 frontend 时间显示入口;长期参考文档已加入 Frontend Time Zone Policy,要求所有 UniDesk frontend timestamps、clocks、Trace times、Gantt labels 和 datetime-local 都固定使用 Asia/Shanghai / UTC+8。已执行 `bun scripts/cli.ts server rebuild frontend`,job succeeded,`unidesk-frontend` healthy。已用 Playwright 打开公网 UniDesk UI,并在 America/Los_Angeles 浏览器时区下验证顶部北京时间时钟、任务历史、Codex Queue card、Codex Trace 和 Pipeline run 时间都显示北京时间。本轮不是只改源码未上线,运行中 served UI 已验证通过。", + expected: "complete", + terminalStatus: "completed", + outputs: [ + { + channel: "user", + text: "unidesk 的所有 frontend 时间显示必须采用北京时间,要修改 unidesk 的前端,并在长期参考文档中要求这一点\n", + method: "enqueue", + }, + { + channel: "system", + text: "judge=retry confidence=0.95 source=minimax: Frontend bundle was not rebuilt/deployed; finalResponse explicitly states the frontend rebuild was skipped to avoid service restart.\n", + method: "judge", + }, + { + channel: "system", + text: "上一次 judge 判定为 retry:当前实现仍是未上线/未完成状态,不能只复述源码修改。\n", + method: "queue", + }, + { + channel: "command", + text: "item/completed: bun scripts/cli.ts server rebuild frontend status=completed; job succeeded; unidesk-frontend healthy", + method: "item/completed", + }, + { + channel: "command", + text: "item/completed: Playwright live UI verification under America/Los_Angeles timezone status=completed; topbar/task/Codex/Pipeline times use Asia/Shanghai", + method: "item/completed", + }, + { + channel: "assistant", + text: "已完成北京时间任务并已上线验证。长期参考文档已加入 Frontend Time Zone Policy。已执行 server rebuild frontend,job succeeded,unidesk-frontend healthy。Playwright live UI verification 通过。本轮不是只改源码未上线,运行中 served UI 已验证通过。", + method: "item/agentMessage/delta", + }, + { channel: "system", text: "turn completed status=completed\n", method: "turn/completed" }, + ], + events: [{ at: nowIso(), method: "turn/completed", status: "completed" }], + }, { id: "transport_closed_before_terminal", prompt: "Refactor the queue worker and run the focused tests.", @@ -4253,6 +4908,7 @@ function taskForJudgeProbe(probe: JudgeProbeCase): QueueTask { return { id: `judge_probe_${probe.id}`, queueId: defaultQueueId, + queueEnteredAt: at, prompt: probe.prompt, basePrompt: probe.prompt, referenceTaskIds: [], @@ -4310,15 +4966,20 @@ async function runJudgeProbe(): Promise { const finishedAt = nowIso(); task.attempts.push(attemptFromResult(task, "initial", startedAt, finishedAt, result)); const judge = await judgeTask(task, result); + const expectedContinuePromptIncludes = probe.expectedContinuePromptIncludes ?? []; + const continuePrompt = judge.continuePrompt ?? ""; + const continuePromptHit = expectedContinuePromptIncludes.every((text) => continuePrompt.includes(text)); return { id: probe.id, expected: probe.expected, decision: judge.decision, - hit: judge.decision === probe.expected, + hit: judge.decision === probe.expected && continuePromptHit, + continuePromptHit, + expectedContinuePromptIncludes, confidence: judge.confidence, source: judge.source, reason: judge.reason, - continuePrompt: judge.continuePrompt ?? null, + continuePrompt: continuePrompt.length > 0 ? continuePrompt : null, }; })); const hits = results.filter((result) => result.hit).length; @@ -4361,24 +5022,58 @@ function attemptFromResult(task: QueueTask, mode: RunMode, startedAt: string, fi return attempt; } -function taskPromptWithReferenceContext(task: QueueTask): string { - const referenceTaskIds = task.referenceTaskIds.length > 0 ? task.referenceTaskIds : referenceTaskIdsFromPrompt(task.basePrompt || userPromptForDisplay(task.prompt)); - let taskPrompt = stripCodexQueueEnvironmentHint(task.prompt); - if (referenceTaskIds.length > 0) { - try { - const basePrompt = task.basePrompt || userPromptForDisplay(task.prompt); - taskPrompt = injectReferencedTaskContext({ prompt: basePrompt, basePrompt, referenceTaskIds }).prompt; - } catch (error) { - logger("warn", "retry_reference_context_injection_failed", { taskId: task.id, error: error instanceof Error ? error.message : String(error) }); - } - } - return taskPrompt; +const retryTaskSummaryMaxChars = 1200; +const judgeReasonPromptMaxChars = 1200; +const maxContinuationPromptChars = 4000; + +function judgeReasonForPrompt(reason: string): string { + return safePreview(reason, judgeReasonPromptMaxChars) || "(empty)"; +} + +function boundedContinuationPrompt(prompt: string): string { + const trimmed = prompt.trim(); + if (trimmed.length <= maxContinuationPromptChars) return trimmed; + return [ + trimmed.slice(0, maxContinuationPromptChars), + "", + "[Codex Queue: judge continuePrompt 过长,已截断;请基于上述关键反馈和当前 thread 上文继续,不要粘贴长上下文。]", + ].join("\n"); +} + +function compactRetryTaskContext(task: QueueTask): string { + const basePrompt = task.basePrompt || userPromptForDisplay(task.prompt); + const referenceTaskIds = taskReferenceIds(task); + return [ + "原始任务摘要(同一 thread 已有完整上文,不重新注入引用全文):", + safePreview(basePrompt, retryTaskSummaryMaxChars) || "(empty)", + referenceTaskIds.length > 0 ? `引用任务 ID:${referenceTaskIds.join(", ")}` : "", + `按需查询有界摘要:bun scripts/cli.ts codex task ${task.id}`, + ].filter((line) => line.length > 0).join("\n"); +} + +function queueRecoveryRetryPrompt(task: QueueTask, reason: string): string { + return [ + retryInstruction, + "Codex Queue 服务在任务运行中重启/停止;这是自动恢复提示,不是新任务,也不需要重新粘贴原始任务或引用全文。", + `恢复原因:${judgeReasonForPrompt(reason)}`, + "请基于当前 thread 上文继续,只做最小必要状态核查,恢复未完成的等待、验证、部署或命令;最终 response 必须给出真实结果证据。", + "原始任务摘要/按需查询:", + compactRetryTaskContext(task), + ].join("\n\n"); } function retryPrompt(task: QueueTask, judge: JudgeResult): string { - if (judge.continuePrompt !== undefined && judge.continuePrompt.trim().length > 0) return judge.continuePrompt; - const taskPrompt = taskPromptWithReferenceContext(task); - return [retryInstruction, "原始任务/引用上下文:", taskPrompt].join("\n\n"); + if (judge.continuePrompt !== undefined && judge.continuePrompt.trim().length > 0) return boundedContinuationPrompt(judge.continuePrompt); + return [ + retryInstruction, + "上一次 judge 判定为 retry,下面是必须传递给本轮 continuation 的 judge feedback。请优先补齐这些缺口,不要只做泛泛的状态核查。", + `judge 来源:${judge.source}`, + `judge 置信度:${judge.confidence.toFixed(2)}`, + `judge 未完成原因:${judgeReasonForPrompt(judge.reason)}`, + "请在本轮最终 response 中明确说明已如何解决上述 judge feedback;如果 judge 要求 benchmark/上线/运行中验证,就必须提供对应真实命令和结果证据。", + "原始任务摘要/按需查询:", + compactRetryTaskContext(task), + ].join("\n\n"); } function retryBackoffMs(completedAttempts: number): number { @@ -4397,17 +5092,16 @@ async function sleepForRetryBackoff(task: QueueTask, delayMs: number): Promise 0) { - parts.push("judge 建议的继续提示:", judge.continuePrompt.trim()); + parts.push("judge 建议的继续提示:", boundedContinuationPrompt(judge.continuePrompt)); } - parts.push("原始任务/引用上下文:", taskPrompt); + parts.push("原始任务摘要/按需查询:", compactRetryTaskContext(task)); return parts.join("\n\n"); } @@ -4419,7 +5113,7 @@ function queueActiveTasksForRestartRetry(reason: string, method: string): number task.activeTurnId = null; task.lastError = reason; task.nextMode = "retry"; - task.nextPrompt = retryPrompt(task, { decision: "retry", confidence: 1, reason, source: "fallback" }); + task.nextPrompt = queueRecoveryRetryPrompt(task, reason); task.maxAttempts = Math.max(task.maxAttempts, maxTaskAttempts, task.attempts.length + 1); setAttemptFeedbackPrompt(task.attempts.at(-1), task.nextPrompt, "queue-recovery-retry", task.attempts.length + 1); task.updatedAt = nowIso(); @@ -4432,7 +5126,7 @@ function queueActiveTasksForRestartRetry(reason: string, method: string): number function failTaskForFallbackRetryLimit(task: QueueTask, judge: JudgeResult | null): void { const count = fallbackJudgeRetryCount(task); - const reason = `Fallback judge retry limit reached (${count}/${fallbackJudgeRetryLimit}). ${judge?.reason ?? task.lastJudge?.reason ?? "MiniMax judge was unavailable."}`; + const reason = `Fallback/non-LLM judge retry limit reached (${count}/${fallbackJudgeRetryLimit}). ${judge?.reason ?? task.lastJudge?.reason ?? "MiniMax judge was unavailable."}`; task.status = "failed"; task.finishedAt = nowIso(); task.updatedAt = task.finishedAt; @@ -4453,7 +5147,7 @@ function failTaskForFallbackRetryLimit(task: QueueTask, judge: JudgeResult | nul async function runTask(task: QueueTask): Promise { logger("info", "task_run_start", { taskId: task.id, queueId: queueIdOf(task), maxAttempts: task.maxAttempts, model: task.model, promptPreview: safePreview(task.prompt, 240) }); - if (task.status === "retry_wait" && task.lastJudge?.source === "fallback" && task.lastJudge.decision === "retry" && fallbackJudgeRetryCount(task) > fallbackJudgeRetryLimit) { + if (task.status === "retry_wait" && task.lastJudge?.source === "fallback" && task.lastJudge.decision === "retry" && fallbackJudgeRetryCount(task) >= fallbackJudgeRetryLimit) { failTaskForFallbackRetryLimit(task, task.lastJudge); return; } @@ -4540,7 +5234,7 @@ async function runTask(task: QueueTask): Promise { void notifyTaskTerminal(task); return; } - if (judge.source === "fallback" && fallbackJudgeRetryCount(task) > fallbackJudgeRetryLimit) { + if (judge.source === "fallback" && fallbackJudgeRetryCount(task) >= fallbackJudgeRetryLimit) { failTaskForFallbackRetryLimit(task, judge); return; } @@ -4583,21 +5277,53 @@ function updateProcessingFlag(): void { processing = processingQueues.size > 0; } +function taskQueueOrderMs(task: QueueTask): number { + return timestampMs(taskQueueEnteredAt(task)) ?? timestampMs(task.createdAt) ?? timestampMs(task.updatedAt) ?? 0; +} + +function compareTaskQueueOrder(left: QueueTask, right: QueueTask): number { + const queueDelta = taskQueueOrderMs(left) - taskQueueOrderMs(right); + if (queueDelta !== 0) return queueDelta; + const createdDelta = (timestampMs(left.createdAt) ?? 0) - (timestampMs(right.createdAt) ?? 0); + if (createdDelta !== 0) return createdDelta; + return left.id.localeCompare(right.id); +} + +function queueTaskIsRunnable(task: QueueTask): boolean { + return task.status === "queued" || task.status === "retry_wait"; +} + +function queueTaskBlocksFollowing(task: QueueTask): boolean { + return !terminalTask(task); +} + +function queueTaskRows(queueId: string, tasks: QueueTask[] = state.tasks): QueueTask[] { + return tasks + .filter((task) => queueIdOf(task) === queueId) + .sort(compareTaskQueueOrder); +} + +function queueHeadTask(queueId: string, tasks: QueueTask[] = state.tasks): QueueTask | null { + return queueTaskRows(queueId, tasks).find(queueTaskBlocksFollowing) ?? null; +} + +function nextRunnableTaskFrom(queueId: string, tasks: QueueTask[] = state.tasks): QueueTask | null { + const head = queueHeadTask(queueId, tasks); + return head !== null && queueTaskIsRunnable(head) ? head : null; +} + +function queueIdsForTasks(tasks: QueueTask[] = state.tasks): string[] { + const ids = new Set(tasks === state.tasks ? state.queues.map((queue) => queue.id) : []); + for (const task of tasks) ids.add(queueIdOf(task)); + return Array.from(ids).sort((left, right) => left.localeCompare(right)); +} + function runnableQueueIds(): string[] { - const ids: string[] = []; - const seen = new Set(); - for (const task of state.tasks) { - if (task.status !== "queued" && task.status !== "retry_wait") continue; - const queueId = queueIdOf(task); - if (seen.has(queueId)) continue; - seen.add(queueId); - ids.push(queueId); - } - return ids; + return queueIdsForTasks().filter((queueId) => nextRunnableTaskFrom(queueId) !== null); } function nextRunnableTask(queueId: string): QueueTask | null { - return state.tasks.find((item) => queueIdOf(item) === queueId && (item.status === "queued" || item.status === "retry_wait")) ?? null; + return nextRunnableTaskFrom(queueId); } async function processQueue(queueId: string): Promise { @@ -4672,7 +5398,14 @@ function installShutdownHandlers(): void { updateProcessingFlag(); persistState(); logger("warn", "service_shutdown_requeued_active_tasks", { signal, recovered }); - process.exit(0); + const forceExit = setTimeout(() => process.exit(1), 8_000); + forceExit.unref?.(); + void flushDirtyTasksToDatabase(true) + .then(() => process.exit(0)) + .catch((error) => { + logger("error", "service_shutdown_database_flush_failed", { signal, error: errorToJson(error) }); + process.exit(1); + }); }; process.once("SIGTERM", stop); process.once("SIGINT", stop); @@ -4874,6 +5607,7 @@ function testTask(id: string, prompt: string, finalResponse: string, referenceTa return normalizeTask({ id, queueId: defaultQueueId, + queueEnteredAt: createdAt, prompt, basePrompt: prompt, referenceTaskIds, @@ -4959,6 +5693,15 @@ function runReferenceInjectionSelfTest(): JsonValue { assertReferenceTest(injectedDeep.referenceInjection?.itemCount === 8, "deep reference chain should not truncate at six rounds"); assertReferenceTest(injectedDeep.referenceInjection?.truncated === false, "deep reference chain should be marked complete"); assertReferenceTest(injectedDeep.prompt.includes("----- Reference Round 8/8 -----"), "deep reference chain should expose all eight rounds"); + const retryTask = testTask("codex_3000_retry", injectedDeep.prompt, "", injectedDeep.referenceTaskIds, "2026-05-08T00:31:00.000Z"); + retryTask.basePrompt = injectedDeep.basePrompt ?? ""; + retryTask.referenceInjection = injectedDeep.referenceInjection ?? null; + const retryAfterDeepReference = retryPrompt(retryTask, { decision: "retry", confidence: 1, reason: "Service restarted while task was active", source: "fallback" }); + const recoveryAfterDeepReference = queueRecoveryRetryPrompt(retryTask, "Service restarted while task was active"); + assertReferenceTest(retryAfterDeepReference.length < 2600, "retry prompt should stay compact for referenced tasks"); + assertReferenceTest(recoveryAfterDeepReference.length < 2200, "queue recovery prompt should stay compact for referenced tasks"); + assertReferenceTest(!retryAfterDeepReference.includes("Reference Round"), "retry prompt should not re-inject reference rounds"); + assertReferenceTest(!recoveryAfterDeepReference.includes("Reference Round"), "queue recovery prompt should not re-inject reference rounds"); return { ok: true, cases: [ @@ -4969,11 +5712,55 @@ function runReferenceInjectionSelfTest(): JsonValue { { name: "timestamp_and_round_separators", ok: true }, { name: "environment_hint_injected_and_stripped_from_display", ok: true }, { name: "deep_reference_graph_not_six_round_truncated", ok: true, itemCount: injectedDeep.referenceInjection?.itemCount ?? 0 }, + { name: "retry_prompt_does_not_reinject_reference_graph", ok: true, chars: retryAfterDeepReference.length }, + { name: "queue_recovery_prompt_is_compact", ok: true, chars: recoveryAfterDeepReference.length }, ], promptPreview: safePreview(promptC, 1200), }; } +function queueOrderTestTask(id: string, status: TaskStatus, createdAt: string, queueEnteredAt: string): QueueTask { + const task = testTask(id, `${id} prompt`, status === "succeeded" ? `${id} final` : "", [], createdAt); + task.queueId = "queue_order_test"; + task.queueEnteredAt = queueEnteredAt; + task.status = status; + task.updatedAt = queueEnteredAt; + task.startedAt = status === "running" || status === "judging" ? queueEnteredAt : null; + task.finishedAt = terminalTask(task) ? queueEnteredAt : null; + task.currentAttempt = status === "queued" ? 0 : 1; + task.currentMode = status === "queued" ? null : "retry"; + task.nextMode = status === "retry_wait" ? "retry" : null; + task.nextPrompt = status === "retry_wait" ? "continue" : null; + return normalizeTask(task); +} + +function runQueueOrderingSelfTest(): JsonValue { + const activeRetry = queueOrderTestTask("codex_4000_active", "retry_wait", "2026-05-11T09:00:00.000Z", "2026-05-11T09:00:00.000Z"); + const movedOlderCreated = queueOrderTestTask("codex_3999_moved", "queued", "2026-05-11T08:00:00.000Z", "2026-05-11T08:00:00.000Z") as QueueTask & { queueEnteredAt?: string }; + delete (movedOlderCreated as Partial).queueEnteredAt; + movedOlderCreated.output.push({ seq: 2, at: "2026-05-11T09:30:00.000Z", channel: "system", text: "moved from queue=default to queue=queue_order_test\n", method: "queue/move" }); + normalizeTask(movedOlderCreated as QueueTask); + const blockedByRetry = [movedOlderCreated, activeRetry]; + const runningHead = queueOrderTestTask("codex_4100_running", "running", "2026-05-11T10:00:00.000Z", "2026-05-11T10:00:00.000Z"); + const queuedBehindRunning = queueOrderTestTask("codex_4101_queued", "queued", "2026-05-11T10:01:00.000Z", "2026-05-11T10:01:00.000Z"); + const terminalAhead = queueOrderTestTask("codex_4200_done", "succeeded", "2026-05-11T11:00:00.000Z", "2026-05-11T11:00:00.000Z"); + const queuedAfterTerminal = queueOrderTestTask("codex_4201_queued", "queued", "2026-05-11T11:01:00.000Z", "2026-05-11T11:01:00.000Z"); + + assertReferenceTest(queueHeadTask("queue_order_test", blockedByRetry)?.id === activeRetry.id, "retry_wait head must keep blocking a moved older-created task"); + assertReferenceTest(nextRunnableTaskFrom("queue_order_test", blockedByRetry)?.id === activeRetry.id, "next runnable should be the retry_wait head"); + assertReferenceTest(nextRunnableTaskFrom("queue_order_test", [queuedBehindRunning, runningHead]) === null, "running head must block queued tasks behind it"); + assertReferenceTest(nextRunnableTaskFrom("queue_order_test", [queuedAfterTerminal, terminalAhead])?.id === queuedAfterTerminal.id, "terminal head should not block later queued task"); + + return { + ok: true, + cases: [ + { name: "retry_wait_head_blocks_moved_older_created_task", ok: true, head: activeRetry.id, moved: movedOlderCreated.id }, + { name: "running_head_blocks_later_queued_task", ok: true }, + { name: "terminal_task_does_not_block_queue", ok: true }, + ], + }; +} + async function steerTask(task: QueueTask, req: Request): Promise { const body = await readJson(req); const prompt = typeof (body as Record).prompt === "string" ? String((body as Record).prompt) : ""; @@ -5033,6 +5820,7 @@ async function manualRetry(task: QueueTask, req: Request): Promise { task.nextPrompt = explicitPrompt.length > 0 ? explicitPrompt : retryPrompt(task, { decision: "retry", confidence: 1, reason: "Manual retry", source: "fallback" }); setAttemptFeedbackPrompt(task.attempts.at(-1), task.nextPrompt, explicitPrompt.length > 0 ? "manual-retry-explicit" : "manual-retry-generated", task.attempts.length + 1); task.updatedAt = nowIso(); + task.queueEnteredAt = task.updatedAt; appendOutput(task, "system", explicitPrompt.length > 0 ? "manual retry queued with explicit continuation prompt\n" : "manual retry queued\n", "manual-retry"); armIdleNotification(); persistState(); @@ -5079,6 +5867,7 @@ async function createQueue(req: Request): Promise { const beforeCount = state.queues.length; const queue = ensureQueue(queueId); queue.updatedAt = nowIso(); + markQueueDirty(queue.id); persistState(false); logger("info", "queue_created", { queueId, existed: beforeCount === state.queues.length }); return jsonResponse({ ok: true, queue, queues: perQueueSummaries(), summary: queueSummary(false) }, beforeCount === state.queues.length ? 200 : 201); @@ -5092,9 +5881,13 @@ async function moveTaskToQueue(task: QueueTask, req: Request): Promise const record = typeof body === "object" && body !== null && !Array.isArray(body) ? body as Record : {}; const queueId = normalizeQueueId(record.queueId ?? record.id); const previousQueueId = queueIdOf(task); - ensureQueue(queueId).updatedAt = nowIso(); + const queue = ensureQueue(queueId); + const movedAt = nowIso(); + queue.updatedAt = movedAt; + markQueueDirty(queue.id); task.queueId = queueId; - task.updatedAt = nowIso(); + task.queueEnteredAt = movedAt; + task.updatedAt = movedAt; appendOutput(task, "system", `moved from queue=${previousQueueId} to queue=${queueId}\n`, "queue/move"); if (task.status === "queued" || task.status === "retry_wait") armIdleNotification(); persistState(); @@ -5111,7 +5904,39 @@ async function route(req: Request): Promise { if (url.pathname === "/logs") return jsonResponse({ ok: true, logs: recentLogs.slice(-parseLimit(url)) }); if (url.pathname === "/api/dev-ready" && req.method === "GET") return jsonResponse({ ok: true, devReady: collectDevReady() }); if (url.pathname === "/api/judge/probe" && (req.method === "GET" || req.method === "POST")) return runJudgeProbe(); + if (url.pathname === "/api/queue-order/self-test" && (req.method === "GET" || req.method === "POST")) return jsonResponse(runQueueOrderingSelfTest()); if (url.pathname === "/api/reference-injection/self-test" && (req.method === "GET" || req.method === "POST")) return jsonResponse(runReferenceInjectionSelfTest()); + if (url.pathname === "/api/notifications/claudeqq" && req.method === "GET") { + await loadClaudeQqNotificationOutboxFromDatabase(); + const limit = parseLimit(url); + const items = claudeQqNotificationOutbox.items.slice(-limit).map((item) => ({ + id: item.id, + kind: item.kind, + dedupKey: item.dedupKey, + target: item.target, + createdAt: item.createdAt, + updatedAt: item.updatedAt, + attempts: item.attempts, + nextAttemptAt: item.nextAttemptAt, + lastError: item.lastError, + sentAt: item.sentAt, + messagePreview: safePreview(item.message, 500), + messageChars: item.message.length, + })); + return jsonResponse({ ok: true, stats: claudeQqNotificationOutboxStats(), items }); + } + if (url.pathname === "/api/notifications/claudeqq/drain" && req.method === "POST") { + return jsonResponse(await drainClaudeQqNotificationOutbox("api")); + } + if (url.pathname === "/api/notifications/claudeqq/backfill" && req.method === "POST") { + const body = await readJson(req); + const record = typeof body === "object" && body !== null && !Array.isArray(body) ? body as Record : {}; + const since = typeof record.since === "string" ? record.since : url.searchParams.get("since"); + const dryRun = record.dryRun === true || url.searchParams.get("dryRun") === "1"; + const rawLimit = Number(record.limit ?? url.searchParams.get("limit") ?? 100); + const limit = Number.isInteger(rawLimit) && rawLimit > 0 ? Math.min(500, rawLimit) : 100; + return jsonResponse(await backfillClaudeQqTaskNotifications(since, limit, dryRun)); + } if (url.pathname === "/api/queues" && req.method === "GET") return jsonResponse({ ok: true, queues: perQueueSummaries(), queue: queueSummary(false) }); if (url.pathname === "/api/queues" && req.method === "POST") return createQueue(req); if (url.pathname === "/api/tasks/read-all" && req.method === "POST") return markTerminalTasksRead(url); @@ -5215,7 +6040,7 @@ installShutdownHandlers(); prepareCodexHome(); await initDatabasePersistenceWithRetry(); Bun.serve({ hostname: config.host, port: config.port, idleTimeout: 120, fetch: route }); -logger("info", "service_started", { port: config.port, statePath: config.statePath, workdir: config.defaultWorkdir, defaultModel: config.defaultModel, judgeConfigured: config.minimaxApiKey.length > 0, storage: databaseReady ? "postgres" : "file" }); +logger("info", "service_started", { port: config.port, workdir: config.defaultWorkdir, defaultModel: config.defaultModel, judgeConfigured: config.minimaxApiKey.length > 0, storage: "postgres" }); { const devReady = collectDevReady() as Record; logger(devReady.ok === true ? "info" : "warn", "dev_ready_check", devReady); @@ -5225,3 +6050,4 @@ if (startupRecovered > 0) logger("warn", "startup_requeued_active_tasks", { reco persistState(); serviceReady = true; scheduleQueue(); +scheduleClaudeQqNotificationDrain(1000);