diff --git a/AGENTS.md b/AGENTS.md index c0a8f4e4..162678f2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,6 +23,7 @@ UniDesk 是一个以主 server 为统一入口的分布式工作平台;本文 - `bun scripts/cli.ts ssh [ssh-like args...]`:通过 provider-gateway 的 Host SSH / WSL SSH 维护桥打开近似原生 ssh 的交互会话或远端命令,并在远端 PATH 注入 `apply_patch`、`glob` 与 `skill-discover`;`apply-patch`、`py`、`skills`、结构化 `find`、`glob` 和 `argv` 子命令用于避免远端补丁、Python stdin、skill 发现与常用只读命令的嵌套转义问题,使用规则见 `docs/reference/cli.md` 和 `docs/reference/provider-gateway.md`。 - `bun scripts/cli.ts microservice list/status/health/proxy`:管理和验证挂载在主 server 或计算节点 Docker 中的用户服务,OA Event Flow/Code Queue/Todo Note/Baidu Netdisk on main-server 与 FindJob/Pipeline/MET Nonlinear on D601 的规则见 `docs/reference/microservices.md`。 - `bun scripts/cli.ts codex task `:按 Code Queue 任务 ID 查询初始 prompt、最后 assistant message、工具调用摘要、attempt/judge/error 和耗时,便于新任务引用历史 session。 +- `bun scripts/cli.ts codex judge --attempt [--dry-run]`:按指定 task/attempt 用与队列 worker 相同的上下文构建和 MiniMax judge 调用路径单步复现完成判定;`--dry-run` 只输出 prompt/payload 诊断。 - `bun scripts/cli.ts server stop`:以异步 job 停止固定 Compose 项目中的全部 UniDesk 服务,停止后用 `server status` 复核。 - `bun scripts/cli.ts job list` / `bun scripts/cli.ts job status latest`:查询 `.state/jobs/` 中的异步任务状态,job 机制见 `docs/reference/cli.md`。 - `bun scripts/cli.ts debug health` / `bun scripts/cli.ts debug dispatch` / `bun scripts/cli.ts debug task`:通过 Docker 内网 core、真实 HTTP、WebSocket、系统指标、Docker 状态和 Host SSH 维护桥流程调试健康检查、任务下发与任务结果,调试规则见 `docs/reference/cli.md`。 diff --git a/TEST.md b/TEST.md index 32303cfd..dde998f0 100644 --- a/TEST.md +++ b/TEST.md @@ -99,7 +99,7 @@ ## T23 Main Server Code Queue User Service -阅读 `AGENTS.md`(本项目 `AGENTS.md` 同时承担 `SKILL.md` 对 `scripts/cli.ts` 的解释职责),然后用 cli 手动测试以下内容:运行 `bun scripts/cli.ts microservice list`,确认 `code-queue` 显示为 `providerId=main-server`、`public=false`、`frontendOnly=true`、仓库 URL `https://github.com/pikasTech/unidesk`、`code-queue:4222` 后端映射和 `code-queue-backend` 容器摘要;运行 `bun scripts/cli.ts server rebuild code-queue` 并用 `bun scripts/cli.ts job status ` 等待该 job 成功且输出 post-up validation,再运行 `bun scripts/cli.ts microservice health code-queue`、`bun scripts/cli.ts microservice proxy code-queue /api/dev-ready --raw`、`bun scripts/cli.ts microservice proxy code-queue /api/tasks` 和 `bun scripts/cli.ts codex task <已有taskId>`,确认链路通过 backend-core、main-server provider-gateway 和 Code Queue 后端,且 task id 查询返回初始 prompt、最后 assistant message、工具调用摘要、attempt/judge/error 和耗时,且 `queue.devReady.ok=true`、`devReady.missingTools=[]`、`docker.versionOk=true`、`docker.composeOk=true`,必需工具包含 `docker`、`docker-compose`、`jq`、`ssh`、`rsync`、`pip3` 和 `unzip`;提交会产生较多命令输出的小任务后,`/health` 和 `/api/tasks` 仍必须在常规 CLI 超时内返回,容器内不得堆积无超时 healthcheck 进程。运行 `bun scripts/cli.ts microservice proxy code-queue /api/dev-containers/D601/start --method POST --raw`(或等价同源 POST),确认 Code Queue 拉起 D601 `unidesk-codex-dev-D601` 开发容器,返回 JSON 中 `masterProxy.mode=ssh-tun-nat`、`verification.pingGoogleOk=true`、`directPingEvidence` 表明建隧道前直连失败、`pingGoogleLog` 包含 `PING google.com` 和 `0% packet loss`,且 `masterProxyEvidenceAfter` 中 `UNIDESK-CODEX-DEV-D601` NAT 链或 `tun601` 计数比 ping 前增长,证明开发容器网络经 master server 全局代理而不是 D601 本地出网。再用 `bun scripts/cli.ts microservice proxy code-queue /api/tasks --raw` 确认返回的 `queue.executionProviders` 至少包含 `main-server` 和 `D601`,`main-server` 的 `defaultWorkdir=/root/unidesk`,`D601` 的 `defaultWorkdir=/home/ubuntu`;通过 API 提交任务时 `providerId=main-server` 必须在本机容器执行,`providerId=D601` 必须自动复用/拉起 D601 开发容器并在任务 JSON、Trace summary 和日志中显示 `providerId=D601`、`cwd=/home/ubuntu`。随后登录公网 frontend `http://74.48.78.17:18081/`,进入 `用户服务 / Code Queue`,确认页面显示默认模型 `gpt-5.5`、默认执行 Provider `main-server`、默认工作目录 `/root/unidesk`、Provider 下拉菜单包含 `D601 · /home/ubuntu`、模型下拉菜单包含 `gpt-5.4-mini`/`gpt-5.4`/`gpt-5.5`、入队份数、队列指标、任务 ID、复制任务 ID、引用按钮、任务耗时、引用任务 ID、清空输入、创建成功提示、任务提交表单、Codex CLI-like 输出、attempt 表、MiniMax/fallback judge 状态、追加 prompt、打断和重试控件;通过页面提交一个小任务,确认任务进入 queued/running/succeeded 或可解释的 failed 状态,并且输出区能看到运行中的 Codex 消息。批量验收时设置 `入队份数=5` 或用 `---` 分隔 5 段 prompt,一次性入队 5 条任务,确认 5 条任务按顺序运行并全部进入 succeeded 或可解释的非成功终态,不能只运行第一条后停止;其中任一任务被 judge 判定 `fail` 时只能把当前任务标为 failed,后续 queued 任务仍必须继续推进。测试异常中断时可以提交长任务后点击 `打断`,确认任务变为 canceled 或被 judge 标记为非成功终态;自动重试只应在服务端/传输异常、任务正常结束但 execution record 显示未完成、或 judge 判定 retry 时发生;retry 必须复用已有 Codex thread 并 append 继续执行 prompt,只有当前任务 complete 后才推进队列中的下一个任务。MiniMax judge 必须能处理 Markdown fence/夹杂文本等 JSON 去噪;若去噪后仍失败,必须把解析错误和上一轮去噪前原始回答反馈给 MiniMax 修复后重试,日志中应出现 `judge_json_parse_retry`,且 repair 成功时仍以 `source=minimax` 返回。Codex provider key 只能通过 `OPENAI_API_KEY`、`CRS_OAI_KEY` 这类运行时环境透传,MiniMax API key 只能通过 `UNIDESK_CODE_QUEUE_MINIMAX_API_KEY` 这类运行时环境传入,禁止写入 `config.json`、Dockerfile、源码或测试文档。 +阅读 `AGENTS.md`(本项目 `AGENTS.md` 同时承担 `SKILL.md` 对 `scripts/cli.ts` 的解释职责),然后用 cli 手动测试以下内容:运行 `bun scripts/cli.ts microservice list`,确认 `code-queue` 显示为 `providerId=main-server`、`public=false`、`frontendOnly=true`、仓库 URL `https://github.com/pikasTech/unidesk`、`code-queue:4222` 后端映射和 `code-queue-backend` 容器摘要;运行 `bun scripts/cli.ts server rebuild code-queue` 并用 `bun scripts/cli.ts job status ` 等待该 job 成功且输出 post-up validation,再运行 `bun scripts/cli.ts microservice health code-queue`、`bun scripts/cli.ts microservice proxy code-queue /api/dev-ready --raw`、`bun scripts/cli.ts microservice proxy code-queue /api/tasks` 和 `bun scripts/cli.ts codex task <已有taskId>`,确认链路通过 backend-core、main-server provider-gateway 和 Code Queue 后端,且 task id 查询返回初始 prompt、最后 assistant message、工具调用摘要、attempt/judge/error 和耗时,且 `queue.devReady.ok=true`、`devReady.missingTools=[]`、`docker.versionOk=true`、`docker.composeOk=true`,必需工具包含 `docker`、`docker-compose`、`jq`、`ssh`、`rsync`、`pip3` 和 `unzip`;提交会产生较多命令输出的小任务后,`/health` 和 `/api/tasks` 仍必须在常规 CLI 超时内返回,容器内不得堆积无超时 healthcheck 进程。运行 `bun scripts/cli.ts microservice proxy code-queue /api/dev-containers/D601/start --method POST --raw`(或等价同源 POST),确认 Code Queue 拉起 D601 `unidesk-codex-dev-D601` 开发容器,返回 JSON 中 `masterProxy.mode=ssh-tun-nat`、`verification.pingGoogleOk=true`、`directPingEvidence` 表明建隧道前直连失败、`pingGoogleLog` 包含 `PING google.com` 和 `0% packet loss`,且 `masterProxyEvidenceAfter` 中 `UNIDESK-CODEX-DEV-D601` NAT 链或 `tun601` 计数比 ping 前增长,证明开发容器网络经 master server 全局代理而不是 D601 本地出网。再用 `bun scripts/cli.ts microservice proxy code-queue /api/tasks --raw` 确认返回的 `queue.executionProviders` 至少包含 `main-server` 和 `D601`,`main-server` 的 `defaultWorkdir=/root/unidesk`,`D601` 的 `defaultWorkdir=/home/ubuntu`,并且 `queue.executionModes` 包含 `windows-native`;通过 API 提交任务时 `providerId=main-server` 必须在本机容器执行,`providerId=D601` 必须自动复用/拉起 D601 开发容器并在任务 JSON、Trace summary 和日志中显示 `providerId=D601`、`cwd=/home/ubuntu`;通过 API 或前端提交 `providerId=D601`、`executionMode=windows-native`、`model=gpt-5.4-mini`、`cwd=/mnt/f/Work/ConStart` 的小任务,必须显示 `executionMode=windows-native`,且 Trace 中的 Codex initialize/userAgent 证明 Codex 运行在 Windows 原生环境。随后登录公网 frontend `http://74.48.78.17:18081/`,进入 `用户服务 / Code Queue`,确认页面显示默认模型 `gpt-5.5`、默认执行 Provider `main-server`、默认工作目录 `/root/unidesk`、Provider 下拉菜单包含 `D601 · /home/ubuntu`、模型下拉菜单包含 `gpt-5.4-mini`/`gpt-5.4`/`gpt-5.5`、入队份数、队列指标、任务 ID、复制任务 ID、引用按钮、任务耗时、引用任务 ID、清空输入、创建成功提示、任务提交表单、Codex CLI-like 输出、attempt 表、MiniMax/fallback judge 状态、追加 prompt、打断和重试控件;通过页面提交一个小任务,确认任务进入 queued/running/succeeded 或可解释的 failed 状态,并且输出区能看到运行中的 Codex 消息。批量验收时设置 `入队份数=5` 或用 `---` 分隔 5 段 prompt,一次性入队 5 条任务,确认 5 条任务按顺序运行并全部进入 succeeded 或可解释的非成功终态,不能只运行第一条后停止;其中任一任务被 judge 判定 `fail` 时只能把当前任务标为 failed,后续 queued 任务仍必须继续推进。测试异常中断时可以提交长任务后点击 `打断`,确认任务变为 canceled 或被 judge 标记为非成功终态;自动重试只应在服务端/传输异常、任务正常结束但 execution record 显示未完成、或 judge 判定 retry 时发生;retry 必须复用已有 Codex thread 并 append 继续执行 prompt,只有当前任务 complete 后才推进队列中的下一个任务。MiniMax judge 必须能处理 Markdown fence/夹杂文本等 JSON 去噪;若去噪后仍失败,必须把解析错误和上一轮去噪前原始回答反馈给 MiniMax 修复后重试,日志中应出现 `judge_json_parse_retry`,且 repair 成功时仍以 `source=minimax` 返回。Codex provider key 只能通过 `OPENAI_API_KEY`、`CRS_OAI_KEY` 这类运行时环境透传,MiniMax API key 只能通过 `UNIDESK_CODE_QUEUE_MINIMAX_API_KEY` 这类运行时环境传入,禁止写入 `config.json`、Dockerfile、源码或测试文档。 ## T24 MET Nonlinear D601 GPU User Service diff --git a/docker-compose.yml b/docker-compose.yml index f5fa3c2c..b53f61fa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -113,8 +113,8 @@ services: dockerfile: src/components/microservices/code-queue/Dockerfile container_name: code-queue-backend restart: unless-stopped - mem_limit: 600m - memswap_limit: 1536m + mem_limit: "${UNIDESK_CODE_QUEUE_MEM_LIMIT:-1200m}" + memswap_limit: "${UNIDESK_CODE_QUEUE_MEMSWAP_LIMIT:-1800m}" depends_on: - database - backend-core @@ -138,7 +138,7 @@ services: OA_EVENT_FLOW_BASE_URL: "http://oa-event-flow:4255" CODE_QUEUE_MAX_ATTEMPTS: "99" CODE_QUEUE_MAX_ACTIVE_QUEUES: "${UNIDESK_CODE_QUEUE_MAX_ACTIVE_QUEUES:-0}" - NODE_OPTIONS: "${UNIDESK_CODE_QUEUE_NODE_OPTIONS:---max-old-space-size=768}" + NODE_OPTIONS: "${UNIDESK_CODE_QUEUE_NODE_OPTIONS:---max-old-space-size=512}" CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS: "${UNIDESK_CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS:-10}" CODE_QUEUE_IN_MEMORY_EVENT_RECORDS: "${UNIDESK_CODE_QUEUE_IN_MEMORY_EVENT_RECORDS:-10}" CODE_QUEUE_CODEX_SQLITE_LOG_EXPORT_BATCH_SIZE: "${UNIDESK_CODE_QUEUE_CODEX_SQLITE_LOG_EXPORT_BATCH_SIZE:-500}" @@ -149,6 +149,11 @@ services: CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID: "${UNIDESK_CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID:-D601}" CODE_QUEUE_DEV_CONTAINER_IMAGE: "${UNIDESK_CODE_QUEUE_DEV_CONTAINER_IMAGE:-}" CODE_QUEUE_DEV_CONTAINER_WORKDIR: "${UNIDESK_CODE_QUEUE_DEV_CONTAINER_WORKDIR:-/home/ubuntu}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_DEFAULT_WORKDIR: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_DEFAULT_WORKDIR:-/mnt/f/Work/ConStart}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_BRIDGE_DIR: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_BRIDGE_DIR:-/home/ubuntu/.unidesk/code-queue/windows-native-codex}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_COMMAND: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_COMMAND:-codex app-server --listen stdio://}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_CONNECT_HOST: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_CONNECT_HOST:-host.docker.internal}" + CODE_QUEUE_WINDOWS_NATIVE_CODEX_IDLE_TIMEOUT_MS: "${UNIDESK_CODE_QUEUE_WINDOWS_NATIVE_CODEX_IDLE_TIMEOUT_MS:-600000}" CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED:-true}" CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL:-http://backend-core:8080/api/microservices/claudeqq/proxy}" CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE: "${UNIDESK_CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE:-private}" @@ -162,7 +167,7 @@ services: MINIMAX_API_KEY: "${UNIDESK_CODE_QUEUE_MINIMAX_API_KEY:-}" MINIMAX_API_BASE: "${UNIDESK_CODE_QUEUE_MINIMAX_API_BASE:-https://api.minimaxi.com/v1}" MINIMAX_MODEL: "${UNIDESK_CODE_QUEUE_MINIMAX_MODEL:-MiniMax-M2.7}" - MINIMAX_JUDGE_TIMEOUT_MS: "${UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_TIMEOUT_MS:-60000}" + MINIMAX_JUDGE_TIMEOUT_MS: "${UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_TIMEOUT_MS:-90000}" MINIMAX_JUDGE_REPAIR_ATTEMPTS: "${UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_REPAIR_ATTEMPTS:-2}" LOG_FILE: "/var/log/unidesk/${UNIDESK_LOG_DAY}/${UNIDESK_LOG_PREFIX}_code-queue.jsonl" UNIDESK_LOG_RETENTION_BYTES: "${UNIDESK_LOG_RETENTION_BYTES:-1GiB}" diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 6e66f339..cc3869d1 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -22,6 +22,7 @@ UniDesk 的统一 CLI 入口是根目录 `scripts/cli.ts`,运行方式固定 - `codex task ` 通过 Code Queue 私有代理按任务 ID 查询结构化执行摘要;默认只返回有界 prompt/response 预览、执行 Provider、工作目录、最后 assistant message、最近工具调用摘要、attempt、judge、错误、耗时和 trace 翻页提示,适合在新队列任务中引用历史 session 且避免噪声爆炸。 - `codex task --trace --tail|--from-start|--after-seq N|--before-seq N --limit N` 按页拉取 Code Queue 的逻辑 trace;响应会返回 `nextAfterSeq`、`previousBeforeSeq`、`hasMore`、`hasBefore` 和下一页/上一页命令,默认 `--trace` 取最新一页,需要完整 prompt/最后 response 时加 `--full`。 - `codex output --tail|--from-start|--after-seq N|--before-seq N --limit N [--full-text]` 按原始 output seq 分页读取底层记录;当 trace 行提示 `commandOmittedLines`、`bodyOmittedLines` 或 `rawSeqs` 时,用该命令按 seq 补取完整信息,默认仍有单条文本预览上限,显式 `--full-text` 才返回该页全文。 +- `codex judge --attempt N [--dry-run] [--include-prompt]` 通过 Code Queue 私有代理按指定 attempt 单步复现 judge;后端会从 PostgreSQL task JSON 与 output 归档重建该 attempt 在真实队列 worker 中的 `QueueTask`/`CodexRunResult`,再调用同一套 judge prompt builder 和 MiniMax 请求路径。默认会真实调用 MiniMax,`--dry-run` 只返回 prompt/payload 大小、attempt 窗口和重建来源诊断,`--include-prompt` 仅用于本地深度排查。 - Code Queue 多队列 lane 由 `codex` 命令命名空间管理:`queues` 列表、`queue create ` 创建、`queue merge --into ` 合并、`move --queue ` 迁移;同一个 queue 内部串行执行,不同 queue 之间并行执行。合并会移动任务归属并自动删除源 queue 记录,只保留合并后的目标 queue;合并后的目标 queue 按任务原 `queueEnteredAt`/`createdAt` 时间顺序串行。迁移 queued/retry_wait 任务后会立即调度目标 queue。 - `job list` 与 `job status` 查询 `.state/jobs/` 文件系统状态,是异步命令的可观测入口。 - `debug health`、`debug dispatch` 与 `debug task` 走真实内部 core、WebSocket、数据库、provider、系统指标、Docker 状态和 Host SSH 维护桥流程,只用于开发调试,不写入 `TEST.md` 的正式验收步骤。 @@ -105,7 +106,7 @@ bun scripts/cli.ts ssh D601 glob --root /home/ubuntu/pikapython --pattern '**/*- `--main-server-ip` 是一个全局前缀,必须放在需要透传的命令同一次调用中,例如 `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug health`。默认传输是公网 frontend:本地 CLI 读取本仓库 `config.json` 中的 frontend 登录账号密码,登录 `http://:/` 获取 HttpOnly session cookie,然后通过 frontend 的 `/api/*` 同源代理访问 backend-core 内网 API;因此计算节点只需要能访问公网 frontend,不需要主 server SSH key,也不需要打开 backend-core REST API 或 PostgreSQL 端口。 -默认 frontend 传输支持 `debug health`、`debug dispatch`、`debug task`、`microservice list/status/health/proxy`、`codex task ` 和 `ssh `。其中 `ssh` 的 remote frontend 传输使用 `host.ssh` dispatch 执行有界远端命令,适合 `ssh D601 hostname` 和 `ssh D601 skills` 这类自测;交互式登录 shell 仍应在主 server 本机 CLI 使用,或显式切换到旧 SSH 传输后在主 server 上执行。frontend 远程透传不会流式转发本地 stdin,因此 `ssh py < script.py`、`ssh apply-patch < patch.diff` 这类 stdin-backed helper 必须在主 server 本机运行,或显式切换到 `--main-server-transport ssh`。若确实需要旧行为,可使用 `--main-server-key ` 或 `--main-server-transport ssh`,这时 CLI 会通过 SSH 登录主 server 的 `--main-server-root` 目录执行同一个 `bun scripts/cli.ts `。 +默认 frontend 传输支持 `debug health`、`debug dispatch`、`debug task`、`microservice list/status/health/proxy`、`codex task `、`codex output `、`codex judge --attempt N` 和 `ssh `。其中 `ssh` 的 remote frontend 传输使用 `host.ssh` dispatch 执行有界远端命令,适合 `ssh D601 hostname` 和 `ssh D601 skills` 这类自测;交互式登录 shell 仍应在主 server 本机 CLI 使用,或显式切换到旧 SSH 传输后在主 server 上执行。frontend 远程透传不会流式转发本地 stdin,因此 `ssh py < script.py`、`ssh apply-patch < patch.diff` 这类 stdin-backed helper 必须在主 server 本机运行,或显式切换到 `--main-server-transport ssh`。若确实需要旧行为,可使用 `--main-server-key ` 或 `--main-server-transport ssh`,这时 CLI 会通过 SSH 登录主 server 的 `--main-server-root` 目录执行同一个 `bun scripts/cli.ts `。 计算节点可以用该入口测试自身的远程升级闭环,而不需要在计算节点公开 core REST API 或 database。标准顺序是:先运行 `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug health` 确认主 server 看到当前 Provider 在线,且该 Provider labels 中 `unideskCapabilities` 包含 `host.ssh`、`hostSshConfigured=true`、`hostSshKeyPresent=true`;再运行 `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch provider.upgrade --mode schedule --wait-ms 15000` 触发真实 `provider.upgrade`;随后再次运行 `debug health` 确认节点重新上线;最后运行 `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch host.ssh --wait-ms 15000` 和 `bun scripts/cli.ts --main-server-ip 74.48.78.17 ssh hostname` 验证 SSH 透传能力。provider-gateway 新部署或升级后没有完成这组 remote CLI 自测,不能视为交付完成。 diff --git a/docs/reference/frontend.md b/docs/reference/frontend.md index a3bf175d..e0625974 100644 --- a/docs/reference/frontend.md +++ b/docs/reference/frontend.md @@ -95,7 +95,7 @@ frontend shell 必须把左侧主模块与顶部子标签编译为统一的 URL - `ClaudeQQ` 子标签必须把 D601 ClaudeQQ 后端渲染为 UniDesk React 控件,包括 NapCat 容器登录二维码、NapCat HTTP/WS 状态、事件缓存、QQ 事件订阅表、订阅创建表单、消息推送表单、主用户私聊账号 `645275593` 标记、最近 QQ 事件、已发送记录和显式原始 JSON 按钮。 - `Baidu Netdisk` 子标签必须把主 server `baidu-netdisk-backend` 后端渲染为 UniDesk React 控件,包括 OAuth 设备码二维码/用户码登录、账号容量、配置工作根文件浏览(当前默认百度网盘根目录 `/`)、staging 目录上传/下载任务、上传/下载自测按钮与 MD5 结果、脱敏安全说明、日志摘要和显式原始 JSON 按钮;不得把 access token、refresh token、dlink 或 staging 文件字节流裸露到浏览器。 - `OA Event Flow` 子标签必须把主 server `oa-event-flow-backend` 后端渲染为 UniDesk React 控件,包括服务健康、事件表、tag 过滤、SSE live 状态、Trace/STEP stats 表、Code Queue/Pipeline 标签入口和显式原始 JSON 按钮;默认页面不得裸铺完整事件 JSON,事件表只展示结构化摘要,完整 envelope/payload 只能通过 `查看原始JSON` 打开。 - - `Code Queue` 子标签必须把主 server `code-queue-backend` 后端渲染为 UniDesk React 控件,包括多 queue lane、queue 内串行、queue 间并行、queue 合并(点击“合并 queue”后必须用公共 `UniDeskDialog` 打开独立小窗口,用下拉菜单选择源 queue;不得把源 queue 选择控件塞进正常提交任务的 Queue 选择区;合并后自动删除源 queue,只保留合并后的目标 queue,目标 queue 按原 queueEnteredAt/createdAt 时间顺序串行)、任务 ID/复制任务 ID、引用按钮、任务耗时、任务提交/批量提交、引用任务 ID、创建成功提示、清空输入、模型下拉、显式入队份数、默认模型 `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;Code Queue 与 Pipeline/OpenCode messages 必须共用 `src/components/frontend/src/trace.tsx` 的 Trace 公共组件、统一 Trace item 接口和 codex/opencode port 适配层;连续 read/edit/run 工具调用只是在 Trace 内折叠为可展开工具调用组,汇总格式至少包含 `xx read, xx edit, xx run`,并展示读取文件、编辑文件、运行命令和耗时摘要;最近 3 个工具调用保持展开,工具调用内容不得自动换行且必须在工具调用块内部横向滚动,工具调用组展开后不得再增加额外左侧缩进;message 与 prompt 必须自动换行,普通 message 不显示左侧项目符号缩进且永不折叠;Trace 首屏可以是摘要预览,但终态任务被选中后必须自动在后台加载完整 Trace,手动“加载完整 Trace”也必须从 Code Queue output archive 分页补齐早期 trace,不得把 preview 的 `hasMore=false` 当成完整历史;即使热状态为控制体积裁剪了早期 raw output,也要从结构化 `basePrompt/displayPrompt/promptHistory` 和 archive 合成完整用户输入与 agent trace,并且初始 prompt 默认显示注入前 prompt 而不是引用注入全文;当初始 prompt 含引用注入时,引用内容必须默认折叠,并只在 Trace 的初始消息中提供可展开的“最终传入 Codex 的真实完整 prompt”,不得再渲染独立 Prompt 全量卡片;多轮引用注入必须按上游/最早上下文在前、直接引用在后的顺序排列,每一轮必须有明确 `Reference Round N/M` 分割线和时间范围,不能用固定 6 轮截断引用链;点击队列引用按钮必须自动把该任务 ID 写入提交表单的引用输入框,引用任务 ID 创建新任务时必须自动注入 `bun scripts/cli.ts codex task ` 的提示;连续执行同一 prompt 应通过入队份数一次性生成多条任务,避免快速连点造成操作员误判。 + - `Code Queue` 子标签必须把主 server `code-queue-backend` 后端渲染为 UniDesk React 控件,包括多 queue lane、queue 内串行、queue 间并行、queue 合并(点击“合并 queue”后必须用公共 `UniDeskDialog` 打开独立小窗口,用下拉菜单选择源 queue;不得把源 queue 选择控件塞进正常提交任务的 Queue 选择区;合并后自动删除源 queue,只保留合并后的目标 queue,目标 queue 按原 queueEnteredAt/createdAt 时间顺序串行)、任务 ID/复制任务 ID、引用按钮、任务耗时、任务提交/批量提交、引用任务 ID、创建成功提示、清空输入、模型下拉、执行 Provider 下拉、执行模式下拉(默认容器/本机或 `windows-native`)、显式入队份数、默认模型 `gpt-5.5`、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、运行中追加 prompt、打断、手动重试和显式原始 JSON 按钮;`windows-native` 模式必须在任务 JSON、卡片和 Trace 头部显示,并要求非主 server WSL Provider 与 `/mnt/` 工作目录;Codex CLI-like 输出流必须始终保留任务的初始 `Submitted prompt` 和运行中 `Steer prompt`;整个 agent loop 消息流统一命名为专有名词 `Trace`,`Trace` 包含 assistant message、user prompt、system event 和 tool call,但非错误 system event 默认只保留在原始输出/数据库中,不在 TraceView 展示;Code Queue 与 Pipeline/OpenCode messages 必须共用 `src/components/frontend/src/trace.tsx` 的 Trace 公共组件、统一 Trace item 接口和 codex/opencode port 适配层;连续 read/edit/run 工具调用只是在 Trace 内折叠为可展开工具调用组,汇总格式至少包含 `xx read, xx edit, xx run`,并展示读取文件、编辑文件、运行命令和耗时摘要;最近 3 个工具调用保持展开,工具调用内容不得自动换行且必须在工具调用块内部横向滚动,工具调用组展开后不得再增加额外左侧缩进;message 与 prompt 必须自动换行,普通 message 不显示左侧项目符号缩进且永不折叠;Trace 首屏可以是摘要预览,但终态任务被选中后必须自动在后台加载完整 Trace,手动“加载完整 Trace”也必须从 Code Queue output archive 分页补齐早期 trace,不得把 preview 的 `hasMore=false` 当成完整历史;即使热状态为控制体积裁剪了早期 raw output,也要从结构化 `basePrompt/displayPrompt/promptHistory` 和 archive 合成完整用户输入与 agent trace,并且初始 prompt 默认显示注入前 prompt 而不是引用注入全文;当初始 prompt 含引用注入时,引用内容必须默认折叠,并只在 Trace 的初始消息中提供可展开的“最终传入 Codex 的真实完整 prompt”,不得再渲染独立 Prompt 全量卡片;多轮引用注入必须按上游/最早上下文在前、直接引用在后的顺序排列,每一轮必须有明确 `Reference Round N/M` 分割线和时间范围,不能用固定 6 轮截断引用链;点击队列引用按钮必须自动把该任务 ID 写入提交表单的引用输入框,引用任务 ID 创建新任务时必须自动注入 `bun scripts/cli.ts codex task ` 的提示;连续执行同一 prompt 应通过入队份数一次性生成多条任务,避免快速连点造成操作员误判。 - `Code Queue` 前端改进必须在同一任务内重建并上线公网 frontend,不能只修改源码或本地 bundle;重建 frontend 是无状态 WebUI 替换,不会导致 Code Queue 长期任务失败。已结束未读任务只能在 task card 边角显示类似未读消息的 `codex-unread-badge` 圆点和“标为已读”操作,不得把整张卡片改成红色/琥珀色失败态边框、背景或胶囊标签;状态栏的“结束未读”提示也不得使用失败态红色。 - `Code Queue` 前端必须把 PostgreSQL-backed backend API 作为 task、queue、readAt/未读状态和 attempt 状态的唯一数据来源;不得用 `localStorage`、`sessionStorage` 或 IndexedDB 持久化这些业务状态,也不得在后端标记已读失败时伪造本地成功。前端允许保留 React 内存态、请求 in-flight guard 和本轮页面缓存,但刷新页面或切换设备后的状态必须完全由后端 PostgreSQL 数据恢复。 - `Code Queue` 前后端通信必须采用渐进式披露:首屏只请求 queue/task 轻量摘要、必要的 selected preview 和小体积统计,不得默认拉取完整 transcript、raw output、原始 JSON 或全部历史任务;加载下一页或搜索分页时必须显式传递 `selected=0`、`includeActive=0`、`stats=0` 等价开关,避免每一页重复请求 selected/active/stats;点击/选中 task 后再按需加载 summary、prompt part、trace step、raw output 或完整 Trace。`read`/`mark all read` 应调用专用 mutation 并用后端返回的 patch 更新当前内存态,不能为了隐藏未读圆点而强制刷新完整 overview;请求仍需遵守 PostgreSQL 权威源,失败时不得本地伪造已读。Code Queue 性能问题应优先通过缩小 API 响应、分页/cursor、去重 in-flight 请求、短 TTL 且 mutation 失效的页面缓存和后端 SQL 聚合解决,避免以重写渲染层或把大 JSON 藏在 DOM/React state 中规避慢请求。 diff --git a/docs/reference/microservices.md b/docs/reference/microservices.md index f1fd38e6..8ff01326 100644 --- a/docs/reference/microservices.md +++ b/docs/reference/microservices.md @@ -138,22 +138,22 @@ Baidu Netdisk 在 UniDesk 语境中按纯后端服务管理:不得暴露百度 - OpenCode 远程执行:`minimax-m2.7` 走 OpenCode JSON event port 时,本地和远程命令都必须显式执行 `opencode run ...`;远程 Docker exec 不得退化成 `exec run ...`,否则会在目标容器内变成 `bash: exec: run: not found`。OpenCode JSON stream 的终态判定以“当前进程退出码 + 当前 attempt 的最终 assistant response”为准:`exit=0` 且当前 attempt 产生非空最终回复时,即使上游没有发 `step_finish` 事件,也应视为正常 terminal;非零退出、无当前最终回复或传输关闭才进入 retry。每个 attempt 的 `finalResponse` 必须只来自当前 OpenCode/Codex turn,禁止在当前 turn 未产出最终回复时回退复用 task 上一次 `finalResponse`,否则会把旧任务内容误判为本轮完成。 - Codex 控制:服务内部启动 `codex app-server --listen stdio://`,用 JSON-RPC 调用 `thread/start`、`turn/start`、`turn/steer` 和 `turn/interrupt`,并监听 `turn/completed`、assistant delta、reasoning delta、command output delta、file diff delta 等通知生成前端可轮询的 transcript。 - 用户输入持久化:任务初始 prompt 以 `basePrompt/displayPrompt` 作为结构化来源,运行中追加的 `turn/steer` prompt 必须写入 `promptHistory`;transcript 构建时从这些结构化字段合成 `Submitted prompt` 和 `Steer prompt`,不能只依赖有 600 条上限的 raw output,否则长任务输出增长后会丢失关键人工指令。 -- 队列语义:`POST /api/tasks` 或 `/api/tasks/batch` 入队,服务始终只运行一个 Codex turn;当前任务真正终止后才推进下一个任务。`GET /api/tasks` 与 `GET /api/tasks/{id}` 返回队列、attempt、judge 和输出;`GET /api/tasks/{id}/summary` 返回按任务 ID 查询的结构化摘要,包括初始 prompt、最后 assistant message、工具调用摘要、attempt、judge、错误和耗时;CLI 入口是 `bun scripts/cli.ts codex task `。`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 必须自动重新调度。 +- 队列语义:`POST /api/tasks` 或 `/api/tasks/batch` 入队,服务始终只运行一个 Codex turn;当前任务真正终止后才推进下一个任务。`GET /api/tasks` 与 `GET /api/tasks/{id}` 返回队列、attempt、judge 和输出;`GET /api/tasks/{id}/summary` 返回按任务 ID 查询的结构化摘要,包括初始 prompt、最后 assistant message、工具调用摘要、attempt、judge、错误和耗时;CLI 入口是 `bun scripts/cli.ts codex task `。`GET|POST /api/tasks/{id}/judge?attempt=N` 与 CLI `bun scripts/cli.ts codex judge --attempt N` 用于单步复现指定 attempt 的 judge,必须复用真实队列 worker 的上下文构建、prompt 压缩、MiniMax 调用、JSON 去噪/repair 和 fallback 路径;`dryRun=1`/`--dry-run` 只输出 prompt/payload 和重建诊断,不调用 MiniMax。`POST /api/tasks/{id}/steer` 向运行中 turn 推入 prompt;`POST /api/tasks/{id}/interrupt` 或 `DELETE /api/tasks/{id}` 打断/取消;`POST /api/tasks/{id}/retry` 手动重试。队列 worker 必须隔离单个 task 的异常,不能因为某个 app-server、judge 异常或 judge 判定 `fail` 让后续 queued 任务停止;`fail` 只把当前任务标为 failed,随后必须继续扫描并推进下一个 queued/retry_wait 任务。当存在 queued/retry_wait 且 worker 空闲时,watchdog 必须自动重新调度。 - 稳定性与重启恢复:Code Queue 的第一目标是长期稳定可用;部署修复或运维排障时不得因为担心容器重启会打断任务而拒绝重启、重建或替换 `code-queue-backend`。容器重启、服务进程重启和镜像替换后,队列、`promptHistory`、running/judging/retry_wait 任务和 active session 元数据必须从 PostgreSQL 恢复,并在已有 `codexThreadId` 可用时用 `thread/resume` 和 continuation prompt 无缝继续当前任务;如果原 app-server turn 已丢失,也必须把当前任务恢复到可 retry/continue 的状态,不能错误推进下一个任务或永久卡住。主 server 侧重建必须走 `server rebuild code-queue`,该 job 受 `.state/locks/server-compose.lock` 串行化约束,并且必须在 build 后执行 no-deps force-recreate 与 post-up health validation;禁止在 job 中先手工 `docker rm` 再依赖后续命令补救,因为中断窗口会让容器消失并触发 frontend `direct microservice proxy failed`。重启后出现 active task 丢失、手动 steer/interrupt 记录丢失、running 任务卡死、误判完成、跳过当前任务、容器消失或阻塞队列,均属于 Code Queue 的 P0 核心缺陷,必须先修复并补充 restart-recovery 验收,不能把“避免重启”作为交付策略。 - 调度与 active run slot:Code Queue 必须把“queue processor 正在等待/退避/轮询”和“实际占用 Codex/OpenCode 子进程运行槽”分开建模;`CODE_QUEUE_MAX_ACTIVE_QUEUES` 只限制真实 active run slot,不能把 retry backoff、等待内存下降或等待前序任务的 `processingQueues` 计入 active slot,否则设置全局 active slot 上限时,一个空等队列会把其他 runnable queue 永久饿死。多个 queue 同时等待 active slot 时必须显式维护 FIFO waiter 队列,避免某个长 retry/backoff 队列刚释放 slot 就立刻重抢,导致更早进入等待的 `retry_wait` 任务长期饥饿;`/health` 必须同时暴露真实 `activeQueueIds`、`activeRunSlotCount`、等待中的 `processingQueueIds` 和 active slot waiters,排障时以 active run slot 与 waiter 顺序判断是否真的有任务在跑、谁应下一个启动。restart-recovery 后的 `retry_wait` 任务若缺失 `codexThreadId`/OpenCode session id,不得无限拒绝 retry;必须用紧凑 recovery prompt 和原始任务摘要重新开一个 agent thread/session,让任务继续推进并在 Trace 中留下 recovery 证据。任何修改 scheduler、retry backoff、queue move、manual retry、shutdown recovery 或内存等待逻辑时,都必须保留“空等 processor 不占 active run slot”、“等待者 FIFO 不饥饿”和“缺失 thread/session 可恢复”的自测或 live 验证。 - 内存优化过程与防回归:主 server 内存预算很小,Code Queue 的内存治理必须按“PostgreSQL 权威源优先、进程热状态最小化、容器硬上限兜底”的顺序设计。长期可复用的优化路径是:先确认任务、queue、readAt、promptHistory、active session 和通知 outbox 均可从 PostgreSQL 恢复;再把历史任务列表、详情、统计、Trace/output 和 `/health` 的只读查询改为 PostgreSQL 直读或聚合查询;随后只把 `queued`、`running`、`judging`、`retry_wait` 等调度必需任务载入 Bun 堆,并在 PostgreSQL 查询侧裁剪 hot `output`/`events`;最后用 dirty-only flush、append-only 输出归档、Codex SQLite 小批量导出、`bun --smol`、`mem_limit=600m`、`memswap_limit=1536m`、`NODE_OPTIONS=--max-old-space-size=768` 和 cgroup memory watchdog 作为运行时防线。PostgreSQL 到进程的单次读取足够快,不能为了减少 SQL 查询把全部历史 `task_json`、Trace、output 或统计摘要常驻内存;任何新增缓存都必须有默认较小的环境变量上限、明确淘汰策略、可从 PostgreSQL 或 append-only 归档重建,且不得影响重启恢复。新增或修改 `/api/tasks`、overview、stats、summary、transcript、output、trace、health、flush、scheduler 和通知路径时,禁止在常规请求中调用会物化全量历史任务 JSON 的代码,禁止启动后无条件重写全量历史 task JSON,禁止用未设上限的 `Map`/数组保存历史 output/event/Trace,`CODE_QUEUE_MAX_ACTIVE_QUEUES=0` 表示不按 queue 数量设置全局排队上限;如显式设置为正数,必须同时说明内存预算并补充内存压测验收。memory watchdog 必须以 cgroup working set 为主要判断,且在 swap 仍有余量时不得提前杀掉唯一 active run;否则 TypeScript/Playwright 这类短时高内存验证会被错误中断并让 retry 队列反复震荡。 - 列表/详情延迟优化原则:Code Queue 控制面交互的长期目标是常规历史规模下首屏、`GET /api/tasks/overview`、`POST /api/tasks//read` 和分页加载均在 1s 内完成;性能面板出现十几秒级 `code_queue_direct_proxy` 或 `core_proxy` 慢操作时,必须优先按后端查询形态和前后端通信策略定位,不能把问题归因于 React 渲染后只改 UI。后端优化顺序是:先为 queue、status、updated/created 时间、readAt/terminal unread 和常用筛选条件补齐 PostgreSQL 索引;再用 SQL `COUNT`、`GROUP BY`、条件聚合和分页 ID 查询生成 queue/status/stats/unread 摘要;随后按 ID 轻量加载当前页、selected、active 和 unread priority task,禁止为了列表或已读操作解析完整 Trace、output archive、Codex transcript 或物化全量历史 `task_json`。`read`/`read-all` 这类 mutation 必须是 SQL-only 更新并返回最小 patch/queue 计数,不能触发 overview 全量重算或重载所有任务;启动 warm 只能预热小体积聚合和索引路径,不得把历史任务作为常驻缓存。允许 frontend/backend 代理使用秒级、严格有界、mutation 自动失效的 overview micro-cache 来吸收重复刷新,但 cache 只能作为抖动保护,不能替代数据库索引、聚合查询和分页披露,也不能让 stale readAt/queue/status 状态跨设备可见。 - Trace/实时输出热路径防回归:Code Queue 的 `appendOutput`、output archive append、`publishTaskEvent`、SSE `/api/events`、任务列表、overview、task meta 和 `/health` 都属于热路径,必须保持 O(1) 或明确小常数上界;这些路径不得同步调用完整 transcript 构建器、`taskFullOutput`、output archive 全量读取、Codex session/log 文件解析、完整 `task_json` 物化或任何会随历史输出长度增长的统计。输出追加时必须增量维护轻量持久化指标,至少包括 `stepCount`、`llmStepCount`、`outputMaxSeq` 或等价字段;列表、overview、meta、SSE 事件和 `/health` 只能读取这些指标或小体积 SQL 聚合。完整 Trace、`trace-summary`、`trace-steps`、`trace-step`、transcript/output 详情允许在显式详情请求中解析归档,但必须分页或有界、使用短 TTL 或容量受限缓存,并在 archive append 后失效。若 frontend 性能面板出现 Code Queue direct proxy 502、`/api/tasks/overview`/trace 接口成批超时,或容器内 `/health` 在 active output 持续追加时也卡住,优先按 Bun event-loop starvation/backpressure 排查,而不是先改 React 渲染;修复必须证明热路径不再随 output/archive 历史线性增长。 -- 完成判定:app-server `turn/completed` 的 `turn.status=completed|interrupted|failed` 只代表 Codex turn 已结束;即使 `completed` 也必须把原始任务、当前 attempt 的 assistant 最终回复、command/file-change 事件、stderr tail 和 current attempt events 组成 execution record 交给 judge 判断是否真的完成。MiniMax judge 之前和之后都必须保留少量协议级硬门禁:明确用户 interrupt 判为 fail;当前 attempt `terminalStatus=failed|null`、传输在终态前关闭、或当前 attempt 最终回复为空时判为 retry;这些门禁只保护“本轮 turn 是否可被验收”的事实,不得发明业务实现要求。协议门禁通过后,配置了 `UNIDESK_CODE_QUEUE_MINIMAX_API_KEY` 且 MiniMax 可用时,MiniMax `MiniMax-M2.7` 对业务是否 `complete|retry|fail` 的判定是权威结果;当且仅当 MiniMax LLM 调用失效(未配置、额度/限流/网络/超时不可用、JSON 去噪与 repair 全部耗尽、或返回超预算反馈且修复耗尽)时,才允许启用非 LLM/fallback 判断。MiniMax 返回必须先做 JSON 去噪,支持去除 Markdown fence、`json` 标签和从夹杂文本中提取平衡 JSON object;如果去噪后仍无法解析,服务必须把解析错误和上一轮去噪前原始回答反馈给 MiniMax 做 JSON repair 重试,重试次数由 `UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_REPAIR_ATTEMPTS` 控制,默认 `2`,耗尽后才进入 fallback,并在 fallback 原因中保留 MiniMax 失败信息。 +- 完成判定:app-server `turn/completed` 的 `turn.status=completed|interrupted|failed` 只代表 Codex turn 已结束;即使 `completed` 也必须把原始任务、当前 attempt 的 assistant 最终回复、command/file-change 事件、stderr tail 和 current attempt events 组成 execution record 交给 judge 判断是否真的完成。MiniMax judge 输入必须做有界压缩,保留终态、最终回复、关键错误/命令/部署证据和摘要计数,避免长 transcript 让 MiniMax 请求超时;默认 `UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_TIMEOUT_MS=90000`。MiniMax judge 之前和之后都必须保留少量协议级硬门禁:明确用户 interrupt 判为 fail;当前 attempt `terminalStatus=failed|null`、传输在终态前关闭、或当前 attempt 最终回复为空时判为 retry;这些门禁只保护“本轮 turn 是否可被验收”的事实,不得发明业务实现要求。协议门禁通过后,配置了 `UNIDESK_CODE_QUEUE_MINIMAX_API_KEY` 且 MiniMax 可用时,MiniMax `MiniMax-M2.7` 对业务是否 `complete|retry|fail` 的判定是权威结果;当且仅当 MiniMax LLM 调用失效(未配置、额度/限流/网络/超时不可用、JSON 去噪与 repair 全部耗尽、或返回超预算反馈且修复耗尽)时,才允许启用非 LLM/fallback 判断。MiniMax 返回必须先做 JSON 去噪,支持去除 Markdown fence、`json` 标签和从夹杂文本中提取平衡 JSON object;如果去噪后仍无法解析,服务必须把解析错误和上一轮去噪前原始回答反馈给 MiniMax 做 JSON repair 重试,重试次数由 `UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_REPAIR_ATTEMPTS` 控制,默认 `2`,耗尽后才进入 fallback,并在 fallback 原因、task JSON、attempt summary 和 TraceView 中保留 MiniMax 失败阶段、是否超时、耗时、prompt/payload 大小、HTTP 状态、错误名和响应预览。 - Judge 权威边界:MiniMax 成功返回可解析、预算内的 judge JSON 后,Code Queue 不得用旧 attempt 的 429/exceeded retry limit 证据、历史 output 字符串、面向特定任务的正则或 `hardCompletionBlockers`/`retryRequiredReasons` 覆盖一次协议有效的完成判定;尤其不能因为 attempt 1 的限流中断仍在历史输出里,就禁止 MiniMax 把 attempt 2 的正常完成判为 `complete`。允许的本地 safety override 必须限定为协议事实和系统交付纪律:用户显式打断、当前 attempt 未正常终止、当前 attempt 没有最终 assistant response、最终回复停在并发文件确认而非交付、或 runtime/UI/service 变更承认未部署验证。所有 override 都必须写入 `_safetyOverride`、生成紧凑 continuation prompt,并由自测或 judge probe 覆盖;不得把业务猜测伪装成本地硬门禁。 - Retry/推进语义:`retry` 不是新开一个独立任务或完全新 session;只要已有 `codexThreadId`,服务必须 `thread/resume` 原 thread 并 append 一个继续执行 prompt。continuation/judge feedback prompt 只应携带本轮缺口、恢复原因、验收要求和有界原始任务摘要,禁止重新注入完整引用上下文、历史 transcript 或长 JSON;服务重启恢复类 feedback 尤其必须保持短 prompt,依赖现有 thread 上文继续。超长 prompt 必须在 prompt 合成源头解决:每个 feedback/recovery/judge 生成器都要从结构化字段选择必要信息、去重合并缺口并提供按需查询入口,禁止先合成超长 prompt 再在末端用 substring/safePreview 一刀切硬截断;硬截断会静默丢失验收信息,风险高于长 prompt 本身。若 MiniMax `continuePrompt` 超出预算,必须要求 MiniMax 基于原始 judge 输入重新合成紧凑反馈,repair 耗尽后才可进入 fallback;不得把已生成的长 prompt 截尾后发送给 Codex。若 MiniMax 成功返回了预算内 `continuePrompt`,必须原样使用该反馈,不得再用 71-Freq、`period_sum/mpu_read_num`、`mpu_read_num`、历史限流中断等字符串识别把它覆盖成“简洁原始需求 continuation”。只有 judge 判定 `complete` 后,队列 worker 才把当前任务标为成功并推进下一个 queued/retry_wait 任务。非 LLM/fallback 判定产生的 `retry` 最多累计 `3` 次;达到上限后当前任务必须转为 `failed` 并记录原因,worker 继续推进后续 queued/retry_wait 任务,避免 fallback safety override 或硬编码判断造成无限循环。 -- Judge 探针:`GET|POST /api/judge/probe` 使用同一套 judge 逻辑跑内置 synthetic execution records,覆盖正常完成、正常结束但只给计划、未上线/未部署的服务或 WebUI 改动、传输中断和用户打断等样本,返回 `hits`、`total`、`hitRate`、每例 `expected` 与 `decision`;该接口不得回显 MiniMax API key。 +- Judge 探针与复现:`GET|POST /api/judge/probe` 使用同一套 judge 逻辑跑内置 synthetic execution records,覆盖正常完成、正常结束但只给计划、未上线/未部署的服务或 WebUI 改动、传输中断和用户打断等样本,返回 `hits`、`total`、`hitRate`、每例 `expected` 与 `decision`;该接口不得回显 MiniMax API key。真实任务排障必须优先使用 `codex judge --attempt N` 或 `/api/tasks/{id}/judge?attempt=N`,响应要包含 attempt 窗口、promptChars/payloadBytes、stored judge 对比、MiniMax 失败阶段和是否因历史 per-attempt events 缺失而降级为 retained events 重建。 - 模型选择:默认 Codex 模型是 `gpt-5.5`,内置模型队列包含 `gpt-5.5`、`gpt-5.4-mini`、`gpt-5.4`;`gpt-5.5` 的默认 reasoning effort 必须是 `xhigh`,可通过 `CODE_QUEUE_MODEL_REASONING_EFFORTS` 追加或覆盖模型级默认值;每个入队任务可通过前端模型下拉菜单或 API 覆盖 `model`、`cwd`、`reasoningEffort` 和 `maxAttempts`,`maxAttempts` 上限为 `99`。Judge 判定 `retry` 或非用户取消类 `fail` 时必须继续已有 `codexThreadId`,不能新建 session;重试间隔使用指数退避,从 `1s` 开始,最大 `10min`。MiniMax 不可用而进入 fallback/non-LLM 判定时,当前 attempt 的 429、Too Many Requests、exceeded retry limit、overloaded、stream disconnected 等服务/限流错误应判定为 `retry`,不能当作完成;MiniMax 可用时,这些内容只能作为当前 attempt 的 factual evidence 提供给 MiniMax,不能通过硬编码覆盖 MiniMax 结果。 -- 状态与日志:`main-server` 默认工作目录为容器内 `/root/unidesk`,该路径映射主 server 的 `~/unidesk`;同时保留 `/workspace` 映射以兼容历史任务。非主 server Provider 的任务默认工作目录为 `/home/ubuntu`,任务 JSON、列表、Trace 摘要和 CLI 查询都必须显示 `providerId` 与最终 `cwd`。Code Queue 的任务、queue、`readAt`/未读状态、attempt、judge、`promptHistory`、active session 元数据、控制状态和 ClaudeQQ 通知 outbox 一律以主 PostgreSQL 为权威,分别写入 `unidesk_code_queue_tasks`、`unidesk_code_queue_queues` 与 `unidesk_code_queue_notifications`;`DATABASE_URL` 是必需配置,服务不得在 PostgreSQL 缺失或不可用时进入文件存储模式。`.state/code-queue/state.json` 不再作为任务或 queue 状态存储,不得重新引入本地 JSON fallback;服务启动必须以 PostgreSQL 为唯一来源恢复队列,并把 running/judging 任务恢复为 retry_wait。主 server 内存很少,Code Queue 必须把“内存是稀缺资源”作为核心设计约束:历史任务列表、详情、统计和只读 Trace 查询优先从 PostgreSQL 直读,进程内只保留当前 running/judging、queued、retry_wait 等调度必需热任务,不得把全部历史 task JSON 长期缓存到 Bun 堆;需要短期热缓存时必须有严格上限、可裁剪、可从 PostgreSQL 和 append-only 输出归档重建。WebUI 不得用 browser `localStorage`、`sessionStorage` 或 IndexedDB 持久化 task/queue/readAt/unread 等业务状态;浏览器只能保留临时 UI 内存缓存,刷新后必须重新从后端读取 PostgreSQL 权威数据。Codex CLI-like output/Trace 的完整记录可以使用 append-only 文件作为日志型归档,但任务状态、未读状态和列表摘要不得依赖这些文件作为权威来源;`/api/tasks//transcript` 与 `/api/tasks//output` 必须能分页重建完整历史,不得因为热状态裁剪而丢失早期 trace。热 task JSON 只保留可配置窗口以保证 `/health`、`/api/tasks` 和 PostgreSQL flush 不被长任务拖死;主 server 为 Code Queue 放宽到 600M 容器预算后仍默认 `CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS=10`、`CODE_QUEUE_IN_MEMORY_EVENT_RECORDS=10`,启动时必须在 PostgreSQL 查询侧裁剪 hot output/events,并只 flush dirty task,禁止启动后无条件重写全量历史 task JSON;更高预算才允许调大热窗口。WebUI 必须支持多 queue 查看、显式创建 queue、提交时下拉选择 queue、提交时下拉选择执行 Provider,并支持把已创建且非 active 的任务移动到其他 queue;queue 内串行,queue 间默认并行且不互相排队;`CODE_QUEUE_MAX_ACTIVE_QUEUES` 仅作为显式配置的全局 active slot 上限,`0` 表示不按 queue 数量限流,内存不足时由 cgroup memory pressure 阻止新 run 并在任务响应中暴露 `QUEUED(MEM LIMIT)`。Code Queue 镜像必须内置 Playwright Chromium 浏览器与系统依赖,并使用 `bun --smol` 运行后端,保证队列任务能直接执行公网 frontend Playwright 回归且主进程内存可控,不得只在宿主机临时安装。日志写入 UniDesk `logs/{YYYYMMDD}/{startStamp}_{YYYYMMDD}_{HH}_code-queue.jsonl`,按小时切片并按日志族默认保留 `1GiB`;Codex app-server 上游产生的 `logs_*.sqlite` 只能作为短暂缓冲,必须由 Code Queue 周期性导出为 `logs/{YYYYMMDD}/{startStamp}_{YYYYMMDD}_{HH}_codex-app-server.jsonl`,导出后删除/压缩已导出的 SQLite 行,避免重新形成 `logs_2.sqlite` 大文件;`/logs` 端点返回最近结构化日志。`/health` 的 `queue.storage.primary` 必须恒为 `postgres`,并通过 `queue.storage.postgresReady`、`queue.devReady` 和 `/api/dev-ready` 暴露 PostgreSQL 可用性、develop-ready 自检、必需工具、Docker socket、`docker compose`、默认工作目录、Codex config 状态和 `/root/.ssh` 共享 SSH key 状态。Codex CLI-like 输出可能很大,服务必须节流状态持久化,禁止对每个 output delta 同步重写完整 state 导致 `/health` 和控制 API 卡死;容器 healthcheck 必须使用带超时的 HTTP 探针,不能留下堆积的无超时探针进程。 +- 状态与日志:`main-server` 默认工作目录为容器内 `/root/unidesk`,该路径映射主 server 的 `~/unidesk`;同时保留 `/workspace` 映射以兼容历史任务。非主 server Provider 的任务默认工作目录为 `/home/ubuntu`,任务 JSON、列表、Trace 摘要和 CLI 查询都必须显示 `providerId`、`executionMode` 与最终 `cwd`。`executionMode=default` 沿用主 server 本机 Codex 或远程执行容器 Codex;`executionMode=windows-native` 只允许非主 server WSL Provider、Codex 模型和 `/mnt/` 工作目录,Code Queue 仍会启动远程执行容器,但容器只运行 stdio relay,经 WSL bridge 调用 Windows 宿主原生 `codex app-server --listen stdio://`,避免公网/main-server 到 Provider 的临时断连直接杀死 Windows Codex 进程。Code Queue 的任务、queue、`readAt`/未读状态、attempt、judge、`promptHistory`、active session 元数据、控制状态和 ClaudeQQ 通知 outbox 一律以主 PostgreSQL 为权威,分别写入 `unidesk_code_queue_tasks`、`unidesk_code_queue_queues` 与 `unidesk_code_queue_notifications`;`DATABASE_URL` 是必需配置,服务不得在 PostgreSQL 缺失或不可用时进入文件存储模式。`.state/code-queue/state.json` 不再作为任务或 queue 状态存储,不得重新引入本地 JSON fallback;服务启动必须以 PostgreSQL 为唯一来源恢复队列,并把 running/judging 任务恢复为 retry_wait。主 server 内存很少,Code Queue 必须把“内存是稀缺资源”作为核心设计约束:历史任务列表、详情、统计和只读 Trace 查询优先从 PostgreSQL 直读,进程内只保留当前 running/judging、queued、retry_wait 等调度必需热任务,不得把全部历史 task JSON 长期缓存到 Bun 堆;需要短期热缓存时必须有严格上限、可裁剪、可从 PostgreSQL 和 append-only 输出归档重建。WebUI 不得用 browser `localStorage`、`sessionStorage` 或 IndexedDB 持久化 task/queue/readAt/unread 等业务状态;浏览器只能保留临时 UI 内存缓存,刷新后必须重新从后端读取 PostgreSQL 权威数据。Codex CLI-like output/Trace 的完整记录可以使用 append-only 文件作为日志型归档,但任务状态、未读状态和列表摘要不得依赖这些文件作为权威来源;`/api/tasks//transcript` 与 `/api/tasks//output` 必须能分页重建完整历史,不得因为热状态裁剪而丢失早期 trace。热 task JSON 只保留可配置窗口以保证 `/health`、`/api/tasks` 和 PostgreSQL flush 不被长任务拖死;主 server 为 Code Queue 放宽到 600M 容器预算后仍默认 `CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS=10`、`CODE_QUEUE_IN_MEMORY_EVENT_RECORDS=10`,启动时必须在 PostgreSQL 查询侧裁剪 hot output/events,并只 flush dirty task,禁止启动后无条件重写全量历史 task JSON;更高预算才允许调大热窗口。WebUI 必须支持多 queue 查看、显式创建 queue、提交时下拉选择 queue、提交时下拉选择执行 Provider 和执行模式,并支持把已创建且非 active 的任务移动到其他 queue;queue 内串行,queue 间默认并行且不互相排队;`CODE_QUEUE_MAX_ACTIVE_QUEUES` 仅作为显式配置的全局 active slot 上限,`0` 表示不按 queue 数量限流,内存不足时由 cgroup memory pressure 阻止新 run 并在任务响应中暴露 `QUEUED(MEM LIMIT)`。Code Queue 镜像必须内置 Playwright Chromium 浏览器与系统依赖,并使用 `bun --smol` 运行后端,保证队列任务能直接执行公网 frontend Playwright 回归且主进程内存可控,不得只在宿主机临时安装。日志写入 UniDesk `logs/{YYYYMMDD}/{startStamp}_{YYYYMMDD}_{HH}_code-queue.jsonl`,按小时切片并按日志族默认保留 `1GiB`;Codex app-server 上游产生的 `logs_*.sqlite` 只能作为短暂缓冲,必须由 Code Queue 周期性导出为 `logs/{YYYYMMDD}/{startStamp}_{YYYYMMDD}_{HH}_codex-app-server.jsonl`,导出后删除/压缩已导出的 SQLite 行,避免重新形成 `logs_2.sqlite` 大文件;`/logs` 端点返回最近结构化日志。`/health` 的 `queue.storage.primary` 必须恒为 `postgres`,并通过 `queue.storage.postgresReady`、`queue.devReady` 和 `/api/dev-ready` 暴露 PostgreSQL 可用性、develop-ready 自检、必需工具、Docker socket、`docker compose`、默认工作目录、Codex config 状态和 `/root/.ssh` 共享 SSH key 状态。Codex CLI-like 输出可能很大,服务必须节流状态持久化,禁止对每个 output delta 同步重写完整 state 导致 `/health` 和控制 API 卡死;容器 healthcheck 必须使用带超时的 HTTP 探针,不能留下堆积的无超时探针进程。 - ClaudeQQ 通知:Code Queue 可通过 backend-core 的 `claudeqq` 用户服务代理调用 `POST /api/push/text`,在每个任务进入 `succeeded`、`failed` 或 `canceled` 终态后向配置目标发送最终 response,并附带 task id、queue、状态、模型、attempt、当前 running/queued/retry_wait 数和任务总耗时;当所有 queue 进入 `0 running / 0 queued` 空闲态时,必须单独发送一次空闲提醒。通知由 `CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED` 控制,目标由 `CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE=private|group`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID` 配置,默认私聊 `645275593`;代理基址、最终 response 最大字符数、单次超时和发送尝试次数分别由 `CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_MAX_RESPONSE_CHARS`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_TIMEOUT_MS` 和 `CODE_QUEUE_NOTIFY_CLAUDEQQ_SEND_ATTEMPTS` 配置。任务终态和队列空闲通知必须先写入 PostgreSQL outbox 表 `unidesk_code_queue_notifications` 再异步发送;不得使用 `.state/code-queue/claudeqq-notifications.json`、`CODE_QUEUE_NOTIFY_CLAUDEQQ_OUTBOX_PATH` 或任何本地 JSON 作为通知权威存储。发送失败、NapCat 离线、代理 502 或容器重启时不能丢通知,必须按 `CODE_QUEUE_NOTIFY_CLAUDEQQ_RETRY_INTERVAL_MS` 指数退避重试并跨进程/容器重启保留。`/health` 的 `queue.notifications.claudeqq` 必须暴露非敏感配置、目标配置状态和 PostgreSQL outbox 统计;`GET /api/notifications/claudeqq` 返回 outbox 明细,`POST /api/notifications/claudeqq/drain` 手动触发发送,`POST /api/notifications/claudeqq/backfill` 可按 `since` 补入某次故障窗口内已终态任务,确保 QQ/NapCat 超时或离线不会让任务完成通知永久丢失。 -- OA 接入:Code Queue 后端通过 `OA_EVENT_FLOW_BASE_URL=http://oa-event-flow:4255` 发布每个 TraceView 可见执行行的 `trace-step-created`、幂等种子/乱序校正用 `trace-stats-snapshot`、`task-updated` 和 queue 事件;服务启动或手动 backfill 时必须用相同 `eventId` 幂等回放历史 TraceView 可见执行行,避免历史任务停留在旧 STEP 统计口径。前端通过 `oa-event-flow` 的 `service:code-queue` tag stream 更新 STEP 和 Trace Summary,Code Queue 私有 SSE 不再作为刷新权威。`STEP` 表示 TraceView 可见执行行数,工具调用数必须由 `readCount+editCount+runCount` 展示,不能复用 `stepCount`。 +- OA 接入:Code Queue 后端通过 `OA_EVENT_FLOW_BASE_URL=http://oa-event-flow:4255` 发布每个 TraceView 可见执行行的 `trace-step-created`、幂等种子/乱序校正用 `trace-stats-snapshot`、`task-updated` 和 queue 事件;服务启动或手动 backfill 时必须用相同 `eventId` 幂等回放历史 TraceView 可见执行行,避免历史任务停留在旧 STEP 统计口径。前端通过 `oa-event-flow` 的 `service:code-queue` tag stream 更新 STEP 和 Trace Summary,Code Queue 私有 SSE 不再作为刷新权威。`STEP` 表示 TraceView 可见且非 system 的执行行数;system 行可保留在任务原始输出/数据库中,但默认不展示、不计入 STEP,工具调用数必须由 `readCount+editCount+runCount` 展示,不能复用 `stepCount`。 - 代理路径:只允许 `/health`、`/logs` 和 `/api/` 前缀;允许方法为 `GET`、`HEAD`、`POST`、`DELETE`、`PATCH`。Code Queue 只在 Compose 内网暴露 `4222/tcp`,不得映射或开放到公网。 -- UniDesk 前端:`用户服务 / Code Queue` React 页面负责展示队列卡片、任务 ID、复制任务 ID、引用按钮、任务耗时、默认模型、模型下拉、执行 Provider 下拉、Provider 对应默认工作目录、显式入队份数、引用任务 ID、清空输入、创建成功提示、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、追加 prompt、打断和手动重试控件;整个 agent loop 消息流统一命名为专有名词 `Trace`,`Trace` 包含 assistant message、user prompt、system event 和 tool call;Code Queue 与 Pipeline/OpenCode messages 必须共用 `src/components/frontend/src/trace.tsx` 的 Trace 公共组件、统一 Trace item 接口和 codex/opencode port 适配层;连续 read/edit/run 工具调用只是在 Trace 内折叠为可展开工具调用组,汇总格式至少包含 `xx read, xx edit, xx run`,并展示读取文件、编辑文件、运行命令和耗时摘要;最近 3 个工具调用保持展开,工具调用内容不得自动换行且必须在工具调用块内部横向滚动,工具调用组展开后不得再增加额外左侧缩进;message 与 prompt 必须自动换行,普通 message 不显示左侧项目符号缩进且永不折叠;点击队列卡片引用按钮必须自动把该任务 ID 写入提交表单的引用任务 ID 输入框;引用任务 ID 创建新任务时必须自动注入 `bun scripts/cli.ts codex task ` 的提示,让 Codex 读取初始 prompt、最后消息和工具摘要后继续;连续执行同一 prompt 应使用 `入队份数` 一次性生成多条队列任务,而不是依赖快速连点按钮;左侧 queue/session 卡片的 `QUEUED` 状态必须显示原因,例如 `QUEUED(PREV TASK)`、`QUEUED(MEM LIMIT)`、`QUEUED(ACTIVE LIMIT)`;原始任务 JSON 只能通过显式 `查看原始JSON` 打开。 +- UniDesk 前端:`用户服务 / Code Queue` React 页面负责展示队列卡片、任务 ID、复制任务 ID、引用按钮、任务耗时、默认模型、模型下拉、执行 Provider 下拉、执行模式下拉、Provider/模式对应默认工作目录、显式入队份数、引用任务 ID、清空输入、创建成功提示、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、追加 prompt、打断和手动重试控件;选择 `windows-native` 时应优先切到支持 Windows 原生 Codex 的非主 server Provider,并把工作目录提示切到 `/mnt/` 默认路径;整个 agent loop 消息流统一命名为专有名词 `Trace`,`Trace` 包含 assistant message、user prompt、system event 和 tool call;Code Queue 与 Pipeline/OpenCode messages 必须共用 `src/components/frontend/src/trace.tsx` 的 Trace 公共组件、统一 Trace item 接口和 codex/opencode port 适配层;连续 read/edit/run 工具调用只是在 Trace 内折叠为可展开工具调用组,汇总格式至少包含 `xx read, xx edit, xx run`,并展示读取文件、编辑文件、运行命令和耗时摘要;最近 3 个工具调用保持展开,工具调用内容不得自动换行且必须在工具调用块内部横向滚动,工具调用组展开后不得再增加额外左侧缩进;message 与 prompt 必须自动换行,普通 message 不显示左侧项目符号缩进且永不折叠;点击队列卡片引用按钮必须自动把该任务 ID 写入提交表单的引用任务 ID 输入框;引用任务 ID 创建新任务时必须自动注入 `bun scripts/cli.ts codex task ` 的提示,让 Codex 读取初始 prompt、最后消息和工具摘要后继续;连续执行同一 prompt 应使用 `入队份数` 一次性生成多条队列任务,而不是依赖快速连点按钮;左侧 queue/session 卡片的 `QUEUED` 状态必须显示原因,例如 `QUEUED(PREV TASK)`、`QUEUED(MEM LIMIT)`、`QUEUED(ACTIVE LIMIT)`;原始任务 JSON 只能通过显式 `查看原始JSON` 打开。 ## D601 User Services diff --git a/docs/reference/oa-event-flow.md b/docs/reference/oa-event-flow.md index 0794bb54..62e1ea81 100644 --- a/docs/reference/oa-event-flow.md +++ b/docs/reference/oa-event-flow.md @@ -59,7 +59,7 @@ Tag 是 OA 事件流的订阅和投影索引。所有 tag 必须是稳定字符 - Code Queue 不再维护独立 SSE 作为前端 Trace/STEP 刷新权威;任务输出、状态变更、queue 变更和统计快照必须发布到 `oa-event-flow`。 - Code Queue 左侧 task card 的 `STEP`、选中 task 的 Trace Summary 和全局统计只能读取 `oa_trace_stats`;本地 task JSON 中的历史字段只能作为发布 snapshot 事件的输入,不作为前端权威统计来源。统计尚未投影完成时必须明确显示 `statsSource=unavailable` 或 `STEP --`,不得回退到 transcript、本地 `stepCount` 或前端重算。 -- 运行中每个新的 TraceView 可见执行行都必须发布 `trace-step-created`,并带 `task:`、`queue:`、`attempt:`、`service:code-queue`、`trace` tag,以及 payload 中的 `scopeId=task:`、`attemptIndex` 和 `attemptScopeId=task::attempt:`;统计中心据此幂等更新任务级累计统计和 attempt 级独立统计,message/system/error 行只增加 STEP 或 error,不伪装为工具调用。 +- 运行中每个新的 TraceView 可见执行行都必须发布 `trace-step-created`,并带 `task:`、`queue:`、`attempt:`、`service:code-queue`、`trace` tag,以及 payload 中的 `scopeId=task:`、`attemptIndex` 和 `attemptScopeId=task::attempt:`;统计中心据此幂等更新任务级累计统计和 attempt 级独立统计,message/error 行增加 STEP 或 error,system 行默认仅保留在任务原始输出/数据库中,不进入 STEP 计数且不伪装为工具调用。 - Trace Summary 顶部执行摘要读取任务级 `task:`;执行过程摘要 `#` 读取 `task::attempt:`。如果 attempt scope 尚未投影完成,必须显示 `statsSource=unavailable` 或 `--`,不得回退到任务级累计统计、transcript 重算或旧本地字段。 - 任务入队、开始、终态、移动 queue、标记已读等状态事实必须发布 `task-updated` 或更具体的事实事件,供事件表和后续审计使用。 - Code Queue 服务启动后可对 PostgreSQL 中已有任务回放每个 TraceView 可见执行行的 `trace-step-created`,并发布 `trace-stats-snapshot` 事件完成统计中心种子同步;回放必须使用相同 `eventId` 保持幂等,不得阻塞队列恢复。历史回放必须按 attempt start 行推导 `attemptIndex`,确保重建投影时 attempt scope 可独立恢复。 diff --git a/docs/reference/windows-passthrough.md b/docs/reference/windows-passthrough.md index 65196a46..d95d48e5 100644 --- a/docs/reference/windows-passthrough.md +++ b/docs/reference/windows-passthrough.md @@ -162,6 +162,17 @@ Keil/串口/board-comm 的通用顺序如下: 多 probe 同时在线时,`keil program`、`keil detect` 必须显式传 `-u `。若 Keil UV4 backend 报缺少 flash/download metadata,可优先用 pyOCD backend 完成下载;是否补齐 UV4 工程下载配置应作为工程维护问题处理,而不是 SSH/Windows 透传问题。 +## Code Queue Windows Native Codex + +Code Queue 支持在提交任务时选择 `executionMode=windows-native`。该模式用于 D601 这类 WSL Provider:主 server 仍先通过既有远程执行容器建立任务运行环境,但容器内不启动 `codex`;容器只运行 stdio relay,连接到 WSL 侧 bridge,再由 bridge 调用 Windows 宿主原生 `codex app-server --listen stdio://`。这样公网/main-server 到 Provider 的临时断连不会直接终止 Windows Codex 进程。 + +约束: + +- 只支持非主 server WSL Provider 和 Codex 模型;`minimax-m2.7` / OpenCode port 不走该模式。 +- 工作目录必须在 `/mnt//...` 下,供 `win-cmd` 转换为 Windows 盘符 cwd;D601 默认提示为 `/mnt/f/Work/ConStart`。 +- Windows 侧必须已安装 `codex`,且 WSL wrapper `win-cmd` 可用;可用 `bun scripts/cli.ts ssh D601 -- 'export PATH="$HOME/.local/bin:$PATH"; win-cmd "where codex && codex --version"'` 验证。 +- 任务 JSON、列表、Trace 摘要和前端卡片必须显示 `executionMode`,便于区分默认容器 Codex 与 Windows 原生 Codex。 + ## Remote Frontend Limits `--main-server-ip ... ssh ` 走 frontend 登录态和 `host.ssh` dispatch,适合短命令和 skill discovery。它不流式转发 stdin,也受 provider-gateway 的 host.ssh command length 限制;`apply-patch`、`py < stdin`、超长 inline 脚本和需要完整终端流的操作应在 main server 本机 CLI 上执行,或显式走旧 SSH transport。 diff --git a/scripts/cli.ts b/scripts/cli.ts index bb026f6b..dad6a4ed 100644 --- a/scripts/cli.ts +++ b/scripts/cli.ts @@ -46,6 +46,7 @@ function help(): unknown { { command: "schedule upsert-pgdata-backup [--time HH:MM] [--remote-base /SERVER_DATA/UNIDESK_PG_DATA]", description: "Create or update the daily PGDATA physical backup task that uploads monthly rotated archives to Baidu Netdisk." }, { command: "codex task [--trace --tail|--from-start|--after-seq N|--before-seq N --limit N] [--full]", description: "Fetch a compact Code Queue task summary; trace rows are opt-in and paged with next/previous commands to avoid output explosion." }, { command: "codex output [--tail|--from-start|--after-seq N|--before-seq N --limit N] [--full-text]", description: "Fetch paged raw Code Queue output records by seq when a trace row has omitted command/output text." }, + { command: "codex judge --attempt N [--dry-run] [--include-prompt]", description: "Replay one stored Code Queue attempt through the same judge context builder and MiniMax judge call path used by the live queue worker." }, { command: "codex (queues | queue create | queue merge --into | move --queue )", description: "List/create/merge Code Queue lanes and move a queued task; merge preserves task queue time order and deletes the source queue record." }, { command: "job list", description: "List async jobs from .state/jobs." }, { command: "job status [--tail-bytes N]", description: "Show job state with bounded stdout/stderr tails." }, diff --git a/scripts/src/code-queue.ts b/scripts/src/code-queue.ts index 899e5cdb..6a856ebd 100644 --- a/scripts/src/code-queue.ts +++ b/scripts/src/code-queue.ts @@ -27,8 +27,15 @@ interface CodexOutputOptions { maxTextChars: number; } -type CodexResponseFetcher = (path: string) => unknown; -type AsyncCodexResponseFetcher = (path: string) => Promise; +interface CodexJudgeOptions { + attempt: number | null; + dryRun: boolean; + includePrompt: boolean; +} + +type CodexRequestInit = { method?: string; body?: unknown }; +type CodexResponseFetcher = (path: string, init?: CodexRequestInit) => unknown; +type AsyncCodexResponseFetcher = (path: string, init?: CodexRequestInit) => Promise; function requireTaskId(value: string | undefined, command: string): string { if (value === undefined || value.trim().length === 0) throw new Error(`${command} requires task id`); @@ -432,6 +439,21 @@ function parseOutputOptions(args: string[]): CodexOutputOptions { }; } +function parseJudgeOptions(args: string[]): CodexJudgeOptions { + const rawAttempt = optionValue(args, ["--attempt", "--attempt-id", "--attemptIndex"]) ?? positionalArgs(args)[0]; + let attempt: number | null = null; + if (rawAttempt !== undefined) { + const value = Number(rawAttempt); + if (!Number.isInteger(value) || value <= 0) throw new Error("--attempt must be a positive integer"); + attempt = value; + } + return { + attempt, + dryRun: hasFlag(args, "--dry-run") || hasFlag(args, "--no-call"), + includePrompt: hasFlag(args, "--include-prompt"), + }; +} + function queryString(params: Record): string { const search = new URLSearchParams(); for (const [key, value] of Object.entries(params)) { @@ -506,6 +528,16 @@ function codexTaskOutput(taskId: string, options: CodexOutputOptions, fetcher: C return { upstream: response.upstream, outputPage: compactOutputPage(response.body, taskId, options.limit) }; } +function codexTaskJudge(taskId: string, options: CodexJudgeOptions, fetcher: CodexResponseFetcher): unknown { + const params = queryString({ + attempt: options.attempt, + dryRun: options.dryRun ? 1 : undefined, + includePrompt: options.includePrompt ? 1 : undefined, + }); + const response = unwrapCodexResponse(fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/judge${params}`, { method: "POST" })); + return { upstream: response.upstream, judgeReplay: response.body }; +} + export function codexTaskQuery(taskId: string, optionArgs: string[], fetcher: CodexResponseFetcher = coreInternalFetch): unknown { return codexTaskSummary(taskId, parseTaskOptions(optionArgs), fetcher); } @@ -514,6 +546,10 @@ export function codexOutputQuery(taskId: string, optionArgs: string[], fetcher: return codexTaskOutput(taskId, parseOutputOptions(optionArgs), fetcher); } +export function codexJudgeQuery(taskId: string, optionArgs: string[], fetcher: CodexResponseFetcher = coreInternalFetch): unknown { + return codexTaskJudge(taskId, parseJudgeOptions(optionArgs), fetcher); +} + async function codexTaskSummaryAsync(taskId: string, options: CodexTaskOptions, fetcher: AsyncCodexResponseFetcher): Promise { const summaryPath = `/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/summary${queryString({ toolLimit: options.toolLimit })}`; const summaryResponse = unwrapCodexResponse(await fetcher(summaryPath)); @@ -548,6 +584,16 @@ async function codexTaskOutputAsync(taskId: string, options: CodexOutputOptions, return { upstream: response.upstream, outputPage: compactOutputPage(response.body, taskId, options.limit) }; } +async function codexTaskJudgeAsync(taskId: string, options: CodexJudgeOptions, fetcher: AsyncCodexResponseFetcher): Promise { + const params = queryString({ + attempt: options.attempt, + dryRun: options.dryRun ? 1 : undefined, + includePrompt: options.includePrompt ? 1 : undefined, + }); + const response = unwrapCodexResponse(await fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/judge${params}`, { method: "POST" })); + return { upstream: response.upstream, judgeReplay: response.body }; +} + export async function codexTaskQueryAsync(taskId: string, optionArgs: string[], fetcher: AsyncCodexResponseFetcher): Promise { return codexTaskSummaryAsync(taskId, parseTaskOptions(optionArgs), fetcher); } @@ -556,6 +602,10 @@ export async function codexOutputQueryAsync(taskId: string, optionArgs: string[] return codexTaskOutputAsync(taskId, parseOutputOptions(optionArgs), fetcher); } +export async function codexJudgeQueryAsync(taskId: string, optionArgs: string[], fetcher: AsyncCodexResponseFetcher): Promise { + return codexTaskJudgeAsync(taskId, parseJudgeOptions(optionArgs), fetcher); +} + function requireQueueId(args: string[], command: string): string { const index = args.indexOf("--queue"); const raw = index === -1 ? args[0] : args[index + 1]; @@ -625,6 +675,10 @@ export async function runCodeQueueCommand(_config: UniDeskConfig, args: string[] const taskId = requireTaskId(taskIdArg, "codex output"); return codexOutputQuery(taskId, args.slice(2)); } + if (action === "judge") { + const taskId = requireTaskId(taskIdArg, "codex judge"); + return codexJudgeQuery(taskId, args.slice(2)); + } if (action === "queues") return codeQueues(); if (action === "queue") { const sub = taskIdArg ?? "list"; @@ -639,5 +693,5 @@ export async function runCodeQueueCommand(_config: UniDeskConfig, args: string[] const taskId = requireTaskId(taskIdArg, "codex move"); return codexMoveTask(taskId, requireQueueId(args.slice(2), "codex move")); } - throw new Error("codex command must be one of: task, summary, show, output, queues, queue list, queue create, queue merge, move"); + throw new Error("codex command must be one of: task, summary, show, output, judge, queues, queue list, queue create, queue merge, move"); } diff --git a/scripts/src/docker.ts b/scripts/src/docker.ts index f95f3a5e..59217e82 100644 --- a/scripts/src/docker.ts +++ b/scripts/src/docker.ts @@ -59,6 +59,12 @@ export function writeComposeEnv(config: UniDeskConfig, freshLogPrefix: boolean): const previousRaw = existsSync(envFile) ? readFileSync(envFile, "utf8") : ""; const previousValue = (key: string): string => previousRaw.match(new RegExp(`^${key}=(.*)$`, "m"))?.[1]?.replace(/^"|"$/g, "") ?? ""; const runtimeSecret = (key: string): string => process.env[key] ?? previousValue(key); + const runtimeSecretWithDefault = (key: string, defaultValue: string, legacyDefault = ""): string => { + if (process.env[key] !== undefined) return process.env[key] ?? defaultValue; + const previous = previousValue(key); + if (previous.length > 0 && previous !== legacyDefault) return previous; + return defaultValue; + }; let logRoot: string; let logDay: string; let logPrefix: string; @@ -134,7 +140,7 @@ export function writeComposeEnv(config: UniDeskConfig, freshLogPrefix: boolean): UNIDESK_CODE_QUEUE_MINIMAX_API_KEY: runtimeSecret("UNIDESK_CODE_QUEUE_MINIMAX_API_KEY") || runtimeSecret("MINIMAX_API_KEY"), UNIDESK_CODE_QUEUE_MINIMAX_MODEL: runtimeSecret("UNIDESK_CODE_QUEUE_MINIMAX_MODEL") || runtimeSecret("MINIMAX_MODEL") || "MiniMax-M2.7", UNIDESK_CODE_QUEUE_MINIMAX_API_BASE: runtimeSecret("UNIDESK_CODE_QUEUE_MINIMAX_API_BASE") || runtimeSecret("MINIMAX_API_BASE") || "https://api.minimaxi.com/v1", - UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_TIMEOUT_MS: runtimeSecret("UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_TIMEOUT_MS") || "60000", + UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_TIMEOUT_MS: runtimeSecretWithDefault("UNIDESK_CODE_QUEUE_MINIMAX_JUDGE_TIMEOUT_MS", "90000", "60000"), UNIDESK_CODE_QUEUE_REMOTE_WORKDIR: runtimeSecret("UNIDESK_CODE_QUEUE_REMOTE_WORKDIR") || "/home/ubuntu", UNIDESK_CODE_QUEUE_EXECUTION_PROVIDER_IDS: runtimeSecret("UNIDESK_CODE_QUEUE_EXECUTION_PROVIDER_IDS") || "D601", UNIDESK_CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID: runtimeSecret("UNIDESK_CODE_QUEUE_DEV_CONTAINER_DEFAULT_PROVIDER_ID") || "D601", diff --git a/scripts/src/remote.ts b/scripts/src/remote.ts index 10f3ed57..1a3b8a51 100644 --- a/scripts/src/remote.ts +++ b/scripts/src/remote.ts @@ -3,7 +3,7 @@ import { type UniDeskConfig } from "./config"; import { type DebugDispatchCommand, isDebugDispatchCommand } from "./debug"; import { summarizeMicroserviceProxyResponse } from "./microservices"; import { isSshSkillDiscoveryArgs, parseSshArgs } from "./ssh"; -import { codexOutputQueryAsync, codexTaskQueryAsync } from "./code-queue"; +import { codexJudgeQueryAsync, codexOutputQueryAsync, codexTaskQueryAsync } from "./code-queue"; export interface RemoteCliOptions { host: string | null; @@ -470,16 +470,26 @@ async function remoteMicroservice(session: FrontendSession, args: string[]): Pro async function remoteCodeQueue(session: FrontendSession, args: string[]): Promise { const action = args[1] ?? "task"; - if (action !== "task" && action !== "summary" && action !== "show" && action !== "output") { - throw new Error("remote codex command must be: codex task or codex output "); + if (action !== "task" && action !== "summary" && action !== "show" && action !== "output" && action !== "judge") { + throw new Error("remote codex command must be: codex task , codex output , or codex judge --attempt N"); } const taskId = args[2]; if (taskId === undefined || taskId.length === 0) throw new Error(`codex ${action} requires task id`); - const fetcher = (path: string): Promise => frontendJson(session, path, undefined, 24_000); + const fetcher = (path: string, init?: { method?: string; body?: unknown }): Promise => { + const requestInit = init === undefined + ? undefined + : { + method: init.method, + body: init.body === undefined ? undefined : JSON.stringify(init.body), + }; + return frontendJson(session, path, requestInit, action === "judge" ? 130_000 : 24_000); + }; return { transport: "frontend", result: action === "output" ? await codexOutputQueryAsync(taskId, args.slice(3), fetcher) + : action === "judge" + ? await codexJudgeQueryAsync(taskId, args.slice(3), fetcher) : await codexTaskQueryAsync(taskId, args.slice(3), fetcher), }; } @@ -538,7 +548,7 @@ async function runRemoteCliOverFrontend(options: RemoteCliOptions, config: UniDe emitRemoteJson(name, { transport: "frontend", baseUrl: session.baseUrl, - commands: ["debug health", "debug dispatch", "debug task", "ssh ", "ssh skills", "microservice list", "microservice status ", "microservice health ", "microservice proxy ", "codex task "], + commands: ["debug health", "debug dispatch", "debug task", "ssh ", "ssh skills", "microservice list", "microservice status ", "microservice health ", "microservice proxy ", "codex task ", "codex judge --attempt N"], }); return 0; } diff --git a/src/components/frontend/public/app.js b/src/components/frontend/public/app.js index 6e47d599..c4223d9c 100644 --- a/src/components/frontend/public/app.js +++ b/src/components/frontend/public/app.js @@ -1,39 +1,41 @@ -(()=>{var yK=Object.create;var{getPrototypeOf:_K,defineProperty:U7,getOwnPropertyNames:$K}=Object;var tK=Object.prototype.hasOwnProperty;function cK(u){return this[u]}var AK,jK,Mu=(u,f,l)=>{var r=u!=null&&typeof u==="object";if(r){var n=f?AK??=new WeakMap:jK??=new WeakMap,i=n.get(u);if(i)return i}l=u!=null?yK(_K(u)):{};let y=f||!u||!u.__esModule?U7(l,"default",{value:u,enumerable:!0}):l;for(let _ of $K(u))if(!tK.call(y,_))U7(y,_,{get:cK.bind(u,_),enumerable:!0});if(r)n.set(u,y);return y};var ur=(u,f)=>()=>(f||u((f={exports:{}}).exports,f),f.exports);var eu=((u)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(u,{get:(f,l)=>(typeof require<"u"?require:f)[l]}):u)(function(u){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+u+'" is not supported')});var Z7=ur((su)=>{var Oy=Symbol.for("react.element"),FK=Symbol.for("react.portal"),JK=Symbol.for("react.fragment"),UK=Symbol.for("react.strict_mode"),QK=Symbol.for("react.profiler"),qK=Symbol.for("react.provider"),NK=Symbol.for("react.context"),WK=Symbol.for("react.forward_ref"),wK=Symbol.for("react.suspense"),LK=Symbol.for("react.memo"),KK=Symbol.for("react.lazy"),Q7=Symbol.iterator;function GK(u){if(u===null||typeof u!=="object")return null;return u=Q7&&u[Q7]||u["@@iterator"],typeof u==="function"?u:null}var W7={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w7=Object.assign,L7={};function e1(u,f,l){this.props=u,this.context=f,this.refs=L7,this.updater=l||W7}e1.prototype.isReactComponent={};e1.prototype.setState=function(u,f){if(typeof u!=="object"&&typeof u!=="function"&&u!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,u,f,"setState")};e1.prototype.forceUpdate=function(u){this.updater.enqueueForceUpdate(this,u,"forceUpdate")};function K7(){}K7.prototype=e1.prototype;function v8(u,f,l){this.props=u,this.context=f,this.refs=L7,this.updater=l||W7}var k8=v8.prototype=new K7;k8.constructor=v8;w7(k8,e1.prototype);k8.isPureReactComponent=!0;var q7=Array.isArray,G7=Object.prototype.hasOwnProperty,I8={current:null},z7={key:!0,ref:!0,__self:!0,__source:!0};function T7(u,f,l){var r,n={},i=null,y=null;if(f!=null)for(r in f.ref!==void 0&&(y=f.ref),f.key!==void 0&&(i=""+f.key),f)G7.call(f,r)&&!z7.hasOwnProperty(r)&&(n[r]=f[r]);var _=arguments.length-2;if(_===1)n.children=l;else if(1<_){for(var $=Array(_),c=0;c<_;c++)$[c]=arguments[c+2];n.children=$}if(u&&u.defaultProps)for(r in _=u.defaultProps,_)n[r]===void 0&&(n[r]=_[r]);return{$$typeof:Oy,type:u,key:i,ref:y,props:n,_owner:I8.current}}function zK(u,f){return{$$typeof:Oy,type:u.type,key:f,ref:u.ref,props:u.props,_owner:u._owner}}function g8(u){return typeof u==="object"&&u!==null&&u.$$typeof===Oy}function TK(u){var f={"=":"=0",":":"=2"};return"$"+u.replace(/[=:]/g,function(l){return f[l]})}var N7=/\/+/g;function b8(u,f){return typeof u==="object"&&u!==null&&u.key!=null?TK(""+u.key):f.toString(36)}function rt(u,f,l,r,n){var i=typeof u;if(i==="undefined"||i==="boolean")u=null;var y=!1;if(u===null)y=!0;else switch(i){case"string":case"number":y=!0;break;case"object":switch(u.$$typeof){case Oy:case FK:y=!0}}if(y)return y=u,n=n(y),u=r===""?"."+b8(y,0):r,q7(n)?(l="",u!=null&&(l=u.replace(N7,"$&/")+"/"),rt(n,f,l,"",function(c){return c})):n!=null&&(g8(n)&&(n=zK(n,l+(!n.key||y&&y.key===n.key?"":(""+n.key).replace(N7,"$&/")+"/")+u)),f.push(n)),1;if(y=0,r=r===""?".":r+":",q7(u))for(var _=0;_{O7.exports=Z7()});var P7=ur((qf)=>{function d8(u,f){var l=u.length;u.push(f);u:for(;0>>1,n=u[r];if(0>>1;ryt(_,l))$yt(c,_)?(u[r]=c,u[$]=l,r=$):(u[r]=_,u[y]=l,r=y);else if($yt(c,l))u[r]=c,u[$]=l,r=$;else break u}}return f}function yt(u,f){var l=u.sortIndex-f.sortIndex;return l!==0?l:u.id-f.id}if(typeof performance==="object"&&typeof performance.now==="function")e8=performance,qf.unstable_now=function(){return e8.now()};else _t=Date,u4=_t.now(),qf.unstable_now=function(){return _t.now()-u4};var e8,_t,u4,ar=[],a0=[],VK=1,Qr=null,Fl=3,At=!1,en=!1,By=!1,X7=typeof setTimeout==="function"?setTimeout:null,Y7=typeof clearTimeout==="function"?clearTimeout:null,D7=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function f4(u){for(var f=Vr(a0);f!==null;){if(f.callback===null)ct(a0);else if(f.startTime<=u)ct(a0),f.sortIndex=f.expirationTime,d8(ar,f);else break;f=Vr(a0)}}function r4(u){if(By=!1,f4(u),!en)if(Vr(ar)!==null)en=!0,i4(n4);else{var f=Vr(a0);f!==null&&y4(r4,f.startTime-u)}}function n4(u,f){en=!1,By&&(By=!1,Y7(Vy),Vy=-1),At=!0;var l=Fl;try{f4(f);for(Qr=Vr(ar);Qr!==null&&(!(Qr.expirationTime>f)||u&&!p7());){var r=Qr.callback;if(typeof r==="function"){Qr.callback=null,Fl=Qr.priorityLevel;var n=r(Qr.expirationTime<=f);f=qf.unstable_now(),typeof n==="function"?Qr.callback=n:Qr===Vr(ar)&&ct(ar),f4(f)}else ct(ar);Qr=Vr(ar)}if(Qr!==null)var i=!0;else{var y=Vr(a0);y!==null&&y4(r4,y.startTime-f),i=!1}return i}finally{Qr=null,Fl=l,At=!1}}var jt=!1,$t=null,Vy=-1,S7=5,m7=-1;function p7(){return qf.unstable_now()-m7u||125r?(u.sortIndex=l,d8(a0,u),Vr(ar)===null&&u===Vr(a0)&&(By?(Y7(Vy),Vy=-1):By=!0,y4(r4,l-r))):(u.sortIndex=n,d8(ar,u),en||At||(en=!0,i4(n4))),u};qf.unstable_shouldYield=p7;qf.unstable_wrapCallback=function(u){var f=Fl;return function(){var l=Fl;Fl=f;try{return u.apply(this,arguments)}finally{Fl=l}}}});var C7=ur((pm,M7)=>{M7.exports=P7()});var xJ=ur((yr)=>{var DK=Qf(),nr=C7();function Uu(u){for(var f="https://reactjs.org/docs/error-decoder.html?invariant="+u,l=1;l"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),O4=Object.prototype.hasOwnProperty,XK=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,R7={},x7={};function YK(u){if(O4.call(x7,u))return!0;if(O4.call(R7,u))return!1;if(XK.test(u))return x7[u]=!0;return R7[u]=!0,!1}function SK(u,f,l,r){if(l!==null&&l.type===0)return!1;switch(typeof f){case"function":case"symbol":return!0;case"boolean":if(r)return!1;if(l!==null)return!l.acceptsBooleans;return u=u.toLowerCase().slice(0,5),u!=="data-"&&u!=="aria-";default:return!1}}function mK(u,f,l,r){if(f===null||typeof f>"u"||SK(u,f,l,r))return!0;if(r)return!1;if(l!==null)switch(l.type){case 3:return!f;case 4:return f===!1;case 5:return isNaN(f);case 6:return isNaN(f)||1>f}return!1}function Hl(u,f,l,r,n,i,y){this.acceptsBooleans=f===2||f===3||f===4,this.attributeName=r,this.attributeNamespace=n,this.mustUseProperty=l,this.propertyName=u,this.type=f,this.sanitizeURL=i,this.removeEmptyString=y}var _l={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(u){_l[u]=new Hl(u,0,!1,u,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(u){var f=u[0];_l[f]=new Hl(f,1,!1,u[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(u){_l[u]=new Hl(u,2,!1,u.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(u){_l[u]=new Hl(u,2,!1,u,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(u){_l[u]=new Hl(u,3,!1,u.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(u){_l[u]=new Hl(u,3,!0,u,null,!1,!1)});["capture","download"].forEach(function(u){_l[u]=new Hl(u,4,!1,u,null,!1,!1)});["cols","rows","size","span"].forEach(function(u){_l[u]=new Hl(u,6,!1,u,null,!1,!1)});["rowSpan","start"].forEach(function(u){_l[u]=new Hl(u,5,!1,u.toLowerCase(),null,!1,!1)});var K2=/[\-:]([a-z])/g;function G2(u){return u[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(u){var f=u.replace(K2,G2);_l[f]=new Hl(f,1,!1,u,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(u){var f=u.replace(K2,G2);_l[f]=new Hl(f,1,!1,u,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(u){var f=u.replace(K2,G2);_l[f]=new Hl(f,1,!1,u,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(u){_l[u]=new Hl(u,1,!1,u.toLowerCase(),null,!1,!1)});_l.xlinkHref=new Hl("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(u){_l[u]=new Hl(u,1,!1,u.toLowerCase(),null,!0,!0)});function z2(u,f,l,r){var n=_l.hasOwnProperty(f)?_l[f]:null;if(n!==null?n.type!==0:r||!(2{var FK=Object.create;var{getPrototypeOf:JK,defineProperty:N7,getOwnPropertyNames:UK}=Object;var QK=Object.prototype.hasOwnProperty;function qK(u){return this[u]}var NK,WK,Pu=(u,f,l)=>{var r=u!=null&&typeof u==="object";if(r){var n=f?NK??=new WeakMap:WK??=new WeakMap,i=n.get(u);if(i)return i}l=u!=null?FK(JK(u)):{};let y=f||!u||!u.__esModule?N7(l,"default",{value:u,enumerable:!0}):l;for(let _ of UK(u))if(!QK.call(y,_))N7(y,_,{get:qK.bind(u,_),enumerable:!0});if(r)n.set(u,y);return y};var nr=(u,f)=>()=>(f||u((f={exports:{}}).exports,f),f.exports);var du=((u)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(u,{get:(f,l)=>(typeof require<"u"?require:f)[l]}):u)(function(u){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+u+'" is not supported')});var B7=nr((su)=>{var Oy=Symbol.for("react.element"),LK=Symbol.for("react.portal"),wK=Symbol.for("react.fragment"),KK=Symbol.for("react.strict_mode"),GK=Symbol.for("react.profiler"),zK=Symbol.for("react.provider"),TK=Symbol.for("react.context"),EK=Symbol.for("react.forward_ref"),ZK=Symbol.for("react.suspense"),OK=Symbol.for("react.memo"),HK=Symbol.for("react.lazy"),W7=Symbol.iterator;function BK(u){if(u===null||typeof u!=="object")return null;return u=W7&&u[W7]||u["@@iterator"],typeof u==="function"?u:null}var K7={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},G7=Object.assign,z7={};function e1(u,f,l){this.props=u,this.context=f,this.refs=z7,this.updater=l||K7}e1.prototype.isReactComponent={};e1.prototype.setState=function(u,f){if(typeof u!=="object"&&typeof u!=="function"&&u!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,u,f,"setState")};e1.prototype.forceUpdate=function(u){this.updater.enqueueForceUpdate(this,u,"forceUpdate")};function T7(){}T7.prototype=e1.prototype;function v8(u,f,l){this.props=u,this.context=f,this.refs=z7,this.updater=l||K7}var k8=v8.prototype=new T7;k8.constructor=v8;G7(k8,e1.prototype);k8.isPureReactComponent=!0;var L7=Array.isArray,E7=Object.prototype.hasOwnProperty,I8={current:null},Z7={key:!0,ref:!0,__self:!0,__source:!0};function O7(u,f,l){var r,n={},i=null,y=null;if(f!=null)for(r in f.ref!==void 0&&(y=f.ref),f.key!==void 0&&(i=""+f.key),f)E7.call(f,r)&&!Z7.hasOwnProperty(r)&&(n[r]=f[r]);var _=arguments.length-2;if(_===1)n.children=l;else if(1<_){for(var $=Array(_),A=0;A<_;A++)$[A]=arguments[A+2];n.children=$}if(u&&u.defaultProps)for(r in _=u.defaultProps,_)n[r]===void 0&&(n[r]=_[r]);return{$$typeof:Oy,type:u,key:i,ref:y,props:n,_owner:I8.current}}function VK(u,f){return{$$typeof:Oy,type:u.type,key:f,ref:u.ref,props:u.props,_owner:u._owner}}function g8(u){return typeof u==="object"&&u!==null&&u.$$typeof===Oy}function DK(u){var f={"=":"=0",":":"=2"};return"$"+u.replace(/[=:]/g,function(l){return f[l]})}var w7=/\/+/g;function b8(u,f){return typeof u==="object"&&u!==null&&u.key!=null?DK(""+u.key):f.toString(36)}function n3(u,f,l,r,n){var i=typeof u;if(i==="undefined"||i==="boolean")u=null;var y=!1;if(u===null)y=!0;else switch(i){case"string":case"number":y=!0;break;case"object":switch(u.$$typeof){case Oy:case LK:y=!0}}if(y)return y=u,n=n(y),u=r===""?"."+b8(y,0):r,L7(n)?(l="",u!=null&&(l=u.replace(w7,"$&/")+"/"),n3(n,f,l,"",function(A){return A})):n!=null&&(g8(n)&&(n=VK(n,l+(!n.key||y&&y.key===n.key?"":(""+n.key).replace(w7,"$&/")+"/")+u)),f.push(n)),1;if(y=0,r=r===""?".":r+":",L7(u))for(var _=0;_{V7.exports=B7()});var R7=nr((Nf)=>{function d8(u,f){var l=u.length;u.push(f);u:for(;0>>1,n=u[r];if(0<_3(n,f))u[r]=f,u[l]=n,l=r;else break u}}function Xr(u){return u.length===0?null:u[0]}function c3(u){if(u.length===0)return null;var f=u[0],l=u.pop();if(l!==f){u[0]=l;u:for(var r=0,n=u.length,i=n>>>1;r_3(_,l))$_3(A,_)?(u[r]=A,u[$]=l,r=$):(u[r]=_,u[y]=l,r=y);else if($_3(A,l))u[r]=A,u[$]=l,r=$;else break u}}return f}function _3(u,f){var l=u.sortIndex-f.sortIndex;return l!==0?l:u.id-f.id}if(typeof performance==="object"&&typeof performance.now==="function")e8=performance,Nf.unstable_now=function(){return e8.now()};else $3=Date,u4=$3.now(),Nf.unstable_now=function(){return $3.now()-u4};var e8,$3,u4,or=[],g0=[],PK=1,Wr=null,Ql=3,j3=!1,on=!1,By=!1,p7=typeof setTimeout==="function"?setTimeout:null,m7=typeof clearTimeout==="function"?clearTimeout:null,S7=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function f4(u){for(var f=Xr(g0);f!==null;){if(f.callback===null)c3(g0);else if(f.startTime<=u)c3(g0),f.sortIndex=f.expirationTime,d8(or,f);else break;f=Xr(g0)}}function r4(u){if(By=!1,f4(u),!on)if(Xr(or)!==null)on=!0,i4(n4);else{var f=Xr(g0);f!==null&&y4(r4,f.startTime-u)}}function n4(u,f){on=!1,By&&(By=!1,m7(Vy),Vy=-1),j3=!0;var l=Ql;try{f4(f);for(Wr=Xr(or);Wr!==null&&(!(Wr.expirationTime>f)||u&&!C7());){var r=Wr.callback;if(typeof r==="function"){Wr.callback=null,Ql=Wr.priorityLevel;var n=r(Wr.expirationTime<=f);f=Nf.unstable_now(),typeof n==="function"?Wr.callback=n:Wr===Xr(or)&&c3(or),f4(f)}else c3(or);Wr=Xr(or)}if(Wr!==null)var i=!0;else{var y=Xr(g0);y!==null&&y4(r4,y.startTime-f),i=!1}return i}finally{Wr=null,Ql=l,j3=!1}}var F3=!1,t3=null,Vy=-1,P7=5,M7=-1;function C7(){return Nf.unstable_now()-M7u||125r?(u.sortIndex=l,d8(g0,u),Xr(or)===null&&u===Xr(g0)&&(By?(m7(Vy),Vy=-1):By=!0,y4(r4,l-r))):(u.sortIndex=n,d8(or,u),on||j3||(on=!0,i4(n4))),u};Nf.unstable_shouldYield=C7;Nf.unstable_wrapCallback=function(u){var f=Ql;return function(){var l=Ql;Ql=f;try{return u.apply(this,arguments)}finally{Ql=l}}}});var h7=nr((Ip,x7)=>{x7.exports=R7()});var vJ=nr((Ar)=>{var MK=qf(),$r=h7();function Uu(u){for(var f="https://reactjs.org/docs/error-decoder.html?invariant="+u,l=1;l"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),O4=Object.prototype.hasOwnProperty,CK=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,b7={},v7={};function RK(u){if(O4.call(v7,u))return!0;if(O4.call(b7,u))return!1;if(CK.test(u))return v7[u]=!0;return b7[u]=!0,!1}function xK(u,f,l,r){if(l!==null&&l.type===0)return!1;switch(typeof f){case"function":case"symbol":return!0;case"boolean":if(r)return!1;if(l!==null)return!l.acceptsBooleans;return u=u.toLowerCase().slice(0,5),u!=="data-"&&u!=="aria-";default:return!1}}function hK(u,f,l,r){if(f===null||typeof f>"u"||xK(u,f,l,r))return!0;if(r)return!1;if(l!==null)switch(l.type){case 3:return!f;case 4:return f===!1;case 5:return isNaN(f);case 6:return isNaN(f)||1>f}return!1}function Bl(u,f,l,r,n,i,y){this.acceptsBooleans=f===2||f===3||f===4,this.attributeName=r,this.attributeNamespace=n,this.mustUseProperty=l,this.propertyName=u,this.type=f,this.sanitizeURL=i,this.removeEmptyString=y}var Al={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(u){Al[u]=new Bl(u,0,!1,u,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(u){var f=u[0];Al[f]=new Bl(f,1,!1,u[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(u){Al[u]=new Bl(u,2,!1,u.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(u){Al[u]=new Bl(u,2,!1,u,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(u){Al[u]=new Bl(u,3,!1,u.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(u){Al[u]=new Bl(u,3,!0,u,null,!1,!1)});["capture","download"].forEach(function(u){Al[u]=new Bl(u,4,!1,u,null,!1,!1)});["cols","rows","size","span"].forEach(function(u){Al[u]=new Bl(u,6,!1,u,null,!1,!1)});["rowSpan","start"].forEach(function(u){Al[u]=new Bl(u,5,!1,u.toLowerCase(),null,!1,!1)});var K2=/[\-:]([a-z])/g;function G2(u){return u[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(u){var f=u.replace(K2,G2);Al[f]=new Bl(f,1,!1,u,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(u){var f=u.replace(K2,G2);Al[f]=new Bl(f,1,!1,u,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(u){var f=u.replace(K2,G2);Al[f]=new Bl(f,1,!1,u,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(u){Al[u]=new Bl(u,1,!1,u.toLowerCase(),null,!1,!1)});Al.xlinkHref=new Bl("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(u){Al[u]=new Bl(u,1,!1,u.toLowerCase(),null,!0,!0)});function z2(u,f,l,r){var n=Al.hasOwnProperty(f)?Al[f]:null;if(n!==null?n.type!==0:r||!(2_||n[y]!==i[_]){var $=` -`+n[y].replace(" at new "," at ");return u.displayName&&$.includes("")&&($=$.replace("",u.displayName)),$}while(1<=y&&0<=_);break}}}finally{$4=!1,Error.prepareStackTrace=l}return(u=u?u.displayName||u.name:"")?My(u):""}function pK(u){switch(u.tag){case 5:return My(u.type);case 16:return My("Lazy");case 13:return My("Suspense");case 19:return My("SuspenseList");case 0:case 2:case 15:return u=t4(u.type,!1),u;case 11:return u=t4(u.type.render,!1),u;case 1:return u=t4(u.type,!0),u;default:return""}}function D4(u){if(u==null)return null;if(typeof u==="function")return u.displayName||u.name||null;if(typeof u==="string")return u;switch(u){case ri:return"Fragment";case li:return"Portal";case H4:return"Profiler";case T2:return"StrictMode";case B4:return"Suspense";case V4:return"SuspenseList"}if(typeof u==="object")switch(u.$$typeof){case Ij:return(u.displayName||"Context")+".Consumer";case kj:return(u._context.displayName||"Context")+".Provider";case E2:var f=u.render;return u=u.displayName,u||(u=f.displayName||f.name||"",u=u!==""?"ForwardRef("+u+")":"ForwardRef"),u;case Z2:return f=u.displayName||null,f!==null?f:D4(u.type)||"Memo";case d0:f=u._payload,u=u._init;try{return D4(u(f))}catch(l){}}return null}function PK(u){var f=u.type;switch(u.tag){case 24:return"Cache";case 9:return(f.displayName||"Context")+".Consumer";case 10:return(f._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return u=f.render,u=u.displayName||u.name||"",f.displayName||(u!==""?"ForwardRef("+u+")":"ForwardRef");case 7:return"Fragment";case 5:return f;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return D4(f);case 8:return f===T2?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof f==="function")return f.displayName||f.name||null;if(typeof f==="string")return f}return null}function Fn(u){switch(typeof u){case"boolean":case"number":case"string":case"undefined":return u;case"object":return u;default:return""}}function sj(u){var f=u.type;return(u=u.nodeName)&&u.toLowerCase()==="input"&&(f==="checkbox"||f==="radio")}function MK(u){var f=sj(u)?"checked":"value",l=Object.getOwnPropertyDescriptor(u.constructor.prototype,f),r=""+u[f];if(!u.hasOwnProperty(f)&&typeof l<"u"&&typeof l.get==="function"&&typeof l.set==="function"){var{get:n,set:i}=l;return Object.defineProperty(u,f,{configurable:!0,get:function(){return n.call(this)},set:function(y){r=""+y,i.call(this,y)}}),Object.defineProperty(u,f,{enumerable:l.enumerable}),{getValue:function(){return r},setValue:function(y){r=""+y},stopTracking:function(){u._valueTracker=null,delete u[f]}}}}function Jt(u){u._valueTracker||(u._valueTracker=MK(u))}function aj(u){if(!u)return!1;var f=u._valueTracker;if(!f)return!0;var l=f.getValue(),r="";return u&&(r=sj(u)?u.checked?"true":"false":u.value),u=r,u!==l?(f.setValue(u),!0):!1}function Mt(u){if(u=u||(typeof document<"u"?document:void 0),typeof u>"u")return null;try{return u.activeElement||u.body}catch(f){return u.body}}function X4(u,f){var l=f.checked;return Of({},f,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:l!=null?l:u._wrapperState.initialChecked})}function b7(u,f){var l=f.defaultValue==null?"":f.defaultValue,r=f.checked!=null?f.checked:f.defaultChecked;l=Fn(f.value!=null?f.value:l),u._wrapperState={initialChecked:r,initialValue:l,controlled:f.type==="checkbox"||f.type==="radio"?f.checked!=null:f.value!=null}}function oj(u,f){f=f.checked,f!=null&&z2(u,"checked",f,!1)}function Y4(u,f){oj(u,f);var l=Fn(f.value),r=f.type;if(l!=null)if(r==="number"){if(l===0&&u.value===""||u.value!=l)u.value=""+l}else u.value!==""+l&&(u.value=""+l);else if(r==="submit"||r==="reset"){u.removeAttribute("value");return}f.hasOwnProperty("value")?S4(u,f.type,l):f.hasOwnProperty("defaultValue")&&S4(u,f.type,Fn(f.defaultValue)),f.checked==null&&f.defaultChecked!=null&&(u.defaultChecked=!!f.defaultChecked)}function v7(u,f,l){if(f.hasOwnProperty("value")||f.hasOwnProperty("defaultValue")){var r=f.type;if(!(r!=="submit"&&r!=="reset"||f.value!==void 0&&f.value!==null))return;f=""+u._wrapperState.initialValue,l||f===u.value||(u.value=f),u.defaultValue=f}l=u.name,l!==""&&(u.name=""),u.defaultChecked=!!u._wrapperState.initialChecked,l!==""&&(u.name=l)}function S4(u,f,l){if(f!=="number"||Mt(u.ownerDocument)!==u)l==null?u.defaultValue=""+u._wrapperState.initialValue:u.defaultValue!==""+l&&(u.defaultValue=""+l)}var Cy=Array.isArray;function Ji(u,f,l,r){if(u=u.options,f){f={};for(var n=0;n"+f.valueOf().toString()+"";for(f=Ut.firstChild;u.firstChild;)u.removeChild(u.firstChild);for(;f.firstChild;)u.appendChild(f.firstChild)}});function r_(u,f){if(f){var l=u.firstChild;if(l&&l===u.lastChild&&l.nodeType===3){l.nodeValue=f;return}}u.textContent=f}var Iy={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},CK=["Webkit","ms","Moz","O"];Object.keys(Iy).forEach(function(u){CK.forEach(function(f){f=f+u.charAt(0).toUpperCase()+u.substring(1),Iy[f]=Iy[u]})});function fF(u,f,l){return f==null||typeof f==="boolean"||f===""?"":l||typeof f!=="number"||f===0||Iy.hasOwnProperty(u)&&Iy[u]?(""+f).trim():f+"px"}function lF(u,f){u=u.style;for(var l in f)if(f.hasOwnProperty(l)){var r=l.indexOf("--")===0,n=fF(l,f[l],r);l==="float"&&(l="cssFloat"),r?u.setProperty(l,n):u[l]=n}}var RK=Of({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function P4(u,f){if(f){if(RK[u]&&(f.children!=null||f.dangerouslySetInnerHTML!=null))throw Error(Uu(137,u));if(f.dangerouslySetInnerHTML!=null){if(f.children!=null)throw Error(Uu(60));if(typeof f.dangerouslySetInnerHTML!=="object"||!("__html"in f.dangerouslySetInnerHTML))throw Error(Uu(61))}if(f.style!=null&&typeof f.style!=="object")throw Error(Uu(62))}}function M4(u,f){if(u.indexOf("-")===-1)return typeof f.is==="string";switch(u){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var C4=null;function O2(u){return u=u.target||u.srcElement||window,u.correspondingUseElement&&(u=u.correspondingUseElement),u.nodeType===3?u.parentNode:u}var R4=null,Ui=null,Qi=null;function g7(u){if(u=L_(u)){if(typeof R4!=="function")throw Error(Uu(280));var f=u.stateNode;f&&(f=F3(f),R4(u.stateNode,u.type,f))}}function rF(u){Ui?Qi?Qi.push(u):Qi=[u]:Ui=u}function nF(){if(Ui){var u=Ui,f=Qi;if(Qi=Ui=null,g7(u),f)for(u=0;u>>=0,u===0?32:31-(dK(u)/eK|0)|0}var Qt=64,qt=4194304;function Ry(u){switch(u&-u){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return u&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return u&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return u}}function ht(u,f){var l=u.pendingLanes;if(l===0)return 0;var r=0,n=u.suspendedLanes,i=u.pingedLanes,y=l&268435455;if(y!==0){var _=y&~n;_!==0?r=Ry(_):(i&=y,i!==0&&(r=Ry(i)))}else y=l&~n,y!==0?r=Ry(y):i!==0&&(r=Ry(i));if(r===0)return 0;if(f!==0&&f!==r&&(f&n)===0&&(n=r&-r,i=f&-f,n>=i||n===16&&(i&4194240)!==0))return f;if((r&4)!==0&&(r|=l&16),f=u.entangledLanes,f!==0)for(u=u.entanglements,f&=r;0l;l++)f.push(u);return f}function W_(u,f,l){u.pendingLanes|=f,f!==536870912&&(u.suspendedLanes=0,u.pingedLanes=0),u=u.eventTimes,f=31-mr(f),u[f]=l}function rG(u,f){var l=u.pendingLanes&~f;u.pendingLanes=f,u.suspendedLanes=0,u.pingedLanes=0,u.expiredLanes&=f,u.mutableReadLanes&=f,u.entangledLanes&=f,f=u.entanglements;var r=u.eventTimes;for(u=u.expirationTimes;0=sy),rj=String.fromCharCode(32),nj=!1;function zF(u,f){switch(u){case"keyup":return VG.indexOf(f.keyCode)!==-1;case"keydown":return f.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function TF(u){return u=u.detail,typeof u==="object"&&"data"in u?u.data:null}var ni=!1;function XG(u,f){switch(u){case"compositionend":return TF(f);case"keypress":if(f.which!==32)return null;return nj=!0,rj;case"textInput":return u=f.data,u===rj&&nj?null:u;default:return null}}function YG(u,f){if(ni)return u==="compositionend"||!m2&&zF(u,f)?(u=KF(),Ht=X2=ln=null,ni=!1,u):null;switch(u){case"paste":return null;case"keypress":if(!(f.ctrlKey||f.altKey||f.metaKey)||f.ctrlKey&&f.altKey){if(f.char&&1=f)return{node:l,offset:f-u};u=r}u:{for(;l;){if(l.nextSibling){l=l.nextSibling;break u}l=l.parentNode}l=void 0}l=_j(l)}}function HF(u,f){return u&&f?u===f?!0:u&&u.nodeType===3?!1:f&&f.nodeType===3?HF(u,f.parentNode):("contains"in u)?u.contains(f):u.compareDocumentPosition?!!(u.compareDocumentPosition(f)&16):!1:!1}function BF(){for(var u=window,f=Mt();f instanceof u.HTMLIFrameElement;){try{var l=typeof f.contentWindow.location.href==="string"}catch(r){l=!1}if(l)u=f.contentWindow;else break;f=Mt(u.document)}return f}function p2(u){var f=u&&u.nodeName&&u.nodeName.toLowerCase();return f&&(f==="input"&&(u.type==="text"||u.type==="search"||u.type==="tel"||u.type==="url"||u.type==="password")||f==="textarea"||u.contentEditable==="true")}function hG(u){var f=BF(),l=u.focusedElem,r=u.selectionRange;if(f!==l&&l&&l.ownerDocument&&HF(l.ownerDocument.documentElement,l)){if(r!==null&&p2(l)){if(f=r.start,u=r.end,u===void 0&&(u=f),"selectionStart"in l)l.selectionStart=f,l.selectionEnd=Math.min(u,l.value.length);else if(u=(f=l.ownerDocument||document)&&f.defaultView||window,u.getSelection){u=u.getSelection();var n=l.textContent.length,i=Math.min(r.start,n);r=r.end===void 0?i:Math.min(r.end,n),!u.extend&&i>r&&(n=r,r=i,i=n),n=$j(l,i);var y=$j(l,r);n&&y&&(u.rangeCount!==1||u.anchorNode!==n.node||u.anchorOffset!==n.offset||u.focusNode!==y.node||u.focusOffset!==y.offset)&&(f=f.createRange(),f.setStart(n.node,n.offset),u.removeAllRanges(),i>r?(u.addRange(f),u.extend(y.node,y.offset)):(f.setEnd(y.node,y.offset),u.addRange(f)))}}f=[];for(u=l;u=u.parentNode;)u.nodeType===1&&f.push({element:u,left:u.scrollLeft,top:u.scrollTop});typeof l.focus==="function"&&l.focus();for(l=0;l=document.documentMode,ii=null,I4=null,oy=null,g4=!1;function tj(u,f,l){var r=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;g4||ii==null||ii!==Mt(r)||(r=ii,("selectionStart"in r)&&p2(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),oy&&t_(oy,r)||(oy=r,r=kt(I4,"onSelect"),0$i||(u.current=l2[$i],l2[$i]=null,$i--)}function Nf(u,f){$i++,l2[$i]=u.current,u.current=f}var Jn={},ql=Qn(Jn),Ml=Qn(!1),$1=Jn;function Li(u,f){var l=u.type.contextTypes;if(!l)return Jn;var r=u.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===f)return r.__reactInternalMemoizedMaskedChildContext;var n={},i;for(i in l)n[i]=f[i];return r&&(u=u.stateNode,u.__reactInternalMemoizedUnmaskedChildContext=f,u.__reactInternalMemoizedMaskedChildContext=n),n}function Cl(u){return u=u.childContextTypes,u!==null&&u!==void 0}function gt(){Lf(Ml),Lf(ql)}function Qj(u,f,l){if(ql.current!==Jn)throw Error(Uu(168));Nf(ql,f),Nf(Ml,l)}function MF(u,f,l){var r=u.stateNode;if(f=f.childContextTypes,typeof r.getChildContext!=="function")return l;r=r.getChildContext();for(var n in r)if(!(n in f))throw Error(Uu(108,PK(u)||"Unknown",n));return Of({},l,r)}function st(u){return u=(u=u.stateNode)&&u.__reactInternalMemoizedMergedChildContext||Jn,$1=ql.current,Nf(ql,u),Nf(Ml,Ml.current),!0}function qj(u,f,l){var r=u.stateNode;if(!r)throw Error(Uu(169));l?(u=MF(u,f,$1),r.__reactInternalMemoizedMergedChildContext=u,Lf(Ml),Lf(ql),Nf(ql,u)):Lf(Ml),Nf(Ml,l)}var w0=null,J3=!1,W4=!1;function CF(u){w0===null?w0=[u]:w0.push(u)}function eG(u){J3=!0,CF(u)}function qn(){if(!W4&&w0!==null){W4=!0;var u=0,f=tf;try{var l=w0;for(tf=1;u>=y,n-=y,L0=1<<32-mr(f)+n|l<E?(D=H,H=null):D=H.sibling;var h=F(J,H,q[E],W);if(h===null){H===null&&(H=D);break}u&&H&&h.alternate===null&&f(J,H),N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h,H=D}if(E===q.length)return l(J,H),zf&&f1(J,E),z;if(H===null){for(;EE?(D=H,H=null):D=H.sibling;var B=F(J,H,h.value,W);if(B===null){H===null&&(H=D);break}u&&H&&B.alternate===null&&f(J,H),N=i(B,N,E),Z===null?z=B:Z.sibling=B,Z=B,H=D}if(h.done)return l(J,H),zf&&f1(J,E),z;if(H===null){for(;!h.done;E++,h=q.next())h=j(J,h.value,W),h!==null&&(N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h);return zf&&f1(J,E),z}for(H=r(J,H);!h.done;E++,h=q.next())h=U(H,J,E,h.value,W),h!==null&&(u&&h.alternate!==null&&H.delete(h.key===null?E:h.key),N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h);return u&&H.forEach(function(X){return f(J,X)}),zf&&f1(J,E),z}function L(J,N,q,W){if(typeof q==="object"&&q!==null&&q.type===ri&&q.key===null&&(q=q.props.children),typeof q==="object"&&q!==null){switch(q.$$typeof){case Ft:u:{for(var z=q.key,Z=N;Z!==null;){if(Z.key===z){if(z=q.type,z===ri){if(Z.tag===7){l(J,Z.sibling),N=n(Z,q.props.children),N.return=J,J=N;break u}}else if(Z.elementType===z||typeof z==="object"&&z!==null&&z.$$typeof===d0&&wj(z)===Z.type){l(J,Z.sibling),N=n(Z,q.props),N.ref=my(J,Z,q),N.return=J,J=N;break u}l(J,Z);break}else f(J,Z);Z=Z.sibling}q.type===ri?(N=_1(q.props.children,J.mode,W,q.key),N.return=J,J=N):(W=Pt(q.type,q.key,q.props,null,J.mode,W),W.ref=my(J,N,q),W.return=J,J=W)}return y(J);case li:u:{for(Z=q.key;N!==null;){if(N.key===Z)if(N.tag===4&&N.stateNode.containerInfo===q.containerInfo&&N.stateNode.implementation===q.implementation){l(J,N.sibling),N=n(N,q.children||[]),N.return=J,J=N;break u}else{l(J,N);break}else f(J,N);N=N.sibling}N=Z4(q,J.mode,W),N.return=J,J=N}return y(J);case d0:return Z=q._init,L(J,N,Z(q._payload),W)}if(Cy(q))return Q(J,N,q,W);if(Dy(q))return w(J,N,q,W);zt(J,q)}return typeof q==="string"&&q!==""||typeof q==="number"?(q=""+q,N!==null&&N.tag===6?(l(J,N.sibling),N=n(N,q),N.return=J,J=N):(l(J,N),N=E4(q,J.mode,W),N.return=J,J=N),y(J)):l(J,N)}return L}var Gi=bF(!0),vF=bF(!1),dt=Qn(null),et=null,Ai=null,R2=null;function x2(){R2=Ai=et=null}function h2(u){var f=dt.current;Lf(dt),u._currentValue=f}function i2(u,f,l){for(;u!==null;){var r=u.alternate;if((u.childLanes&f)!==f?(u.childLanes|=f,r!==null&&(r.childLanes|=f)):r!==null&&(r.childLanes&f)!==f&&(r.childLanes|=f),u===l)break;u=u.return}}function Ni(u,f){et=u,R2=Ai=null,u=u.dependencies,u!==null&&u.firstContext!==null&&((u.lanes&f)!==0&&(Pl=!0),u.firstContext=null)}function Lr(u){var f=u._currentValue;if(R2!==u)if(u={context:u,memoizedValue:f,next:null},Ai===null){if(et===null)throw Error(Uu(308));Ai=u,et.dependencies={lanes:0,firstContext:u}}else Ai=Ai.next=u;return f}var n1=null;function b2(u){n1===null?n1=[u]:n1.push(u)}function kF(u,f,l,r){var n=f.interleaved;return n===null?(l.next=l,b2(f)):(l.next=n.next,n.next=l),f.interleaved=l,E0(u,r)}function E0(u,f){u.lanes|=f;var l=u.alternate;l!==null&&(l.lanes|=f),l=u;for(u=u.return;u!==null;)u.childLanes|=f,l=u.alternate,l!==null&&(l.childLanes|=f),l=u,u=u.return;return l.tag===3?l.stateNode:null}var e0=!1;function v2(u){u.updateQueue={baseState:u.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function IF(u,f){u=u.updateQueue,f.updateQueue===u&&(f.updateQueue={baseState:u.baseState,firstBaseUpdate:u.firstBaseUpdate,lastBaseUpdate:u.lastBaseUpdate,shared:u.shared,effects:u.effects})}function G0(u,f){return{eventTime:u,lane:f,tag:0,payload:null,callback:null,next:null}}function tn(u,f,l){var r=u.updateQueue;if(r===null)return null;if(r=r.shared,(lf&2)!==0){var n=r.pending;return n===null?f.next=f:(f.next=n.next,n.next=f),r.pending=f,E0(u,l)}return n=r.interleaved,n===null?(f.next=f,b2(r)):(f.next=n.next,n.next=f),r.interleaved=f,E0(u,l)}function Dt(u,f,l){if(f=f.updateQueue,f!==null&&(f=f.shared,(l&4194240)!==0)){var r=f.lanes;r&=u.pendingLanes,l|=r,f.lanes=l,B2(u,l)}}function Lj(u,f){var{updateQueue:l,alternate:r}=u;if(r!==null&&(r=r.updateQueue,l===r)){var n=null,i=null;if(l=l.firstBaseUpdate,l!==null){do{var y={eventTime:l.eventTime,lane:l.lane,tag:l.tag,payload:l.payload,callback:l.callback,next:null};i===null?n=i=y:i=i.next=y,l=l.next}while(l!==null);i===null?n=i=f:i=i.next=f}else n=i=f;l={baseState:r.baseState,firstBaseUpdate:n,lastBaseUpdate:i,shared:r.shared,effects:r.effects},u.updateQueue=l;return}u=l.lastBaseUpdate,u===null?l.firstBaseUpdate=f:u.next=f,l.lastBaseUpdate=f}function u3(u,f,l,r){var n=u.updateQueue;e0=!1;var{firstBaseUpdate:i,lastBaseUpdate:y}=n,_=n.shared.pending;if(_!==null){n.shared.pending=null;var $=_,c=$.next;$.next=null,y===null?i=c:y.next=c,y=$;var A=u.alternate;A!==null&&(A=A.updateQueue,_=A.lastBaseUpdate,_!==y&&(_===null?A.firstBaseUpdate=c:_.next=c,A.lastBaseUpdate=$))}if(i!==null){var j=n.baseState;y=0,A=c=$=null,_=i;do{var{lane:F,eventTime:U}=_;if((r&F)===F){A!==null&&(A=A.next={eventTime:U,lane:0,tag:_.tag,payload:_.payload,callback:_.callback,next:null});u:{var Q=u,w=_;switch(F=f,U=l,w.tag){case 1:if(Q=w.payload,typeof Q==="function"){j=Q.call(U,j,F);break u}j=Q;break u;case 3:Q.flags=Q.flags&-65537|128;case 0:if(Q=w.payload,F=typeof Q==="function"?Q.call(U,j,F):Q,F===null||F===void 0)break u;j=Of({},j,F);break u;case 2:e0=!0}}_.callback!==null&&_.lane!==0&&(u.flags|=64,F=n.effects,F===null?n.effects=[_]:F.push(_))}else U={eventTime:U,lane:F,tag:_.tag,payload:_.payload,callback:_.callback,next:null},A===null?(c=A=U,$=j):A=A.next=U,y|=F;if(_=_.next,_===null)if(_=n.shared.pending,_===null)break;else F=_,_=F.next,F.next=null,n.lastBaseUpdate=F,n.shared.pending=null}while(1);if(A===null&&($=j),n.baseState=$,n.firstBaseUpdate=c,n.lastBaseUpdate=A,f=n.shared.interleaved,f!==null){n=f;do y|=n.lane,n=n.next;while(n!==f)}else i===null&&(n.shared.lanes=0);A1|=y,u.lanes=y,u.memoizedState=j}}function Kj(u,f,l){if(u=f.effects,f.effects=null,u!==null)for(f=0;fl?l:4,u(!0);var r=L4.transition;L4.transition={};try{u(!1),f()}finally{tf=l,L4.transition=r}}function cJ(){return Kr().memoizedState}function rz(u,f,l){var r=An(u);if(l={lane:r,action:l,hasEagerState:!1,eagerState:null,next:null},AJ(u))jJ(f,l);else if(l=kF(u,f,l,r),l!==null){var n=Ol();pr(l,u,r,n),FJ(l,f,r)}}function nz(u,f,l){var r=An(u),n={lane:r,action:l,hasEagerState:!1,eagerState:null,next:null};if(AJ(u))jJ(f,n);else{var i=u.alternate;if(u.lanes===0&&(i===null||i.lanes===0)&&(i=f.lastRenderedReducer,i!==null))try{var y=f.lastRenderedState,_=i(y,l);if(n.hasEagerState=!0,n.eagerState=_,Pr(_,y)){var $=f.interleaved;$===null?(n.next=n,b2(f)):(n.next=$.next,$.next=n),f.interleaved=n;return}}catch(c){}finally{}l=kF(u,f,n,r),l!==null&&(n=Ol(),pr(l,u,r,n),FJ(l,f,r))}}function AJ(u){var f=u.alternate;return u===Zf||f!==null&&f===Zf}function jJ(u,f){dy=l3=!0;var l=u.pending;l===null?f.next=f:(f.next=l.next,l.next=f),u.pending=f}function FJ(u,f,l){if((l&4194240)!==0){var r=f.lanes;r&=u.pendingLanes,l|=r,f.lanes=l,B2(u,l)}}var r3={readContext:Lr,useCallback:Jl,useContext:Jl,useEffect:Jl,useImperativeHandle:Jl,useInsertionEffect:Jl,useLayoutEffect:Jl,useMemo:Jl,useReducer:Jl,useRef:Jl,useState:Jl,useDebugValue:Jl,useDeferredValue:Jl,useTransition:Jl,useMutableSource:Jl,useSyncExternalStore:Jl,useId:Jl,unstable_isNewReconciler:!1},iz={readContext:Lr,useCallback:function(u,f){return dr().memoizedState=[u,f===void 0?null:f],u},useContext:Lr,useEffect:zj,useImperativeHandle:function(u,f,l){return l=l!==null&&l!==void 0?l.concat([u]):null,Yt(4194308,4,iJ.bind(null,f,u),l)},useLayoutEffect:function(u,f){return Yt(4194308,4,u,f)},useInsertionEffect:function(u,f){return Yt(4,2,u,f)},useMemo:function(u,f){var l=dr();return f=f===void 0?null:f,u=u(),l.memoizedState=[u,f],u},useReducer:function(u,f,l){var r=dr();return f=l!==void 0?l(f):f,r.memoizedState=r.baseState=f,u={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:u,lastRenderedState:f},r.queue=u,u=u.dispatch=rz.bind(null,Zf,u),[r.memoizedState,u]},useRef:function(u){var f=dr();return u={current:u},f.memoizedState=u},useState:Gj,useDebugValue:e2,useDeferredValue:function(u){return dr().memoizedState=u},useTransition:function(){var u=Gj(!1),f=u[0];return u=lz.bind(null,u[1]),dr().memoizedState=u,[f,u]},useMutableSource:function(){},useSyncExternalStore:function(u,f,l){var r=Zf,n=dr();if(zf){if(l===void 0)throw Error(Uu(407));l=l()}else{if(l=f(),fl===null)throw Error(Uu(349));(c1&30)!==0||oF(r,f,l)}n.memoizedState=l;var i={value:l,getSnapshot:f};return n.queue=i,zj(eF.bind(null,r,i,u),[u]),r.flags|=2048,q_(9,dF.bind(null,r,i,l,f),void 0,null),l},useId:function(){var u=dr(),f=fl.identifierPrefix;if(zf){var l=K0,r=L0;l=(r&~(1<<32-mr(r)-1)).toString(32)+l,f=":"+f+"R"+l,l=U_++,0")&&($=$.replace("",u.displayName)),$}while(1<=y&&0<=_);break}}}finally{$4=!1,Error.prepareStackTrace=l}return(u=u?u.displayName||u.name:"")?My(u):""}function bK(u){switch(u.tag){case 5:return My(u.type);case 16:return My("Lazy");case 13:return My("Suspense");case 19:return My("SuspenseList");case 0:case 2:case 15:return u=t4(u.type,!1),u;case 11:return u=t4(u.type.render,!1),u;case 1:return u=t4(u.type,!0),u;default:return""}}function D4(u){if(u==null)return null;if(typeof u==="function")return u.displayName||u.name||null;if(typeof u==="string")return u;switch(u){case ri:return"Fragment";case li:return"Portal";case H4:return"Profiler";case T2:return"StrictMode";case B4:return"Suspense";case V4:return"SuspenseList"}if(typeof u==="object")switch(u.$$typeof){case aj:return(u.displayName||"Context")+".Consumer";case sj:return(u._context.displayName||"Context")+".Provider";case E2:var f=u.render;return u=u.displayName,u||(u=f.displayName||f.name||"",u=u!==""?"ForwardRef("+u+")":"ForwardRef"),u;case Z2:return f=u.displayName||null,f!==null?f:D4(u.type)||"Memo";case a0:f=u._payload,u=u._init;try{return D4(u(f))}catch(l){}}return null}function vK(u){var f=u.type;switch(u.tag){case 24:return"Cache";case 9:return(f.displayName||"Context")+".Consumer";case 10:return(f._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return u=f.render,u=u.displayName||u.name||"",f.displayName||(u!==""?"ForwardRef("+u+")":"ForwardRef");case 7:return"Fragment";case 5:return f;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return D4(f);case 8:return f===T2?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof f==="function")return f.displayName||f.name||null;if(typeof f==="string")return f}return null}function cn(u){switch(typeof u){case"boolean":case"number":case"string":case"undefined":return u;case"object":return u;default:return""}}function dj(u){var f=u.type;return(u=u.nodeName)&&u.toLowerCase()==="input"&&(f==="checkbox"||f==="radio")}function kK(u){var f=dj(u)?"checked":"value",l=Object.getOwnPropertyDescriptor(u.constructor.prototype,f),r=""+u[f];if(!u.hasOwnProperty(f)&&typeof l<"u"&&typeof l.get==="function"&&typeof l.set==="function"){var{get:n,set:i}=l;return Object.defineProperty(u,f,{configurable:!0,get:function(){return n.call(this)},set:function(y){r=""+y,i.call(this,y)}}),Object.defineProperty(u,f,{enumerable:l.enumerable}),{getValue:function(){return r},setValue:function(y){r=""+y},stopTracking:function(){u._valueTracker=null,delete u[f]}}}}function U3(u){u._valueTracker||(u._valueTracker=kK(u))}function ej(u){if(!u)return!1;var f=u._valueTracker;if(!f)return!0;var l=f.getValue(),r="";return u&&(r=dj(u)?u.checked?"true":"false":u.value),u=r,u!==l?(f.setValue(u),!0):!1}function C3(u){if(u=u||(typeof document<"u"?document:void 0),typeof u>"u")return null;try{return u.activeElement||u.body}catch(f){return u.body}}function X4(u,f){var l=f.checked;return Bf({},f,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:l!=null?l:u._wrapperState.initialChecked})}function I7(u,f){var l=f.defaultValue==null?"":f.defaultValue,r=f.checked!=null?f.checked:f.defaultChecked;l=cn(f.value!=null?f.value:l),u._wrapperState={initialChecked:r,initialValue:l,controlled:f.type==="checkbox"||f.type==="radio"?f.checked!=null:f.value!=null}}function uF(u,f){f=f.checked,f!=null&&z2(u,"checked",f,!1)}function Y4(u,f){uF(u,f);var l=cn(f.value),r=f.type;if(l!=null)if(r==="number"){if(l===0&&u.value===""||u.value!=l)u.value=""+l}else u.value!==""+l&&(u.value=""+l);else if(r==="submit"||r==="reset"){u.removeAttribute("value");return}f.hasOwnProperty("value")?S4(u,f.type,l):f.hasOwnProperty("defaultValue")&&S4(u,f.type,cn(f.defaultValue)),f.checked==null&&f.defaultChecked!=null&&(u.defaultChecked=!!f.defaultChecked)}function g7(u,f,l){if(f.hasOwnProperty("value")||f.hasOwnProperty("defaultValue")){var r=f.type;if(!(r!=="submit"&&r!=="reset"||f.value!==void 0&&f.value!==null))return;f=""+u._wrapperState.initialValue,l||f===u.value||(u.value=f),u.defaultValue=f}l=u.name,l!==""&&(u.name=""),u.defaultChecked=!!u._wrapperState.initialChecked,l!==""&&(u.name=l)}function S4(u,f,l){if(f!=="number"||C3(u.ownerDocument)!==u)l==null?u.defaultValue=""+u._wrapperState.initialValue:u.defaultValue!==""+l&&(u.defaultValue=""+l)}var Cy=Array.isArray;function Ji(u,f,l,r){if(u=u.options,f){f={};for(var n=0;n"+f.valueOf().toString()+"";for(f=Q3.firstChild;u.firstChild;)u.removeChild(u.firstChild);for(;f.firstChild;)u.appendChild(f.firstChild)}});function r_(u,f){if(f){var l=u.firstChild;if(l&&l===u.lastChild&&l.nodeType===3){l.nodeValue=f;return}}u.textContent=f}var Iy={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},IK=["Webkit","ms","Moz","O"];Object.keys(Iy).forEach(function(u){IK.forEach(function(f){f=f+u.charAt(0).toUpperCase()+u.substring(1),Iy[f]=Iy[u]})});function nF(u,f,l){return f==null||typeof f==="boolean"||f===""?"":l||typeof f!=="number"||f===0||Iy.hasOwnProperty(u)&&Iy[u]?(""+f).trim():f+"px"}function iF(u,f){u=u.style;for(var l in f)if(f.hasOwnProperty(l)){var r=l.indexOf("--")===0,n=nF(l,f[l],r);l==="float"&&(l="cssFloat"),r?u.setProperty(l,n):u[l]=n}}var gK=Bf({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function P4(u,f){if(f){if(gK[u]&&(f.children!=null||f.dangerouslySetInnerHTML!=null))throw Error(Uu(137,u));if(f.dangerouslySetInnerHTML!=null){if(f.children!=null)throw Error(Uu(60));if(typeof f.dangerouslySetInnerHTML!=="object"||!("__html"in f.dangerouslySetInnerHTML))throw Error(Uu(61))}if(f.style!=null&&typeof f.style!=="object")throw Error(Uu(62))}}function M4(u,f){if(u.indexOf("-")===-1)return typeof f.is==="string";switch(u){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var C4=null;function O2(u){return u=u.target||u.srcElement||window,u.correspondingUseElement&&(u=u.correspondingUseElement),u.nodeType===3?u.parentNode:u}var R4=null,Ui=null,Qi=null;function o7(u){if(u=w_(u)){if(typeof R4!=="function")throw Error(Uu(280));var f=u.stateNode;f&&(f=Jt(f),R4(u.stateNode,u.type,f))}}function yF(u){Ui?Qi?Qi.push(u):Qi=[u]:Ui=u}function _F(){if(Ui){var u=Ui,f=Qi;if(Qi=Ui=null,o7(u),f)for(u=0;u>>=0,u===0?32:31-(iG(u)/yG|0)|0}var q3=64,N3=4194304;function Ry(u){switch(u&-u){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return u&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return u&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return u}}function b3(u,f){var l=u.pendingLanes;if(l===0)return 0;var r=0,n=u.suspendedLanes,i=u.pingedLanes,y=l&268435455;if(y!==0){var _=y&~n;_!==0?r=Ry(_):(i&=y,i!==0&&(r=Ry(i)))}else y=l&~n,y!==0?r=Ry(y):i!==0&&(r=Ry(i));if(r===0)return 0;if(f!==0&&f!==r&&(f&n)===0&&(n=r&-r,i=f&-f,n>=i||n===16&&(i&4194240)!==0))return f;if((r&4)!==0&&(r|=l&16),f=u.entangledLanes,f!==0)for(u=u.entanglements,f&=r;0l;l++)f.push(u);return f}function W_(u,f,l){u.pendingLanes|=f,f!==536870912&&(u.suspendedLanes=0,u.pingedLanes=0),u=u.eventTimes,f=31-Pr(f),u[f]=l}function AG(u,f){var l=u.pendingLanes&~f;u.pendingLanes=f,u.suspendedLanes=0,u.pingedLanes=0,u.expiredLanes&=f,u.mutableReadLanes&=f,u.entangledLanes&=f,f=u.entanglements;var r=u.eventTimes;for(u=u.expirationTimes;0=sy),yj=String.fromCharCode(32),_j=!1;function ZF(u,f){switch(u){case"keyup":return PG.indexOf(f.keyCode)!==-1;case"keydown":return f.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function OF(u){return u=u.detail,typeof u==="object"&&"data"in u?u.data:null}var ni=!1;function CG(u,f){switch(u){case"compositionend":return OF(f);case"keypress":if(f.which!==32)return null;return _j=!0,yj;case"textInput":return u=f.data,u===yj&&_j?null:u;default:return null}}function RG(u,f){if(ni)return u==="compositionend"||!p2&&ZF(u,f)?(u=TF(),B3=X2=un=null,ni=!1,u):null;switch(u){case"paste":return null;case"keypress":if(!(f.ctrlKey||f.altKey||f.metaKey)||f.ctrlKey&&f.altKey){if(f.char&&1=f)return{node:l,offset:f-u};u=r}u:{for(;l;){if(l.nextSibling){l=l.nextSibling;break u}l=l.parentNode}l=void 0}l=Aj(l)}}function DF(u,f){return u&&f?u===f?!0:u&&u.nodeType===3?!1:f&&f.nodeType===3?DF(u,f.parentNode):("contains"in u)?u.contains(f):u.compareDocumentPosition?!!(u.compareDocumentPosition(f)&16):!1:!1}function XF(){for(var u=window,f=C3();f instanceof u.HTMLIFrameElement;){try{var l=typeof f.contentWindow.location.href==="string"}catch(r){l=!1}if(l)u=f.contentWindow;else break;f=C3(u.document)}return f}function m2(u){var f=u&&u.nodeName&&u.nodeName.toLowerCase();return f&&(f==="input"&&(u.type==="text"||u.type==="search"||u.type==="tel"||u.type==="url"||u.type==="password")||f==="textarea"||u.contentEditable==="true")}function aG(u){var f=XF(),l=u.focusedElem,r=u.selectionRange;if(f!==l&&l&&l.ownerDocument&&DF(l.ownerDocument.documentElement,l)){if(r!==null&&m2(l)){if(f=r.start,u=r.end,u===void 0&&(u=f),"selectionStart"in l)l.selectionStart=f,l.selectionEnd=Math.min(u,l.value.length);else if(u=(f=l.ownerDocument||document)&&f.defaultView||window,u.getSelection){u=u.getSelection();var n=l.textContent.length,i=Math.min(r.start,n);r=r.end===void 0?i:Math.min(r.end,n),!u.extend&&i>r&&(n=r,r=i,i=n),n=cj(l,i);var y=cj(l,r);n&&y&&(u.rangeCount!==1||u.anchorNode!==n.node||u.anchorOffset!==n.offset||u.focusNode!==y.node||u.focusOffset!==y.offset)&&(f=f.createRange(),f.setStart(n.node,n.offset),u.removeAllRanges(),i>r?(u.addRange(f),u.extend(y.node,y.offset)):(f.setEnd(y.node,y.offset),u.addRange(f)))}}f=[];for(u=l;u=u.parentNode;)u.nodeType===1&&f.push({element:u,left:u.scrollLeft,top:u.scrollTop});typeof l.focus==="function"&&l.focus();for(l=0;l=document.documentMode,ii=null,I4=null,oy=null,g4=!1;function jj(u,f,l){var r=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;g4||ii==null||ii!==C3(r)||(r=ii,("selectionStart"in r)&&m2(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),oy&&t_(oy,r)||(oy=r,r=I3(I4,"onSelect"),0$i||(u.current=l2[$i],l2[$i]=null,$i--)}function Wf(u,f){$i++,l2[$i]=u.current,u.current=f}var jn={},Ll=Jn(jn),Rl=Jn(!1),y1=jn;function wi(u,f){var l=u.type.contextTypes;if(!l)return jn;var r=u.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===f)return r.__reactInternalMemoizedMaskedChildContext;var n={},i;for(i in l)n[i]=f[i];return r&&(u=u.stateNode,u.__reactInternalMemoizedUnmaskedChildContext=f,u.__reactInternalMemoizedMaskedChildContext=n),n}function xl(u){return u=u.childContextTypes,u!==null&&u!==void 0}function s3(){Gf(Rl),Gf(Ll)}function Wj(u,f,l){if(Ll.current!==jn)throw Error(Uu(168));Wf(Ll,f),Wf(Rl,l)}function xF(u,f,l){var r=u.stateNode;if(f=f.childContextTypes,typeof r.getChildContext!=="function")return l;r=r.getChildContext();for(var n in r)if(!(n in f))throw Error(Uu(108,vK(u)||"Unknown",n));return Bf({},l,r)}function a3(u){return u=(u=u.stateNode)&&u.__reactInternalMemoizedMergedChildContext||jn,y1=Ll.current,Wf(Ll,u),Wf(Rl,Rl.current),!0}function Lj(u,f,l){var r=u.stateNode;if(!r)throw Error(Uu(169));l?(u=xF(u,f,y1),r.__reactInternalMemoizedMergedChildContext=u,Gf(Rl),Gf(Ll),Wf(Ll,u)):Gf(Rl),Wf(Rl,l)}var L0=null,Ut=!1,W4=!1;function hF(u){L0===null?L0=[u]:L0.push(u)}function yz(u){Ut=!0,hF(u)}function Un(){if(!W4&&L0!==null){W4=!0;var u=0,f=Af;try{var l=L0;for(Af=1;u>=y,n-=y,w0=1<<32-Pr(f)+n|l<E?(D=H,H=null):D=H.sibling;var h=F(J,H,q[E],W);if(h===null){H===null&&(H=D);break}u&&H&&h.alternate===null&&f(J,H),N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h,H=D}if(E===q.length)return l(J,H),Ef&&en(J,E),z;if(H===null){for(;EE?(D=H,H=null):D=H.sibling;var V=F(J,H,h.value,W);if(V===null){H===null&&(H=D);break}u&&H&&V.alternate===null&&f(J,H),N=i(V,N,E),Z===null?z=V:Z.sibling=V,Z=V,H=D}if(h.done)return l(J,H),Ef&&en(J,E),z;if(H===null){for(;!h.done;E++,h=q.next())h=j(J,h.value,W),h!==null&&(N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h);return Ef&&en(J,E),z}for(H=r(J,H);!h.done;E++,h=q.next())h=U(H,J,E,h.value,W),h!==null&&(u&&h.alternate!==null&&H.delete(h.key===null?E:h.key),N=i(h,N,E),Z===null?z=h:Z.sibling=h,Z=h);return u&&H.forEach(function(Y){return f(J,Y)}),Ef&&en(J,E),z}function w(J,N,q,W){if(typeof q==="object"&&q!==null&&q.type===ri&&q.key===null&&(q=q.props.children),typeof q==="object"&&q!==null){switch(q.$$typeof){case J3:u:{for(var z=q.key,Z=N;Z!==null;){if(Z.key===z){if(z=q.type,z===ri){if(Z.tag===7){l(J,Z.sibling),N=n(Z,q.props.children),N.return=J,J=N;break u}}else if(Z.elementType===z||typeof z==="object"&&z!==null&&z.$$typeof===a0&&Gj(z)===Z.type){l(J,Z.sibling),N=n(Z,q.props),N.ref=py(J,Z,q),N.return=J,J=N;break u}l(J,Z);break}else f(J,Z);Z=Z.sibling}q.type===ri?(N=i1(q.props.children,J.mode,W,q.key),N.return=J,J=N):(W=M3(q.type,q.key,q.props,null,J.mode,W),W.ref=py(J,N,q),W.return=J,J=W)}return y(J);case li:u:{for(Z=q.key;N!==null;){if(N.key===Z)if(N.tag===4&&N.stateNode.containerInfo===q.containerInfo&&N.stateNode.implementation===q.implementation){l(J,N.sibling),N=n(N,q.children||[]),N.return=J,J=N;break u}else{l(J,N);break}else f(J,N);N=N.sibling}N=Z4(q,J.mode,W),N.return=J,J=N}return y(J);case a0:return Z=q._init,w(J,N,Z(q._payload),W)}if(Cy(q))return Q(J,N,q,W);if(Dy(q))return L(J,N,q,W);T3(J,q)}return typeof q==="string"&&q!==""||typeof q==="number"?(q=""+q,N!==null&&N.tag===6?(l(J,N.sibling),N=n(N,q),N.return=J,J=N):(l(J,N),N=E4(q,J.mode,W),N.return=J,J=N),y(J)):l(J,N)}return w}var Gi=IF(!0),gF=IF(!1),e3=Jn(null),ut=null,ci=null,R2=null;function x2(){R2=ci=ut=null}function h2(u){var f=e3.current;Gf(e3),u._currentValue=f}function i2(u,f,l){for(;u!==null;){var r=u.alternate;if((u.childLanes&f)!==f?(u.childLanes|=f,r!==null&&(r.childLanes|=f)):r!==null&&(r.childLanes&f)!==f&&(r.childLanes|=f),u===l)break;u=u.return}}function Ni(u,f){ut=u,R2=ci=null,u=u.dependencies,u!==null&&u.firstContext!==null&&((u.lanes&f)!==0&&(Cl=!0),u.firstContext=null)}function zr(u){var f=u._currentValue;if(R2!==u)if(u={context:u,memoizedValue:f,next:null},ci===null){if(ut===null)throw Error(Uu(308));ci=u,ut.dependencies={lanes:0,firstContext:u}}else ci=ci.next=u;return f}var l1=null;function b2(u){l1===null?l1=[u]:l1.push(u)}function sF(u,f,l,r){var n=f.interleaved;return n===null?(l.next=l,b2(f)):(l.next=n.next,n.next=l),f.interleaved=l,E0(u,r)}function E0(u,f){u.lanes|=f;var l=u.alternate;l!==null&&(l.lanes|=f),l=u;for(u=u.return;u!==null;)u.childLanes|=f,l=u.alternate,l!==null&&(l.childLanes|=f),l=u,u=u.return;return l.tag===3?l.stateNode:null}var o0=!1;function v2(u){u.updateQueue={baseState:u.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function aF(u,f){u=u.updateQueue,f.updateQueue===u&&(f.updateQueue={baseState:u.baseState,firstBaseUpdate:u.firstBaseUpdate,lastBaseUpdate:u.lastBaseUpdate,shared:u.shared,effects:u.effects})}function G0(u,f){return{eventTime:u,lane:f,tag:0,payload:null,callback:null,next:null}}function _n(u,f,l){var r=u.updateQueue;if(r===null)return null;if(r=r.shared,(lf&2)!==0){var n=r.pending;return n===null?f.next=f:(f.next=n.next,n.next=f),r.pending=f,E0(u,l)}return n=r.interleaved,n===null?(f.next=f,b2(r)):(f.next=n.next,n.next=f),r.interleaved=f,E0(u,l)}function X3(u,f,l){if(f=f.updateQueue,f!==null&&(f=f.shared,(l&4194240)!==0)){var r=f.lanes;r&=u.pendingLanes,l|=r,f.lanes=l,B2(u,l)}}function zj(u,f){var{updateQueue:l,alternate:r}=u;if(r!==null&&(r=r.updateQueue,l===r)){var n=null,i=null;if(l=l.firstBaseUpdate,l!==null){do{var y={eventTime:l.eventTime,lane:l.lane,tag:l.tag,payload:l.payload,callback:l.callback,next:null};i===null?n=i=y:i=i.next=y,l=l.next}while(l!==null);i===null?n=i=f:i=i.next=f}else n=i=f;l={baseState:r.baseState,firstBaseUpdate:n,lastBaseUpdate:i,shared:r.shared,effects:r.effects},u.updateQueue=l;return}u=l.lastBaseUpdate,u===null?l.firstBaseUpdate=f:u.next=f,l.lastBaseUpdate=f}function ft(u,f,l,r){var n=u.updateQueue;o0=!1;var{firstBaseUpdate:i,lastBaseUpdate:y}=n,_=n.shared.pending;if(_!==null){n.shared.pending=null;var $=_,A=$.next;$.next=null,y===null?i=A:y.next=A,y=$;var c=u.alternate;c!==null&&(c=c.updateQueue,_=c.lastBaseUpdate,_!==y&&(_===null?c.firstBaseUpdate=A:_.next=A,c.lastBaseUpdate=$))}if(i!==null){var j=n.baseState;y=0,c=A=$=null,_=i;do{var{lane:F,eventTime:U}=_;if((r&F)===F){c!==null&&(c=c.next={eventTime:U,lane:0,tag:_.tag,payload:_.payload,callback:_.callback,next:null});u:{var Q=u,L=_;switch(F=f,U=l,L.tag){case 1:if(Q=L.payload,typeof Q==="function"){j=Q.call(U,j,F);break u}j=Q;break u;case 3:Q.flags=Q.flags&-65537|128;case 0:if(Q=L.payload,F=typeof Q==="function"?Q.call(U,j,F):Q,F===null||F===void 0)break u;j=Bf({},j,F);break u;case 2:o0=!0}}_.callback!==null&&_.lane!==0&&(u.flags|=64,F=n.effects,F===null?n.effects=[_]:F.push(_))}else U={eventTime:U,lane:F,tag:_.tag,payload:_.payload,callback:_.callback,next:null},c===null?(A=c=U,$=j):c=c.next=U,y|=F;if(_=_.next,_===null)if(_=n.shared.pending,_===null)break;else F=_,_=F.next,F.next=null,n.lastBaseUpdate=F,n.shared.pending=null}while(1);if(c===null&&($=j),n.baseState=$,n.firstBaseUpdate=A,n.lastBaseUpdate=c,f=n.shared.interleaved,f!==null){n=f;do y|=n.lane,n=n.next;while(n!==f)}else i===null&&(n.shared.lanes=0);t1|=y,u.lanes=y,u.memoizedState=j}}function Tj(u,f,l){if(u=f.effects,f.effects=null,u!==null)for(f=0;fl?l:4,u(!0);var r=w4.transition;w4.transition={};try{u(!1),f()}finally{Af=l,w4.transition=r}}function FJ(){return Tr().memoizedState}function Az(u,f,l){var r=tn(u);if(l={lane:r,action:l,hasEagerState:!1,eagerState:null,next:null},JJ(u))UJ(f,l);else if(l=sF(u,f,l,r),l!==null){var n=Hl();Mr(l,u,r,n),QJ(l,f,r)}}function cz(u,f,l){var r=tn(u),n={lane:r,action:l,hasEagerState:!1,eagerState:null,next:null};if(JJ(u))UJ(f,n);else{var i=u.alternate;if(u.lanes===0&&(i===null||i.lanes===0)&&(i=f.lastRenderedReducer,i!==null))try{var y=f.lastRenderedState,_=i(y,l);if(n.hasEagerState=!0,n.eagerState=_,Cr(_,y)){var $=f.interleaved;$===null?(n.next=n,b2(f)):(n.next=$.next,$.next=n),f.interleaved=n;return}}catch(A){}finally{}l=sF(u,f,n,r),l!==null&&(n=Hl(),Mr(l,u,r,n),QJ(l,f,r))}}function JJ(u){var f=u.alternate;return u===Hf||f!==null&&f===Hf}function UJ(u,f){dy=rt=!0;var l=u.pending;l===null?f.next=f:(f.next=l.next,l.next=f),u.pending=f}function QJ(u,f,l){if((l&4194240)!==0){var r=f.lanes;r&=u.pendingLanes,l|=r,f.lanes=l,B2(u,l)}}var nt={readContext:zr,useCallback:ql,useContext:ql,useEffect:ql,useImperativeHandle:ql,useInsertionEffect:ql,useLayoutEffect:ql,useMemo:ql,useReducer:ql,useRef:ql,useState:ql,useDebugValue:ql,useDeferredValue:ql,useTransition:ql,useMutableSource:ql,useSyncExternalStore:ql,useId:ql,unstable_isNewReconciler:!1},jz={readContext:zr,useCallback:function(u,f){return er().memoizedState=[u,f===void 0?null:f],u},useContext:zr,useEffect:Zj,useImperativeHandle:function(u,f,l){return l=l!==null&&l!==void 0?l.concat([u]):null,S3(4194308,4,$J.bind(null,f,u),l)},useLayoutEffect:function(u,f){return S3(4194308,4,u,f)},useInsertionEffect:function(u,f){return S3(4,2,u,f)},useMemo:function(u,f){var l=er();return f=f===void 0?null:f,u=u(),l.memoizedState=[u,f],u},useReducer:function(u,f,l){var r=er();return f=l!==void 0?l(f):f,r.memoizedState=r.baseState=f,u={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:u,lastRenderedState:f},r.queue=u,u=u.dispatch=Az.bind(null,Hf,u),[r.memoizedState,u]},useRef:function(u){var f=er();return u={current:u},f.memoizedState=u},useState:Ej,useDebugValue:e2,useDeferredValue:function(u){return er().memoizedState=u},useTransition:function(){var u=Ej(!1),f=u[0];return u=tz.bind(null,u[1]),er().memoizedState=u,[f,u]},useMutableSource:function(){},useSyncExternalStore:function(u,f,l){var r=Hf,n=er();if(Ef){if(l===void 0)throw Error(Uu(407));l=l()}else{if(l=f(),fl===null)throw Error(Uu(349));($1&30)!==0||uJ(r,f,l)}n.memoizedState=l;var i={value:l,getSnapshot:f};return n.queue=i,Zj(lJ.bind(null,r,i,u),[u]),r.flags|=2048,q_(9,fJ.bind(null,r,i,l,f),void 0,null),l},useId:function(){var u=er(),f=fl.identifierPrefix;if(Ef){var l=K0,r=w0;l=(r&~(1<<32-Pr(r)-1)).toString(32)+l,f=":"+f+"R"+l,l=U_++,0",u=u.removeChild(u.firstChild)):typeof r.is==="string"?u=y.createElement(l,{is:r.is}):(u=y.createElement(l),l==="select"&&(y=u,r.multiple?y.multiple=!0:r.size&&(y.size=r.size))):u=y.createElementNS(u,l),u[er]=f,u[j_]=r,GJ(u,f,!1,!1),f.stateNode=u;u:{switch(y=M4(l,r),l){case"dialog":wf("cancel",u),wf("close",u),n=r;break;case"iframe":case"object":case"embed":wf("load",u),n=r;break;case"video":case"audio":for(n=0;nEi&&(f.flags|=128,r=!0,py(i,!1),f.lanes=4194304)}else{if(!r)if(u=f3(y),u!==null){if(f.flags|=128,r=!0,l=u.updateQueue,l!==null&&(f.updateQueue=l,f.flags|=4),py(i,!0),i.tail===null&&i.tailMode==="hidden"&&!y.alternate&&!zf)return Ul(f),null}else 2*Sf()-i.renderingStartTime>Ei&&l!==1073741824&&(f.flags|=128,r=!0,py(i,!1),f.lanes=4194304);i.isBackwards?(y.sibling=f.child,f.child=y):(l=i.last,l!==null?l.sibling=y:f.child=y,i.last=y)}if(i.tail!==null)return f=i.tail,i.rendering=f,i.tail=f.sibling,i.renderingStartTime=Sf(),f.sibling=null,l=Ef.current,Nf(Ef,r?l&1|2:l&1),f;return Ul(f),null;case 22:case 23:return ic(),r=f.memoizedState!==null,u!==null&&u.memoizedState!==null!==r&&(f.flags|=8192),r&&(f.mode&1)!==0?(fr&1073741824)!==0&&(Ul(f),f.subtreeFlags&6&&(f.flags|=8192)):Ul(f),null;case 24:return null;case 25:return null}throw Error(Uu(156,f.tag))}function Fz(u,f){switch(M2(f),f.tag){case 1:return Cl(f.type)&>(),u=f.flags,u&65536?(f.flags=u&-65537|128,f):null;case 3:return zi(),Lf(Ml),Lf(ql),g2(),u=f.flags,(u&65536)!==0&&(u&128)===0?(f.flags=u&-65537|128,f):null;case 5:return I2(f),null;case 13:if(Lf(Ef),u=f.memoizedState,u!==null&&u.dehydrated!==null){if(f.alternate===null)throw Error(Uu(340));Ki()}return u=f.flags,u&65536?(f.flags=u&-65537|128,f):null;case 19:return Lf(Ef),null;case 4:return zi(),null;case 10:return h2(f.type._context),null;case 22:case 23:return ic(),null;case 24:return null;default:return null}}var Et=!1,Ql=!1,Jz=typeof WeakSet==="function"?WeakSet:Set,zu=null;function ji(u,f){var l=u.ref;if(l!==null)if(typeof l==="function")try{l(null)}catch(r){Vf(u,f,r)}else l.current=null}function J2(u,f,l){try{l()}catch(r){Vf(u,f,r)}}var Sj=!1;function Uz(u,f){if(o4=bt,u=BF(),p2(u)){if("selectionStart"in u)var l={start:u.selectionStart,end:u.selectionEnd};else u:{l=(l=u.ownerDocument)&&l.defaultView||window;var r=l.getSelection&&l.getSelection();if(r&&r.rangeCount!==0){l=r.anchorNode;var{anchorOffset:n,focusNode:i}=r;r=r.focusOffset;try{l.nodeType,i.nodeType}catch(W){l=null;break u}var y=0,_=-1,$=-1,c=0,A=0,j=u,F=null;f:for(;;){for(var U;;){if(j!==l||n!==0&&j.nodeType!==3||(_=y+n),j!==i||r!==0&&j.nodeType!==3||($=y+r),j.nodeType===3&&(y+=j.nodeValue.length),(U=j.firstChild)===null)break;F=j,j=U}for(;;){if(j===u)break f;if(F===l&&++c===n&&(_=y),F===i&&++A===r&&($=y),(U=j.nextSibling)!==null)break;j=F,F=j.parentNode}j=U}l=_===-1||$===-1?null:{start:_,end:$}}else l=null}l=l||{start:0,end:0}}else l=null;d4={focusedElem:u,selectionRange:l},bt=!1;for(zu=f;zu!==null;)if(f=zu,u=f.child,(f.subtreeFlags&1028)!==0&&u!==null)u.return=f,zu=u;else for(;zu!==null;){f=zu;try{var Q=f.alternate;if((f.flags&1024)!==0)switch(f.tag){case 0:case 11:case 15:break;case 1:if(Q!==null){var{memoizedProps:w,memoizedState:L}=Q,J=f.stateNode,N=J.getSnapshotBeforeUpdate(f.elementType===f.type?w:Xr(f.type,w),L);J.__reactInternalSnapshotBeforeUpdate=N}break;case 3:var q=f.stateNode.containerInfo;q.nodeType===1?q.textContent="":q.nodeType===9&&q.documentElement&&q.removeChild(q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(Uu(163))}}catch(W){Vf(f,f.return,W)}if(u=f.sibling,u!==null){u.return=f.return,zu=u;break}zu=f.return}return Q=Sj,Sj=!1,Q}function ey(u,f,l){var r=f.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var n=r=r.next;do{if((n.tag&u)===u){var i=n.destroy;n.destroy=void 0,i!==void 0&&J2(f,l,i)}n=n.next}while(n!==r)}}function q3(u,f){if(f=f.updateQueue,f=f!==null?f.lastEffect:null,f!==null){var l=f=f.next;do{if((l.tag&u)===u){var r=l.create;l.destroy=r()}l=l.next}while(l!==f)}}function U2(u){var f=u.ref;if(f!==null){var l=u.stateNode;switch(u.tag){case 5:u=l;break;default:u=l}typeof f==="function"?f(u):f.current=u}}function EJ(u){var f=u.alternate;f!==null&&(u.alternate=null,EJ(f)),u.child=null,u.deletions=null,u.sibling=null,u.tag===5&&(f=u.stateNode,f!==null&&(delete f[er],delete f[j_],delete f[f2],delete f[oG],delete f[dG])),u.stateNode=null,u.return=null,u.dependencies=null,u.memoizedProps=null,u.memoizedState=null,u.pendingProps=null,u.stateNode=null,u.updateQueue=null}function ZJ(u){return u.tag===5||u.tag===3||u.tag===4}function mj(u){u:for(;;){for(;u.sibling===null;){if(u.return===null||ZJ(u.return))return null;u=u.return}u.sibling.return=u.return;for(u=u.sibling;u.tag!==5&&u.tag!==6&&u.tag!==18;){if(u.flags&2)continue u;if(u.child===null||u.tag===4)continue u;else u.child.return=u,u=u.child}if(!(u.flags&2))return u.stateNode}}function Q2(u,f,l){var r=u.tag;if(r===5||r===6)u=u.stateNode,f?l.nodeType===8?l.parentNode.insertBefore(u,f):l.insertBefore(u,f):(l.nodeType===8?(f=l.parentNode,f.insertBefore(u,l)):(f=l,f.appendChild(u)),l=l._reactRootContainer,l!==null&&l!==void 0||f.onclick!==null||(f.onclick=It));else if(r!==4&&(u=u.child,u!==null))for(Q2(u,f,l),u=u.sibling;u!==null;)Q2(u,f,l),u=u.sibling}function q2(u,f,l){var r=u.tag;if(r===5||r===6)u=u.stateNode,f?l.insertBefore(u,f):l.appendChild(u);else if(r!==4&&(u=u.child,u!==null))for(q2(u,f,l),u=u.sibling;u!==null;)q2(u,f,l),u=u.sibling}var il=null,Yr=!1;function o0(u,f,l){for(l=l.child;l!==null;)OJ(u,f,l),l=l.sibling}function OJ(u,f,l){if(u0&&typeof u0.onCommitFiberUnmount==="function")try{u0.onCommitFiberUnmount(t3,l)}catch(_){}switch(l.tag){case 5:Ql||ji(l,f);case 6:var r=il,n=Yr;il=null,o0(u,f,l),il=r,Yr=n,il!==null&&(Yr?(u=il,l=l.stateNode,u.nodeType===8?u.parentNode.removeChild(l):u.removeChild(l)):il.removeChild(l.stateNode));break;case 18:il!==null&&(Yr?(u=il,l=l.stateNode,u.nodeType===8?N4(u.parentNode,l):u.nodeType===1&&N4(u,l),__(u)):N4(il,l.stateNode));break;case 4:r=il,n=Yr,il=l.stateNode.containerInfo,Yr=!0,o0(u,f,l),il=r,Yr=n;break;case 0:case 11:case 14:case 15:if(!Ql&&(r=l.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){n=r=r.next;do{var i=n,y=i.destroy;i=i.tag,y!==void 0&&((i&2)!==0?J2(l,f,y):(i&4)!==0&&J2(l,f,y)),n=n.next}while(n!==r)}o0(u,f,l);break;case 1:if(!Ql&&(ji(l,f),r=l.stateNode,typeof r.componentWillUnmount==="function"))try{r.props=l.memoizedProps,r.state=l.memoizedState,r.componentWillUnmount()}catch(_){Vf(l,f,_)}o0(u,f,l);break;case 21:o0(u,f,l);break;case 22:l.mode&1?(Ql=(r=Ql)||l.memoizedState!==null,o0(u,f,l),Ql=r):o0(u,f,l);break;default:o0(u,f,l)}}function pj(u){var f=u.updateQueue;if(f!==null){u.updateQueue=null;var l=u.stateNode;l===null&&(l=u.stateNode=new Jz),f.forEach(function(r){var n=zz.bind(null,u,r);l.has(r)||(l.add(r),r.then(n,n))})}}function Dr(u,f){var l=f.deletions;if(l!==null)for(var r=0;rn&&(n=y),r&=~i}if(r=n,r=Sf()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3000>r?3000:4320>r?4320:1960*qz(r/1960))-r,10u?16:u,rn===null)var r=!1;else{if(u=rn,rn=null,y3=0,(lf&6)!==0)throw Error(Uu(331));var n=lf;lf|=4;for(zu=u.current;zu!==null;){var i=zu,y=i.child;if((zu.flags&16)!==0){var _=i.deletions;if(_!==null){for(var $=0;$<_.length;$++){var c=_[$];for(zu=c;zu!==null;){var A=zu;switch(A.tag){case 0:case 11:case 15:ey(8,A,i)}var j=A.child;if(j!==null)j.return=A,zu=j;else for(;zu!==null;){A=zu;var{sibling:F,return:U}=A;if(EJ(A),A===c){zu=null;break}if(F!==null){F.return=U,zu=F;break}zu=U}}}var Q=i.alternate;if(Q!==null){var w=Q.child;if(w!==null){Q.child=null;do{var L=w.sibling;w.sibling=null,w=L}while(w!==null)}}zu=i}}if((i.subtreeFlags&2064)!==0&&y!==null)y.return=i,zu=y;else u:for(;zu!==null;){if(i=zu,(i.flags&2048)!==0)switch(i.tag){case 0:case 11:case 15:ey(9,i,i.return)}var J=i.sibling;if(J!==null){J.return=i.return,zu=J;break u}zu=i.return}}var N=u.current;for(zu=N;zu!==null;){y=zu;var q=y.child;if((y.subtreeFlags&2064)!==0&&q!==null)q.return=y,zu=q;else u:for(y=N;zu!==null;){if(_=zu,(_.flags&2048)!==0)try{switch(_.tag){case 0:case 11:case 15:q3(9,_)}}catch(z){Vf(_,_.return,z)}if(_===y){zu=null;break u}var W=_.sibling;if(W!==null){W.return=_.return,zu=W;break u}zu=_.return}}if(lf=n,qn(),u0&&typeof u0.onPostCommitFiberRoot==="function")try{u0.onPostCommitFiberRoot(t3,u)}catch(z){}r=!0}return r}finally{tf=l,wr.transition=f}}return!1}function xj(u,f,l){f=Ti(l,f),f=UJ(u,f,1),u=tn(u,f,1),f=Ol(),u!==null&&(W_(u,1,f),Rl(u,f))}function Vf(u,f,l){if(u.tag===3)xj(u,u,l);else for(;f!==null;){if(f.tag===3){xj(f,u,l);break}else if(f.tag===1){var r=f.stateNode;if(typeof f.type.getDerivedStateFromError==="function"||typeof r.componentDidCatch==="function"&&(cn===null||!cn.has(r))){u=Ti(l,u),u=QJ(f,u,1),f=tn(f,u,1),u=Ol(),f!==null&&(W_(f,1,u),Rl(f,u));break}}f=f.return}}function Kz(u,f,l){var r=u.pingCache;r!==null&&r.delete(f),f=Ol(),u.pingedLanes|=u.suspendedLanes&l,fl===u&&(yl&l)===l&&(af===4||af===3&&(yl&130023424)===yl&&500>Sf()-rc?y1(u,0):lc|=l),Rl(u,f)}function mJ(u,f){f===0&&((u.mode&1)===0?f=1:(f=qt,qt<<=1,(qt&130023424)===0&&(qt=4194304)));var l=Ol();u=E0(u,f),u!==null&&(W_(u,f,l),Rl(u,l))}function Gz(u){var f=u.memoizedState,l=0;f!==null&&(l=f.retryLane),mJ(u,l)}function zz(u,f){var l=0;switch(u.tag){case 13:var{stateNode:r,memoizedState:n}=u;n!==null&&(l=n.retryLane);break;case 19:r=u.stateNode;break;default:throw Error(Uu(314))}r!==null&&r.delete(f),mJ(u,l)}var pJ;pJ=function(u,f,l){if(u!==null)if(u.memoizedProps!==f.pendingProps||Ml.current)Pl=!0;else{if((u.lanes&l)===0&&(f.flags&128)===0)return Pl=!1,Az(u,f,l);Pl=(u.flags&131072)!==0?!0:!1}else Pl=!1,zf&&(f.flags&1048576)!==0&&RF(f,ot,f.index);switch(f.lanes=0,f.tag){case 2:var r=f.type;St(u,f),u=f.pendingProps;var n=Li(f,ql.current);Ni(f,l),n=a2(null,f,r,u,n,l);var i=o2();return f.flags|=1,typeof n==="object"&&n!==null&&typeof n.render==="function"&&n.$$typeof===void 0?(f.tag=1,f.memoizedState=null,f.updateQueue=null,Cl(r)?(i=!0,st(f)):i=!1,f.memoizedState=n.state!==null&&n.state!==void 0?n.state:null,v2(f),n.updater=Q3,f.stateNode=n,n._reactInternals=f,_2(f,r,u,l),f=c2(null,f,r,!0,i,l)):(f.tag=0,zf&&i&&P2(f),Zl(null,f,n,l),f=f.child),f;case 16:r=f.elementType;u:{switch(St(u,f),u=f.pendingProps,n=r._init,r=n(r._payload),f.type=r,n=f.tag=Ez(r),u=Xr(r,u),n){case 0:f=t2(null,f,r,u,l);break u;case 1:f=Dj(null,f,r,u,l);break u;case 11:f=Bj(null,f,r,u,l);break u;case 14:f=Vj(null,f,r,Xr(r.type,u),l);break u}throw Error(Uu(306,r,""))}return f;case 0:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Xr(r,n),t2(u,f,r,n,l);case 1:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Xr(r,n),Dj(u,f,r,n,l);case 3:u:{if(wJ(f),u===null)throw Error(Uu(387));r=f.pendingProps,i=f.memoizedState,n=i.element,IF(u,f),u3(f,r,null,l);var y=f.memoizedState;if(r=y.element,i.isDehydrated)if(i={element:r,isDehydrated:!1,cache:y.cache,pendingSuspenseBoundaries:y.pendingSuspenseBoundaries,transitions:y.transitions},f.updateQueue.baseState=i,f.memoizedState=i,f.flags&256){n=Ti(Error(Uu(423)),f),f=Xj(u,f,r,l,n);break u}else if(r!==n){n=Ti(Error(Uu(424)),f),f=Xj(u,f,r,l,n);break u}else for(lr=$n(f.stateNode.containerInfo.firstChild),rr=f,zf=!0,Sr=null,l=vF(f,null,r,l),f.child=l;l;)l.flags=l.flags&-3|4096,l=l.sibling;else{if(Ki(),r===n){f=Z0(u,f,l);break u}Zl(u,f,r,l)}f=f.child}return f;case 5:return gF(f),u===null&&n2(f),r=f.type,n=f.pendingProps,i=u!==null?u.memoizedProps:null,y=n.children,e4(r,n)?y=null:i!==null&&e4(r,i)&&(f.flags|=32),WJ(u,f),Zl(u,f,y,l),f.child;case 6:return u===null&&n2(f),null;case 13:return LJ(u,f,l);case 4:return k2(f,f.stateNode.containerInfo),r=f.pendingProps,u===null?f.child=Gi(f,null,r,l):Zl(u,f,r,l),f.child;case 11:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Xr(r,n),Bj(u,f,r,n,l);case 7:return Zl(u,f,f.pendingProps,l),f.child;case 8:return Zl(u,f,f.pendingProps.children,l),f.child;case 12:return Zl(u,f,f.pendingProps.children,l),f.child;case 10:u:{if(r=f.type._context,n=f.pendingProps,i=f.memoizedProps,y=n.value,Nf(dt,r._currentValue),r._currentValue=y,i!==null)if(Pr(i.value,y)){if(i.children===n.children&&!Ml.current){f=Z0(u,f,l);break u}}else for(i=f.child,i!==null&&(i.return=f);i!==null;){var _=i.dependencies;if(_!==null){y=i.child;for(var $=_.firstContext;$!==null;){if($.context===r){if(i.tag===1){$=G0(-1,l&-l),$.tag=2;var c=i.updateQueue;if(c!==null){c=c.shared;var A=c.pending;A===null?$.next=$:($.next=A.next,A.next=$),c.pending=$}}i.lanes|=l,$=i.alternate,$!==null&&($.lanes|=l),i2(i.return,l,f),_.lanes|=l;break}$=$.next}}else if(i.tag===10)y=i.type===f.type?null:i.child;else if(i.tag===18){if(y=i.return,y===null)throw Error(Uu(341));y.lanes|=l,_=y.alternate,_!==null&&(_.lanes|=l),i2(y,l,f),y=i.sibling}else y=i.child;if(y!==null)y.return=i;else for(y=i;y!==null;){if(y===f){y=null;break}if(i=y.sibling,i!==null){i.return=y.return,y=i;break}y=y.return}i=y}Zl(u,f,n.children,l),f=f.child}return f;case 9:return n=f.type,r=f.pendingProps.children,Ni(f,l),n=Lr(n),r=r(n),f.flags|=1,Zl(u,f,r,l),f.child;case 14:return r=f.type,n=Xr(r,f.pendingProps),n=Xr(r.type,n),Vj(u,f,r,n,l);case 15:return qJ(u,f,f.type,f.pendingProps,l);case 17:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Xr(r,n),St(u,f),f.tag=1,Cl(r)?(u=!0,st(f)):u=!1,Ni(f,l),JJ(f,r,n),_2(f,r,n,l),c2(null,f,r,!0,u,l);case 19:return KJ(u,f,l);case 22:return NJ(u,f,l)}throw Error(Uu(156,f.tag))};function PJ(u,f){return AF(u,f)}function Tz(u,f,l,r){this.tag=u,this.key=l,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=f,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Wr(u,f,l,r){return new Tz(u,f,l,r)}function _c(u){return u=u.prototype,!(!u||!u.isReactComponent)}function Ez(u){if(typeof u==="function")return _c(u)?1:0;if(u!==void 0&&u!==null){if(u=u.$$typeof,u===E2)return 11;if(u===Z2)return 14}return 2}function jn(u,f){var l=u.alternate;return l===null?(l=Wr(u.tag,f,u.key,u.mode),l.elementType=u.elementType,l.type=u.type,l.stateNode=u.stateNode,l.alternate=u,u.alternate=l):(l.pendingProps=f,l.type=u.type,l.flags=0,l.subtreeFlags=0,l.deletions=null),l.flags=u.flags&14680064,l.childLanes=u.childLanes,l.lanes=u.lanes,l.child=u.child,l.memoizedProps=u.memoizedProps,l.memoizedState=u.memoizedState,l.updateQueue=u.updateQueue,f=u.dependencies,l.dependencies=f===null?null:{lanes:f.lanes,firstContext:f.firstContext},l.sibling=u.sibling,l.index=u.index,l.ref=u.ref,l}function Pt(u,f,l,r,n,i){var y=2;if(r=u,typeof u==="function")_c(u)&&(y=1);else if(typeof u==="string")y=5;else u:switch(u){case ri:return _1(l.children,n,i,f);case T2:y=8,n|=8;break;case H4:return u=Wr(12,l,f,n|2),u.elementType=H4,u.lanes=i,u;case B4:return u=Wr(13,l,f,n),u.elementType=B4,u.lanes=i,u;case V4:return u=Wr(19,l,f,n),u.elementType=V4,u.lanes=i,u;case gj:return W3(l,n,i,f);default:if(typeof u==="object"&&u!==null)switch(u.$$typeof){case kj:y=10;break u;case Ij:y=9;break u;case E2:y=11;break u;case Z2:y=14;break u;case d0:y=16,r=null;break u}throw Error(Uu(130,u==null?u:typeof u,""))}return f=Wr(y,l,f,n),f.elementType=u,f.type=r,f.lanes=i,f}function _1(u,f,l,r){return u=Wr(7,u,r,f),u.lanes=l,u}function W3(u,f,l,r){return u=Wr(22,u,r,f),u.elementType=gj,u.lanes=l,u.stateNode={isHidden:!1},u}function E4(u,f,l){return u=Wr(6,u,null,f),u.lanes=l,u}function Z4(u,f,l){return f=Wr(4,u.children!==null?u.children:[],u.key,f),f.lanes=l,f.stateNode={containerInfo:u.containerInfo,pendingChildren:null,implementation:u.implementation},f}function Zz(u,f,l,r,n){this.tag=f,this.containerInfo=u,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=A4(0),this.expirationTimes=A4(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=A4(0),this.identifierPrefix=r,this.onRecoverableError=n,this.mutableSourceEagerHydrationData=null}function $c(u,f,l,r,n,i,y,_,$){return u=new Zz(u,f,l,_,$),f===1?(f=1,i===!0&&(f|=8)):f=0,i=Wr(3,null,null,f),u.current=i,i.stateNode=u,i.memoizedState={element:r,isDehydrated:l,cache:null,transitions:null,pendingSuspenseBoundaries:null},v2(i),u}function Oz(u,f,l){var r=3{function hJ(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=="function")return;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(hJ)}catch(u){console.error(u)}}hJ(),bJ.exports=xJ()});var kJ=ur((Fc)=>{var vJ=jc();Fc.createRoot=vJ.createRoot,Fc.hydrateRoot=vJ.hydrateRoot;var Xz});var hQ=ur((y6)=>{var IZ=Qf(),gZ=Symbol.for("react.element"),sZ=Symbol.for("react.fragment"),aZ=Object.prototype.hasOwnProperty,oZ=IZ.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,dZ={key:!0,ref:!0,__self:!0,__source:!0};function xQ(u,f,l){var r,n={},i=null,y=null;l!==void 0&&(i=""+l),f.key!==void 0&&(i=""+f.key),f.ref!==void 0&&(y=f.ref);for(r in f)aZ.call(f,r)&&!dZ.hasOwnProperty(r)&&(n[r]=f[r]);if(u&&u.defaultProps)for(r in f=u.defaultProps,f)n[r]===void 0&&(n[r]=f[r]);return{$$typeof:gZ,type:u,key:i,ref:y,props:n,_owner:oZ.current}}y6.Fragment=sZ;y6.jsx=xQ;y6.jsxs=xQ});var vQ=ur((Rp,bQ)=>{bQ.exports=hQ()});var KN=ur((LN)=>{var $y=Qf();function UV(u,f){return u===f&&(u!==0||1/u===1/f)||u!==u&&f!==f}var QV=typeof Object.is==="function"?Object.is:UV,qV=$y.useState,NV=$y.useEffect,WV=$y.useLayoutEffect,wV=$y.useDebugValue;function LV(u,f){var l=f(),r=qV({inst:{value:l,getSnapshot:f}}),n=r[0].inst,i=r[1];return WV(function(){n.value=l,n.getSnapshot=f,r9(n)&&i({inst:n})},[u,l,f]),NV(function(){return r9(n)&&i({inst:n}),u(function(){r9(n)&&i({inst:n})})},[u]),wV(l),l}function r9(u){var f=u.getSnapshot;u=u.value;try{var l=f();return!QV(u,l)}catch(r){return!0}}function KV(u,f){return f()}var GV=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?KV:LV;LN.useSyncExternalStore=$y.useSyncExternalStore!==void 0?$y.useSyncExternalStore:GV});var zN=ur((Yh,GN)=>{GN.exports=KN()});var EN=ur((TN)=>{var e6=Qf(),zV=zN();function TV(u,f){return u===f&&(u!==0||1/u===1/f)||u!==u&&f!==f}var EV=typeof Object.is==="function"?Object.is:TV,ZV=zV.useSyncExternalStore,OV=e6.useRef,HV=e6.useEffect,BV=e6.useMemo,VV=e6.useDebugValue;TN.useSyncExternalStoreWithSelector=function(u,f,l,r,n){var i=OV(null);if(i.current===null){var y={hasValue:!1,value:null};i.current=y}else y=i.current;i=BV(function(){function $(U){if(!c){if(c=!0,A=U,U=r(U),n!==void 0&&y.hasValue){var Q=y.value;if(n(Q,U))return j=Q}return j=U}if(Q=j,EV(A,U))return Q;var w=r(U);if(n!==void 0&&n(Q,w))return A=U,Q;return A=U,j=w}var c=!1,A,j,F=l===void 0?null:l;return[function(){return $(f())},F===null?void 0:function(){return $(F())}]},[f,l,r,n]);var _=ZV(u,i[0],i[1]);return HV(function(){y.hasValue=!0,y.value=_},[_]),VV(_),_}});var ON=ur((mh,ZN)=>{ZN.exports=EN()});var kn=Mu(Qf(),1);var it="北京时间";var OK={timeZone:"Asia/Shanghai",hour12:!1},HK={timeZone:"Asia/Shanghai",hour12:!1},BK=new Intl.DateTimeFormat("en-CA",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23"});function s8(u){if(u===null||u===void 0||u==="")return null;let f=u instanceof Date?u:new Date(u);return Number.isNaN(f.getTime())?null:f}function H7(u){let f=s8(u);if(!f)return null;return BK.formatToParts(f).reduce((l,r)=>{if(r.type!=="literal")l[r.type]=r.value;return l},{})}function Nu(u){let f=s8(u);return f?f.toLocaleString("zh-CN",OK):"--"}function $f(u){let f=s8(u);return f?f.toLocaleTimeString("zh-CN",HK):"--"}function a8(u){let f=H7(u);if(!f)return"";let l=f.hour==="24"?"00":f.hour;return`${f.year}-${f.month}-${f.day}T${l}:${f.minute}`}function B7(u=new Date){let f=H7(u);if(!f)return"";return`${f.year}-${f.month}-${f.day}`}function V7(u){if(!u)return null;let f=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(u);if(!f)return null;let[,l,r,n,i,y,_="00"]=f,$=Date.UTC(Number(l),Number(r)-1,Number(n),Number(i)-8,Number(y),Number(_)),c=new Date($),A=a8(c);return Number.isNaN(c.getTime())||A!==`${l}-${r}-${n}T${i}:${y}`?null:c.toISOString()}var dw=Mu(kJ(),1);var E3=Mu(Qf(),1);var IJ=Mu(Qf(),1),G_=IJ.default.createElement;function Yz({active:u=!0,label:f="正在加载"}){if(!u)return null;return G_("span",{className:"loading-spinner-indicator",role:"status","aria-label":f,title:f,"data-testid":"loading-title-indicator"},G_("span",{className:"loading-spinner-ring","aria-hidden":!0}))}function nf({title:u,children:f,loading:l,level:r=2,className:n="",label:i="正在加载"}){return G_(r===3?"h3":"h2",{className:`loading-title ${l?"is-loading":""} ${n}`.trim()},G_("span",{className:"loading-title-text"},f??u),G_(Yz,{active:Boolean(l),label:i}))}class Hi extends Error{unideskRequestError=!0;meta;constructor(u,f){super(u);this.name="UniDeskRequestError",this.meta=f}}function Sz(u){return new Promise((f)=>setTimeout(f,u))}function E_(u,f="操作失败"){return u instanceof Error?u.message:String(u||f)}function z3(u,f=500){if(u===null||u===void 0)return"";let l=typeof u==="string"?u:JSON.stringify(u),r=String(l||"").replace(/\s+/gu," ").trim();return r.length>f?`${r.slice(0,f)}...`:r}function mz(u){try{let f=typeof location<"u"&&location.origin?location.origin:"http://localhost";return new URL(u,f).toString()}catch{return u}}function gJ(u){return String(u.method||"GET").toUpperCase()}function pz(u){if(u===null||u===void 0)return!1;if(typeof u!=="object")return!1;if(typeof Blob<"u"&&u instanceof Blob)return!1;if(typeof FormData<"u"&&u instanceof FormData)return!1;if(typeof URLSearchParams<"u"&&u instanceof URLSearchParams)return!1;if(typeof ArrayBuffer<"u"&&u instanceof ArrayBuffer)return!1;return!0}function sJ(u){let f=new Headers(u.headers||{}),l=pz(u.body)?JSON.stringify(u.body):u.body;if(l&&!f.has("content-type")&&typeof l==="string")f.set("content-type","application/json");return{...u,credentials:u.credentials||"same-origin",body:l,headers:f}}function aJ(u){if(u?.error&&typeof u.error==="object"&&typeof u.error.message==="string")return u.error.message;if(typeof u?.error==="string")return u.error;if(typeof u?.message==="string")return u.message;if(typeof u?.detail==="string")return u.detail;return""}function Pz(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return!1;return f.some((l)=>l!==!1&&u[l]===!1)}function z_(u,f,l,r,n={}){return{kind:u,method:l,url:mz(f),occurredAt:r.toISOString(),...n}}function T_(u,f){if(!u)return"请求失败";return`HTTP ${u}${f?` ${f}`:""}`}function oJ(u){try{return{body:u?JSON.parse(u):null,parseError:""}}catch(f){return{body:{text:u},parseError:E_(f,"parse failed")}}}async function Eu(u,f={},l=0){let{failureFields:r=["ok"],strictJson:n=!1,retryInvalidJson:i=0,retryDelayMs:y=120,invalidJsonPrefix:_="服务返回了无效 JSON",invalidJsonPreview:$=!1,responsePreviewLength:c=500,...A}=f,j=gJ(A),F=new Date,U;try{U=await fetch(u,sJ(A))}catch(L){let J=E_(L,"网络请求失败");throw new Hi(J,z_("network",u,j,F,{upstreamMessage:J}))}let Q=await U.text(),w=oJ(Q);if(w.parseError){if(n&&j==="GET"&&l=300)?T_(u.meta.status,u.meta.statusText):"应用请求失败",i=u.meta.status?T_(u.meta.status):"",y=($)=>!$||$===n||$===i,_=!y(u.message)?u.message:y(u.meta.upstreamMessage)?"":u.meta.upstreamMessage||"";return{title:n,message:_,status:u.meta.status,statusText:u.meta.statusText,method:u.meta.method,url:u.meta.url,occurredAt:Mz(u.meta.occurredAt),responsePreview:u.meta.responsePreview,parseError:u.meta.parseError,structured:!0}}let r=E_(u,f).split(/\r?\n/u);return{title:r[0]||f,message:r.slice(1).join(` -`),structured:r.length>1}}function Cz(u,f="操作失败"){let l=Jc(u,f),r=[l.title];if(l.message)r.push(`原因: ${l.message}`);if(l.method||l.url)r.push(`请求: ${[l.method,l.url].filter(Boolean).join(" ")}`);if(l.status)r.push(`状态: ${T_(l.status,l.statusText)}`);if(l.occurredAt)r.push(`时间: ${l.occurredAt}`);if(l.parseError)r.push(`解析错误: ${l.parseError}`);if(l.responsePreview&&l.responsePreview!==l.message)r.push(`响应预览: ${l.responsePreview}`);return r.filter(Boolean).join(` -`)}function Hu(u,f="操作失败"){return eJ(u)?Cz(u,f):E_(u,f)}var uU=Mu(Qf(),1);var Nn=uU.default.createElement;function Z_(u,f){return f?[Nn("dt",{key:`${u}-label`},u),Nn("dd",{key:u},f)]:null}function yf({error:u,wide:f=!1,fallback:l="操作失败",className:r=""}){if(!u)return null;let n=Jc(u,l),i=[Z_("请求",[n.method,n.url].filter(Boolean).join(" ")),Z_("状态",n.status?`HTTP ${n.status}${n.statusText?` ${n.statusText}`:""}`:""),Z_("时间",n.occurredAt),Z_("解析错误",n.parseError),Z_("响应预览",n.responsePreview)].filter(Boolean);return Nn("div",{className:`form-error unidesk-error${f?" wide":""}${r?` ${r}`:""}`,role:"alert","data-testid":"unidesk-error"},Nn("div",{className:"unidesk-error-title"},Nn("strong",null,n.title),n.status?Nn("span",{className:"unidesk-error-code"},`HTTP ${n.status}`):null),n.message?Nn("pre",{className:"unidesk-error-message"},n.message):null,i.length>0?Nn("dl",{className:"unidesk-error-details"},i):null)}var l0=Mu(Qf(),1),fU=l0.default.createContext(null);function lU({children:u}){let[f,l]=l0.default.useState([]),[r,n]=l0.default.useState(Date.now()),i=l0.default.useCallback((j,F)=>{let Q={id:`notif_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:j,message:F,timestamp:Date.now()};l((w)=>{let L=[...w,Q];if(L.length>50)return L.slice(-50);return L})},[]),y=l0.default.useCallback((j)=>{l((F)=>F.filter((U)=>U.id!==j))},[]),_=l0.default.useCallback(()=>{l([]),n(Date.now())},[]),$=l0.default.useMemo(()=>{return f.filter((j)=>j.timestamp>r).length},[f,r]),c=$>0,A={notifications:f,addNotification:i,removeNotification:y,clearNotifications:_,unreadCount:$,hasUnread:c};return Rz(fU.Provider,{value:A},u)}var Rz=l0.default.createElement;function Bl(){let u=l0.default.useContext(fU);if(!u)throw Error("useNotification must be used within NotificationProvider");return u}var R=E3.default.createElement,{useEffect:T3}=E3.default,Bi=E3.default.useState;function Nl(u,f={}){return Eu(u,{failureFields:["ok","success"],...f})}function Vl(u,f){return`${u}/microservices/baidu-netdisk/proxy${f}`}function xz(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}function Wn(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=["B","KB","MB","GB","TB"],r=f,n=0;while(r>=1024&&n{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function Di({title:u,text:f}){return R("div",{className:"empty-state"},R("strong",null,u),R("span",null,f))}function Xi({title:u,text:f,href:l,badge:r,testId:n}){return R("a",{className:"doc-link-card",href:l,target:"_blank",rel:"noreferrer","data-testid":n},R("span",null,r||"DOC"),R("strong",null,u),R("p",null,f),R("code",null,l))}function hz(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function bz(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function vz(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function kz(u){return Array.isArray(u?.files)?u.files:[]}function Iz(u){return Array.isArray(u?.jobs)?u.jobs:[]}function gz(u,f){if(!u||u===f)return f;let l=u.replace(/\/+$/u,""),r=l.slice(0,l.lastIndexOf("/"))||f;return r.lengthx.id==="baidu-netdisk")||null,[n,i]=Bi({loading:!1,actionLoading:!1,error:"",message:"",health:null,account:null,files:null,transfers:null,logs:null,selfTest:null,refreshedAt:null}),[y,_]=Bi("/"),[$,c]=Bi(null),[A,j]=Bi(""),[F,U]=Bi({localPath:"sample.txt",remotePath:"/sample.txt"}),[Q,w]=Bi({fsId:"",localPath:"downloads/"}),{addNotification:L}=Bl(),J=n.health?.baidu?.appRoot||n.account?.rootPath||"/";T3(()=>{U((x)=>{let fu=new Set(["/sample.txt","/apps/UniDeskBaiduNetdisk/sample.txt"]);if(x.remotePath&&!fu.has(x.remotePath))return x;let $u=Uc(J,"sample.txt");return x.remotePath===$u?x:{...x,remotePath:$u}})},[J]);async function N(x=y){let $u=await Nl(Vl(l,`/api/files?dir=${encodeURIComponent(x||J)}&limit=100`));i((tu)=>({...tu,files:$u}))}async function q(){let x=await Nl(Vl(l,"/api/transfers?limit=80"));i((fu)=>({...fu,transfers:x}))}async function W(){if(!r)return;i((x)=>({...x,loading:!0,error:"",message:""}));try{let x=await Nl(`${l}/microservices/baidu-netdisk/health`),fu=x?.baidu?.appRoot||J,$u=null,tu=null;if(x?.auth?.loggedIn){$u=await Nl(Vl(l,"/api/account?refresh=1"));let qu=y&&y.startsWith(fu)?y:fu;_(qu),tu=await Nl(Vl(l,`/api/files?dir=${encodeURIComponent(qu)}&limit=100`))}else _(fu);let ju=await Nl(Vl(l,"/api/transfers?limit=80")),Gu=await Nl(Vl(l,"/logs?limit=60"));i((qu)=>({...qu,loading:!1,health:x,account:$u?.account||null,files:tu,transfers:ju,logs:Gu,refreshedAt:new Date}))}catch(x){i((fu)=>({...fu,loading:!1,error:Hu(x,"百度网盘服务加载失败")}))}}async function z(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{let x=await Nl(Vl(l,"/api/auth/device/start"),{method:"POST",body:{}});c(x.session||null),i((fu)=>({...fu,actionLoading:!1,message:"设备码已生成,请扫码授权"}))}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Hu(x,"创建设备码失败")}))}}async function Z(x=!1){if(!$?.id)return;if(x)i((fu)=>({...fu,actionLoading:!0,error:""}));try{let fu=await Nl(Vl(l,`/api/auth/device/status?sessionId=${encodeURIComponent($.id)}`));if(c(fu.session||null),fu.session?.status==="succeeded")i(($u)=>({...$u,actionLoading:!1,message:"授权成功,正在刷新账号与文件列表"})),await W();else if(x)i(($u)=>({...$u,actionLoading:!1}))}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"轮询登录状态失败")}))}}async function H(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{await Nl(Vl(l,"/api/auth/logout"),{method:"POST",body:{}}),c(null),i((x)=>({...x,actionLoading:!1,account:null,files:null,message:"本地 token 已清除"})),await W()}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Hu(x,"退出登录失败")}))}}async function E(x){x.preventDefault();let fu=A.trim();if(!fu)return;i(($u)=>({...$u,actionLoading:!0,error:"",message:""}));try{await Nl(Vl(l,"/api/folders"),{method:"POST",body:{path:Uc(y,fu)}}),j(""),i(($u)=>({...$u,actionLoading:!1,message:"文件夹已创建"})),await N(y)}catch($u){i((tu)=>({...tu,actionLoading:!1,error:Hu($u,"创建文件夹失败")}))}}async function D(x){if(!x)return;i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await Nl(Vl(l,"/api/files/manage"),{method:"POST",body:{opera:"delete",filelist:[{path:x}],async:1}}),i((fu)=>({...fu,actionLoading:!1,message:"删除任务已提交"})),await N(y)}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"删除失败")}))}}async function h(x){x.preventDefault(),i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await Nl(Vl(l,"/api/transfers/upload-from-path"),{method:"POST",body:F}),i((fu)=>({...fu,actionLoading:!1,message:"上传任务已入队"})),await q()}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"上传任务创建失败")}))}}async function B(x){x.preventDefault(),i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await Nl(Vl(l,"/api/transfers/download-to-path"),{method:"POST",body:Q}),i((fu)=>({...fu,actionLoading:!1,message:"下载任务已入队"})),await q()}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"下载任务创建失败")}))}}async function X(x,fu){i(($u)=>({...$u,actionLoading:!0,error:"",message:""}));try{await Nl(Vl(l,`/api/transfers/${encodeURIComponent(x)}/${fu}`),{method:"POST",body:{}}),i(($u)=>({...$u,actionLoading:!1,message:fu==="cancel"?"已请求取消任务":"任务已重新入队"})),await q()}catch($u){i((tu)=>({...tu,actionLoading:!1,error:Hu($u,"任务操作失败")}))}}async function m(){i((x)=>({...x,actionLoading:!0,error:"",message:"正在运行上传/下载自测..."}));try{let x=await Nl(Vl(l,"/api/self-test"),{method:"POST",body:{}});i((fu)=>({...fu,actionLoading:!1,selfTest:x,message:`上传/下载自测通过:${x.remotePath||""}`})),await N(y),await q()}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Hu(x,"上传/下载自测失败")}))}}if(T3(()=>{if(!r)return;W();return},[r?.id,r?.runtime?.providerStatus]),T3(()=>{if(!$?.id||$.status!=="pending")return;let x=window.setInterval(()=>void Z(!1),Math.max(5000,Number($.pollIntervalSeconds||5)*1000));return()=>window.clearInterval(x)},[$?.id,$?.status,$?.pollIntervalSeconds]),T3(()=>{if(!r)return;let x=window.setInterval(()=>void q(),5000);return()=>window.clearInterval(x)},[r?.id]),!r)return R(Di,{title:"Baidu Netdisk 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=baidu-netdisk"});let O=hz(r),p=vz(r),Y=bz(r),v=n.health||{},T=n.account||v.auth?.account||null,S=v.auth||{},k=kz(n.files),I=Iz(n.transfers),b=T?.quota||{},o=Boolean(S.loggedIn||T),s=Boolean(S.configured);return R("div",{className:"baidu-netdisk-page","data-testid":"baidu-netdisk-page"},R(Q1,{title:"Baidu Netdisk 工作台",eyebrow:"Containerized Storage Gateway",loading:n.loading,actions:R("div",{className:"panel-actions"},R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-env-setup.md",target:"_blank",rel:"noreferrer","data-testid":"baidu-netdisk-config-doc-link"},"配置文档"),R("button",{type:"button",className:"ghost-btn",onClick:W,disabled:n.loading,"data-testid":"baidu-netdisk-refresh"},n.loading?"刷新中":"刷新"),R(H0,{title:"Baidu Netdisk 用户服务",data:r,onOpen:f,testId:"raw-baidu-netdisk-service"}))},R("div",{className:"baidu-netdisk-hero"},R("div",null,R("div",{className:"node-version-line"},R(U1,{status:O.providerStatus==="online"?"online":"warn"},O.providerStatus||"unknown"),R("span",null,r.providerId),R(U1,{status:Y.public?"warn":"private"},Y.public?"公网暴露":"仅 UniDesk frontend 代理访问")),R("p",{className:"muted paragraph"},r.description)),R("div",{className:"microservice-ref-card"},R("span",null,"Repo"),R("strong",null,p.url||"--"),R("code",null,p.commitId||"--")),R("div",{className:"microservice-ref-card"},R("span",null,"Private Backend"),R("strong",null,`${Y.nodeBindHost||"--"}:${Y.nodePort||"--"}`),R("code",null,`${p.composeFile||"--"} / ${p.composeService||"--"}`))),R(yf,{error:n.error,wide:!0})),R("div",{className:"metric-grid"},R(Vi,{label:"Health",value:v.ok?"OK":"--",hint:v.storage?.postgres||"postgres",tone:v.ok?"ok":"warn"}),R(Vi,{label:"OAuth",value:s?"已配置":"待配置",hint:s?"client + secret + token key":"需要设置 UNIDESK_BAIDU_NETDISK_*",tone:s?"ok":"warn"}),R(Vi,{label:"Login",value:o?"已登录":"未登录",hint:T?.username||"Device Code QR",tone:o?"ok":"warn"}),R(Vi,{label:"Work Root",value:sz(J),hint:J}),R(Vi,{label:"Quota",value:Wn(b.used),hint:b.total?`${b.usedPercent||0}% / ${Wn(b.total)}`:"授权后刷新"}),R(Vi,{label:"Transfers",value:xz(I.length),hint:`running ${n.transfers?.counts?.running||0} / failed ${n.transfers?.counts?.failed||0}`})),R(Q1,{title:"文件浏览器",eyebrow:y,className:"baidu-files-panel",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"ghost-btn",onClick:()=>{let x=gz(y,J);_(x),N(x)},disabled:!o||y===J},"上级"),R("button",{type:"button",className:"ghost-btn",onClick:()=>N(y),disabled:!o},"刷新文件"),R(H0,{title:"Baidu Files",data:n.files,onOpen:f,testId:"raw-baidu-files"}))},R("form",{className:"baidu-pathbar",onSubmit:(x)=>{x.preventDefault(),N(y)}},R("input",{value:y,onChange:(x)=>_(x.target.value),disabled:!o}),R("button",{type:"submit",className:"ghost-btn",disabled:!o},"打开路径")),R("form",{className:"baidu-pathbar",onSubmit:E},R("input",{value:A,onChange:(x)=>j(x.target.value),placeholder:"新文件夹名称",disabled:!o}),R("button",{type:"submit",className:"primary-btn",disabled:!o||!A.trim()},"新建文件夹")),!o?R(Di,{title:"等待授权",text:"登录后通过 /api/files 读取工作目录文件列表"}):k.length===0?R(Di,{title:"目录为空",text:"可以从 staging 目录上传文件或新建文件夹"}):R("div",{className:"table-wrap","data-testid":"baidu-netdisk-file-table"},R("table",null,R("thead",null,R("tr",null,R("th",null,"名称"),R("th",null,"类型"),R("th",null,"大小"),R("th",null,"修改时间"),R("th",null,"fs_id"),R("th",null,"操作"))),R("tbody",null,k.map((x)=>R("tr",{key:x.fsId||x.path},R("td",null,R("strong",null,x.serverFilename||x.path),R("code",null,x.path||"--")),R("td",null,R(U1,{status:x.isDir?"queued":"private"},x.isDir?"DIR":"FILE")),R("td",null,x.isDir?"--":Wn(x.size)),R("td",null,x.serverMtime?Nu(x.serverMtime*1000):"--"),R("td",null,R("code",null,x.fsId||"--")),R("td",null,R("div",{className:"inline-actions"},x.isDir?R("button",{type:"button",className:"ghost-btn",onClick:()=>{_(x.path),N(x.path)}},"打开"):R("button",{type:"button",className:"ghost-btn",onClick:()=>w((fu)=>({...fu,fsId:x.fsId}))},"填入下载"),R("button",{type:"button",className:"ghost-btn",onClick:()=>D(x.path),disabled:n.actionLoading},"删除"))))))))),R("div",{className:"baidu-netdisk-grid"},R(Q1,{title:"配置与文档",eyebrow:"Deployment References",className:"baidu-docs-panel",actions:R("div",{className:"panel-actions inline-actions"},R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-env-setup.md",target:"_blank",rel:"noreferrer"},"打开环境配置"),R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-user-service.md",target:"_blank",rel:"noreferrer"},"打开服务方案"))},R("p",{className:"muted paragraph"},s?"OAuth 运行时变量已配置;如需轮换密钥、迁移部署或排查代理边界,可直接打开下面的项目内文档。":"首次使用请先按环境变量配置文档填入百度应用 client id / secret,然后重建 baidu-netdisk 服务并刷新本页。"),R("div",{className:"baidu-doc-grid","data-testid":"baidu-netdisk-doc-links"},R(Xi,{title:"环境变量配置",text:"填写 UNIDESK_BAIDU_NETDISK_CLIENT_ID、CLIENT_SECRET、TOKEN_KEY,并执行重建与健康检查。",href:"/docs/issue/baidu-netdisk-env-setup.md",badge:"SETUP",testId:"baidu-netdisk-env-doc-card"}),R(Xi,{title:"服务方案与 API",text:"说明 OAuth Device Code、根目录工作区、staging 上传下载任务和后端 API 设计。",href:"/docs/issue/baidu-netdisk-user-service.md",badge:"DESIGN"}),R(Xi,{title:"用户服务安全边界",text:"查看 UniDesk microservice 私有代理、允许路径、frontendOnly 和密钥边界规则。",href:"/docs/reference/microservices.md",badge:"REF"}),R(Xi,{title:"部署与重建流程",text:"查看 server rebuild、Compose 编排、健康检查和交付验证的长期规则。",href:"/docs/reference/deployment.md",badge:"DEPLOY"}),R(Xi,{title:"CLI 验证命令",text:"查看 microservice health/proxy、server rebuild、job status 等命令入口。",href:"/docs/reference/cli.md",badge:"CLI"}),R(Xi,{title:"百度设备码模式",text:"打开百度官方 OAuth Device Code 文档,对照扫码登录和轮询参数。",href:"https://pan.baidu.com/union/doc/fl1x114ti",badge:"OFFICIAL"}))),R(Q1,{title:"设备码登录",eyebrow:"OAuth Device Code",className:"baidu-login-panel",loading:n.actionLoading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"primary-btn",onClick:z,disabled:n.actionLoading||!s,"data-testid":"baidu-netdisk-start-login"},"生成二维码"),$?.id?R("button",{type:"button",className:"ghost-btn",onClick:()=>Z(!0),disabled:n.actionLoading},"检查状态"):null,o?R("button",{type:"button",className:"ghost-btn",onClick:H,disabled:n.actionLoading},"清除本地登录"):null,R(H0,{title:"Baidu Device Session",data:$||S.latestSession,onOpen:f,testId:"raw-baidu-device-session"}))},R("div",{className:"baidu-login-card","data-testid":"baidu-netdisk-login-card"},R("div",{className:"baidu-qr-frame"},$?.qrcodeUrl?R("img",{src:$.qrcodeUrl,alt:"百度网盘设备码授权二维码","data-testid":"baidu-netdisk-qrcode"}):R(Di,{title:s?"等待二维码":"OAuth 未配置",text:s?"点击生成二维码后使用百度网盘或百度 App 扫码":"设置 client id、secret 和 token key 后重建服务"})),R("div",{className:"claudeqq-login-copy"},R("div",{className:"node-version-line"},R(U1,{status:o?"online":$?.status==="pending"?"warn":"unknown"},o?"已登录":$?.status||"未开始"),R("span",null,$?.secondsRemaining!==void 0?`${$.secondsRemaining}s`:"--"),R("span",null,"scope basic,netdisk")),R("p",{className:"muted paragraph"},o?"access token / refresh token 已加密保存到 PostgreSQL;前端只看到脱敏登录态。":"后端使用百度 OAuth Device Code 轮询换取 token;二维码过期后重新生成即可。"),R("div",{className:"microservice-ref-card"},R("span",null,"User Code"),R("strong",null,$?.userCode||"--"),R("code",null,$?.verificationUrl||"https://openapi.baidu.com/device")),R("div",{className:"microservice-ref-card"},R("span",null,"Expires"),R("strong",null,$?.expiresAt?Nu($.expiresAt):"--"),R("code",null,$?.error||"no token exposed"))))),R(Q1,{title:"账号与容量",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Account",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(H0,{title:"Baidu Account",data:T,onOpen:f,testId:"raw-baidu-account"}))},T?R("div",{className:"baidu-account-card"},R("div",{className:"node-version-line"},R(U1,{status:"online"},"connected"),R("span",null,T.baiduUid||"--"),R("span",null,`VIP ${T.vipType??"--"}`)),R("h3",null,T.username||"Baidu Netdisk"),R("p",{className:"muted paragraph"},`工作目录固定在 ${T.rootPath||J};v1 上传/下载只读写容器 staging 目录,不把大文件字节流穿过 UniDesk proxy。`),R("div",{className:"quota-bar"},R("span",{style:{width:`${Math.max(0,Math.min(100,Number(b.usedPercent||0)))}%`}})),R("div",{className:"microservice-ref-card"},R("span",null,"Quota"),R("strong",null,`${Wn(b.used)} / ${Wn(b.total)}`),R("code",null,`${b.usedPercent||0}% used`))):R(Di,{title:"尚未登录",text:"扫码授权后这里会显示账号、UID、会员状态和容量"})),R(Q1,{title:"传输任务",eyebrow:"staging path jobs",className:"baidu-transfers-panel",loading:n.actionLoading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"primary-btn",onClick:m,disabled:!o||n.actionLoading,"data-testid":"baidu-netdisk-self-test"},"运行自测"),R("button",{type:"button",className:"ghost-btn",onClick:q},"刷新任务"),R(H0,{title:"Baidu Transfers",data:n.transfers,onOpen:f,testId:"raw-baidu-transfers"}))},R("div",{className:"baidu-transfer-forms"},R("form",{className:"stack-form",onSubmit:h,"data-testid":"baidu-upload-form"},R("label",null,"容器 staging 文件",R("input",{value:F.localPath,onChange:(x)=>U((fu)=>({...fu,localPath:x.target.value})),placeholder:"sample.txt"})),R("label",null,"百度网盘目标路径",R("input",{value:F.remotePath,onChange:(x)=>U((fu)=>({...fu,remotePath:x.target.value})),placeholder:Uc(J,"sample.txt")})),R("button",{type:"submit",className:"primary-btn",disabled:!o||n.actionLoading},"上传 staging 文件")),R("form",{className:"stack-form",onSubmit:B,"data-testid":"baidu-download-form"},R("label",null,"文件 fs_id",R("input",{value:Q.fsId,onChange:(x)=>w((fu)=>({...fu,fsId:x.target.value})),placeholder:"从文件表填入"})),R("label",null,"保存到 staging 路径",R("input",{value:Q.localPath,onChange:(x)=>w((fu)=>({...fu,localPath:x.target.value})),placeholder:"downloads/"})),R("button",{type:"submit",className:"primary-btn",disabled:!o||!Q.fsId||n.actionLoading},"下载到 staging"))),n.selfTest?R("div",{className:"baidu-account-card","data-testid":"baidu-netdisk-self-test-result"},R("div",{className:"node-version-line"},R(U1,{status:n.selfTest.ok?"online":"warn"},n.selfTest.ok?"self-test ok":"self-test"),R("span",null,Wn(n.selfTest.sizeBytes))),R("h3",null,n.selfTest.remotePath||"Baidu self-test"),R("div",{className:"microservice-ref-card"},R("span",null,"fs_id"),R("strong",null,n.selfTest.fsId||"--"),R("code",null,n.selfTest.downloadedPath||"--")),R("div",{className:"microservice-ref-card"},R("span",null,"MD5"),R("strong",null,n.selfTest.downloadedMd5||"--"),R("code",null,n.selfTest.expectedMd5||"--")),R(H0,{title:"Baidu Self Test",data:n.selfTest,onOpen:f,testId:"raw-baidu-self-test"})):null,I.length===0?R(Di,{title:"暂无传输任务",text:"上传/下载任务会在后端容器内执行,避免大文件穿过 UniDesk proxy"}):R("div",{className:"table-wrap","data-testid":"baidu-transfer-table"},R("table",null,R("thead",null,R("tr",null,R("th",null,"状态"),R("th",null,"方向"),R("th",null,"路径"),R("th",null,"进度"),R("th",null,"时间"),R("th",null,"操作"))),R("tbody",null,I.map((x)=>R("tr",{key:x.id},R("td",null,R(U1,{status:x.status},x.status)),R("td",null,x.direction),R("td",null,R("strong",null,x.remotePath||x.fsId||"--"),R("code",null,x.localPath||"--"),x.error?R("span",{className:"form-error"},x.error):null),R("td",null,R(az,{percent:x.progressPercent}),R("span",{className:"muted"},`${Wn(x.bytesDone)} / ${Wn(x.sizeBytes)}`)),R("td",null,Nu(x.updatedAt)),R("td",null,R("div",{className:"inline-actions"},["queued","running"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>X(x.id,"cancel")},"取消"):null,["failed","canceled"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>X(x.id,"retry")},"重试"):null,R(H0,{title:`Transfer ${x.id}`,data:x,onOpen:f}))))))))),R(Q1,{title:"安全与日志",eyebrow:"redacted diagnostics",className:"baidu-wide-panel",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(H0,{title:"Baidu Health",data:v,onOpen:f,testId:"raw-baidu-health"}),R(H0,{title:"Baidu Logs",data:n.logs,onOpen:f,testId:"raw-baidu-logs"}))},R("div",{className:"policy-grid"},R("article",null,R("b",null,"私有后端"),R("span",null,"4244 只在 Compose 网络 expose,浏览器经 UniDesk 同源代理访问")),R("article",null,R("b",null,"Token 加密"),R("span",null,"access/refresh token 使用 BAIDU_NETDISK_TOKEN_KEY 加密后写入 PostgreSQL")),R("article",null,R("b",null,"无浏览器大文件流"),R("span",null,"上传/下载以容器 staging 目录为边界,避免 proxy 文本通道传输大字节流"))))))}var H3=Mu(Qf(),1);var a=H3.default.createElement,{useEffect:oz}=H3.default,Z3=H3.default.useState,q1={label:"主用户私聊账号",userId:645275593};function Qc(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}async function wn(u,f={}){return Eu(u,{failureFields:["ok","success"],...f})}async function dz(u){let f=await fetch(u,{credentials:"same-origin"}),l=await f.text();try{return l?JSON.parse(l):{ok:f.ok,status:f.status}}catch{return{ok:f.ok,status:f.status,text:l}}}function O3({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return a("span",{className:`status-badge ${l}`},f||u||"unknown")}function Yi({label:u,value:f,hint:l,tone:r}){return a("article",{className:`metric-card ${r||""}`},a("div",{className:"metric-label"},u),a("div",{className:"metric-value"},f),a("div",{className:"metric-hint"},l))}function Si({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return a("section",{className:`panel ${n||""}`},a("div",{className:"panel-head"},a("div",null,f?a("p",{className:"panel-eyebrow"},f):null,a(nf,{title:u,loading:i})),l?a("div",{className:"panel-actions"},l):null),a("div",{className:"panel-body"},r))}function O_({title:u,data:f,onOpen:l,testId:r}){return a("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function H_({title:u,text:f}){return a("div",{className:"empty-state"},a("strong",null,u),a("span",null,f))}function ez(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function uT(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function fT(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Ln(u,f){return`${u}/microservices/claudeqq/proxy${f}`}function lT(u){return Array.isArray(u?.events)?u.events.slice(0,80):[]}function rT(u){return Array.isArray(u?.subscriptions)?u.subscriptions.slice(0,50):[]}function nT(u){return Array.isArray(u?.messages)?u.messages.slice(0,30):[]}function nU(u){let f=u?.text??u?.message??u?.raw?.raw_message;if(typeof f!=="string")return"--";return f.length>180?`${f.slice(0,177)}...`:f}function iU(u){let f=u?.groupId??u?.group_id??(u?.message_type==="group"?u?.target_id:void 0),l=u?.userId??u?.user_id??(u?.message_type==="private"?u?.target_id:void 0);if(f)return`群 ${f}`;if(l)return`私聊 ${l}`;return"--"}function yU({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((T)=>T.id==="claudeqq")||null,[n,i]=Z3({loading:!1,qrLoading:!1,error:"",health:null,status:null,napcatLogin:null,napcatQrcode:null,qrcodeFetched:!1,qrcodeRefreshedAt:null,events:null,subscriptions:null,sent:null,refreshedAt:null}),[y,_]=Z3({targetType:"private",targetId:String(q1.userId),message:""}),[$,c]=Z3({name:"unidesk-callback",targetUrl:"",eventTypes:"message",secret:""}),[A,j]=Z3(""),{addNotification:F}=Bl();async function U(){if(!r)return;i((T)=>({...T,loading:!0,error:""}));try{let[T,S,k,I,b]=await Promise.all([dz(`${l}/microservices/claudeqq/health`),wn(Ln(l,"/api/server/status")),wn(Ln(l,"/api/events/recent?limit=60")),wn(Ln(l,"/api/events/subscriptions")),wn(Ln(l,"/api/messages/sent?limit=20"))]);if(i((o)=>({...o,loading:!1,error:"",health:T,status:S,events:k,subscriptions:I,sent:b,refreshedAt:new Date})),!n.qrcodeFetched)Q(!1)}catch(T){i((S)=>({...S,loading:!1,error:Hu(T,"ClaudeQQ 加载失败")}))}}async function Q(T=!0){if(!r)return;i((S)=>({...S,qrLoading:!0,error:T?"":S.error}));try{let S=await wn(Ln(l,"/api/napcat/login")),k=S?.napcat?.qrcode||S?.qrcode||null;i((I)=>({...I,qrLoading:!1,error:"",napcatLogin:S,napcatQrcode:k,qrcodeFetched:!0,qrcodeRefreshedAt:new Date}))}catch(S){i((k)=>({...k,qrLoading:!1,error:T||!k.napcatQrcode?Hu(S,"NapCat 二维码加载失败"):k.error}))}}async function w(T){T.preventDefault(),j("");let S=Number(y.targetId);if(!Number.isFinite(S)||S<=0||y.message.trim().length===0){i((k)=>({...k,error:"请填写 QQ 目标和消息内容"}));return}try{await wn(Ln(l,"/api/push/text"),{method:"POST",body:JSON.stringify({userId:y.targetType==="private"?S:void 0,groupId:y.targetType==="group"?S:void 0,message:y.message})});let k="消息推送请求已提交";_((I)=>({...I,targetType:"private",targetId:String(q1.userId),message:""})),j(k),F("success",k),await U()}catch(k){i((I)=>({...I,error:Hu(k,"发送失败")}))}}async function L(T){if(T.preventDefault(),j(""),$.targetUrl.trim().length===0){i((S)=>({...S,error:"请填写订阅回调 URL"}));return}try{await wn(Ln(l,"/api/events/subscriptions"),{method:"POST",body:JSON.stringify({name:$.name,targetUrl:$.targetUrl,eventTypes:$.eventTypes.split(",").map((k)=>k.trim()).filter(Boolean),secret:$.secret||void 0,enabled:!0})});let S="事件订阅已创建";j(S),F("success",S),await U()}catch(S){i((k)=>({...k,error:Hu(S,"订阅失败")}))}}async function J(T){if(!T)return;j("");try{await wn(Ln(l,`/api/events/subscriptions/${encodeURIComponent(T)}`),{method:"DELETE"});let S="事件订阅已删除";j(S),F("success",S),await U()}catch(S){i((k)=>({...k,error:Hu(S,"删除订阅失败")}))}}if(oz(()=>{if(!r)return;U();return},[r?.id,r?.runtime?.providerStatus]),!r)return a(H_,{title:"ClaudeQQ 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=claudeqq"});let N=ez(r),q=fT(r),W=uT(r),z=n.health||{},Z=n.status||{},H=n.napcatLogin||{},E=z.napcat||Z.napcat||{},D={...H.napcat||{},...E,qrcode:n.napcatQrcode||{},webui:E.webui||H.napcat?.webui},h=H.login||{},B=n.napcatQrcode||{},X=lT(n.events),m=rT(n.subscriptions),O=nT(n.sent),p=Boolean(D.httpConnected||h.ready),Y=String(D.loginState||h.state||(p?"logged_in":"unknown")),v=Boolean(B.available&&B.dataUrl);return a("div",{className:"claudeqq-page","data-testid":"claudeqq-page"},a(Si,{title:"ClaudeQQ 工作台",eyebrow:"D601 QQ Event Gateway",loading:n.loading,actions:a("div",{className:"panel-actions"},a("button",{type:"button",className:"ghost-btn",onClick:U,disabled:n.loading,"data-testid":"claudeqq-refresh-button"},n.loading?"刷新中":"刷新"),a(O_,{title:"ClaudeQQ 用户服务",data:r,onOpen:f,testId:"raw-claudeqq-service"}))},a("div",{className:"findjob-hero"},a("div",null,a("div",{className:"node-version-line"},a(O3,{status:N.providerStatus==="online"?"online":"warn"},N.providerStatus||"unknown"),a("span",null,r.providerId),a("span",null,W.public?"公网暴露":"仅 UniDesk frontend 代理访问")),a("p",{className:"muted paragraph"},r.description)),a("div",{className:"microservice-ref-card"},a("span",null,"Repo"),a("strong",null,q.url||"--"),a("code",null,q.commitId||"--")),a("div",{className:"microservice-ref-card"},a("span",null,"D601 Docker"),a("strong",null,`${W.nodeBindHost||"--"}:${W.nodePort||"--"}`),a("code",null,`${q.composeFile||"--"} / ${q.composeService||"--"}`))),a(yf,{error:n.error,wide:!0})),a("div",{className:"metric-grid"},a(Yi,{label:"Health",value:z.ok||z.status==="ok"?"OK":"--",hint:"D601 /health",tone:z.ok||z.status==="ok"?"ok":"warn"}),a(Yi,{label:"NapCat HTTP",value:D.httpConnected||D.http?.connected?"OK":"离线",hint:`${D.httpHost||z.napcat?.httpHost||"--"}:${D.httpPort||z.napcat?.httpPort||"--"}`}),a(Yi,{label:"NapCat WS",value:D.wsConnected||D.ws?.connected?"OK":"离线",hint:`${D.wsHost||z.napcat?.wsHost||"--"}:${D.wsPort||z.napcat?.wsPort||"--"}`}),a(Yi,{label:"事件缓存",value:Qc(n.events?.count??X.length),hint:"recent QQ events"}),a(Yi,{label:"订阅",value:Qc(n.subscriptions?.count??m.length),hint:"webhook subscribers"}),a(Yi,{label:"已发送",value:Qc(n.sent?.count??O.length),hint:"sent message log"})),a("div",{className:"findjob-grid"},a(Si,{title:"NapCat 容器登录",eyebrow:"QR Login",className:"claudeqq-login-panel",loading:n.qrLoading,actions:a("div",{className:"panel-actions inline-actions"},a("button",{type:"button",className:"ghost-btn",onClick:()=>Q(!0),disabled:n.qrLoading,"data-testid":"claudeqq-napcat-refresh"},n.qrLoading?"刷新中":"手动刷新二维码"),a(O_,{title:"NapCat Login",data:n.napcatLogin,onOpen:f,testId:"raw-claudeqq-napcat-login"}))},a("div",{className:"claudeqq-login-card","data-testid":"claudeqq-napcat-login"},a("div",{className:"claudeqq-qr-frame"},v?a("img",{src:B.dataUrl,alt:"NapCat QQ 登录二维码","data-testid":"claudeqq-napcat-qrcode"}):a(H_,{title:"等待二维码",text:"NapCat 容器启动后会把登录二维码写入 cache/qrcode.png"})),a("div",{className:"claudeqq-login-copy"},a("div",{className:"node-version-line"},a(O3,{status:p?"online":v?"warn":"unknown"},p?"已登录":v?"待扫码":"等待二维码"),a("span",null,Y),a("span",null,"D601 containerized")),a("p",{className:"muted paragraph"},p?"NapCat 已登录,ClaudeQQ 可通过容器内 HTTP/WS 链路收发 QQ 消息。":"用手机 QQ 扫描二维码授权登录。二维码只在首次加载或手动刷新时更新,D601 的 NapCat 端口仍只绑定 127.0.0.1。"),a("div",{className:"microservice-ref-card"},a("span",null,"NapCat WebUI"),a("strong",null,D.webui?.url||"http://napcat:6099/webui"),a("code",null,"local-only / proxied QR login")),a("div",{className:"microservice-ref-card"},a("span",null,"QR Source"),a("strong",null,B.modifiedAt?Nu(B.modifiedAt):n.qrcodeRefreshedAt?Nu(n.qrcodeRefreshedAt):"--"),a("code",null,B.file||"/napcat/cache/qrcode.png"))))),a(Si,{title:"消息推送",eyebrow:"Push API"},a("div",{className:"microservice-ref-card"},a("span",null,q1.label),a("strong",null,String(q1.userId)),a("code",null,"private userId / 默认推送测试目标")),a("form",{className:"stack-form",onSubmit:w,"data-testid":"claudeqq-push-form"},a("label",null,"目标类型",a("select",{value:y.targetType,onChange:(T)=>_((S)=>({...S,targetType:T.target.value}))},a("option",{value:"private"},"私聊 userId"),a("option",{value:"group"},"群 groupId"))),a("label",null,"QQ ID",a("input",{value:y.targetId,onChange:(T)=>_((S)=>({...S,targetId:T.target.value})),placeholder:String(q1.userId)})),a("label",null,"消息内容",a("textarea",{value:y.message,onChange:(T)=>_((S)=>({...S,message:T.target.value})),rows:4,placeholder:"通过 ClaudeQQ 推送一条 QQ 消息"})),a("button",{type:"submit",className:"primary-btn"},"发送 QQ 消息")),a("p",{className:"muted paragraph"},`主 server 和其他用户服务可通过 UniDesk 同源代理调用 /api/push/text;当前人工推送测试默认使用 ${q1.label} ${q1.userId},不需要暴露 D601 后端端口。`)),a(Si,{title:"QQ 事件订阅",eyebrow:"Webhook Subscription",loading:n.loading},a("form",{className:"stack-form",onSubmit:L,"data-testid":"claudeqq-subscription-form"},a("label",null,"订阅名称",a("input",{value:$.name,onChange:(T)=>c((S)=>({...S,name:T.target.value}))})),a("label",null,"回调 URL",a("input",{value:$.targetUrl,onChange:(T)=>c((S)=>({...S,targetUrl:T.target.value})),placeholder:"http://host.docker.internal:18080/..."})),a("label",null,"事件类型",a("input",{value:$.eventTypes,onChange:(T)=>c((S)=>({...S,eventTypes:T.target.value})),placeholder:"message,notice"})),a("label",null,"签名密钥",a("input",{value:$.secret,onChange:(T)=>c((S)=>({...S,secret:T.target.value})),placeholder:"可选,生成 x-claudeqq-signature"})),a("button",{type:"submit",className:"primary-btn"},"创建订阅")),m.length===0?a(H_,{title:"暂无订阅",text:"可以为 main server 或其他用户服务注册 HTTP webhook"}):a("div",{className:"table-wrap","data-testid":"claudeqq-subscription-table"},a("table",null,a("thead",null,a("tr",null,a("th",null,"名称"),a("th",null,"状态"),a("th",null,"事件"),a("th",null,"回调"),a("th",null,"最近投递"),a("th",null,"操作"))),a("tbody",null,m.map((T)=>a("tr",{key:T.id},a("td",null,a("strong",null,T.name||T.id),a("code",null,T.id||"--")),a("td",null,a(O3,{status:T.enabled?"online":"warn"},T.enabled?"enabled":"disabled")),a("td",null,Array.isArray(T.eventTypes)?T.eventTypes.join(", "):"message"),a("td",null,T.targetUrl||"--"),a("td",null,T.lastDelivery?`${T.lastDelivery.ok?"OK":"FAIL"} ${Nu(T.lastDelivery.at)}`:"--"),a("td",null,a("button",{type:"button",className:"ghost-btn",onClick:()=>J(T.id)},"删除"))))))),a("div",{className:"panel-actions inline-actions"},a(O_,{title:"ClaudeQQ Subscriptions",data:n.subscriptions,onOpen:f,testId:"raw-claudeqq-subscriptions"}))),a(Si,{title:"最近 QQ 事件",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Event Stream",loading:n.loading},X.length===0?a(H_,{title:"暂无事件",text:"等待 NapCat WebSocket 上报 QQ 消息事件,或通过订阅 API 消费后续事件"}):a("div",{className:"table-wrap","data-testid":"claudeqq-event-list"},a("table",null,a("thead",null,a("tr",null,a("th",null,"时间"),a("th",null,"类型"),a("th",null,"会话"),a("th",null,"消息"),a("th",null,"ID"))),a("tbody",null,X.map((T)=>a("tr",{key:T.id},a("td",null,Nu(T.receivedAt||T.timestamp)),a("td",null,a(O3,{status:T.postType||T.eventType},T.postType||T.eventType||"--")),a("td",null,iU(T)),a("td",null,nU(T)),a("td",null,a("code",null,T.messageId||T.id||"--"))))))),a("div",{className:"panel-actions inline-actions"},a(O_,{title:"ClaudeQQ Events",data:n.events,onOpen:f,testId:"raw-claudeqq-events"}))),a(Si,{title:"已发送消息",eyebrow:`${O.length} Sent`,loading:n.loading},O.length===0?a(H_,{title:"暂无发送记录",text:"发送日志来自 ClaudeQQ bot_workspace/messages/sent_messages.jsonl"}):a("div",{className:"table-wrap"},a("table",null,a("thead",null,a("tr",null,a("th",null,"时间"),a("th",null,"目标"),a("th",null,"消息"),a("th",null,"结果"))),a("tbody",null,O.map((T,S)=>a("tr",{key:T.id||S},a("td",null,Nu(T.timestamp||T.sentAt||T.createdAt)),a("td",null,iU(T)),a("td",null,nU(T)),a("td",null,T.status||T.messageId||T.message_id||"--")))))),a("div",{className:"panel-actions inline-actions"},a(O_,{title:"ClaudeQQ Sent Messages",data:n.sent,onOpen:f,testId:"raw-claudeqq-sent"})))))}var P_=Mu(Qf(),1);var tU=Mu(Qf(),1),Uf=tU.default.createElement;function cU({markdown:u,className:f,testId:l}){let r=String(u??"").trimEnd(),n=["markdown-body",f].filter(Boolean).join(" ");return Uf("div",{className:n,"data-testid":l},AU(r,"md"))}function AU(u,f){let l=iT(u).split(` -`),r=[],n=0;while(n\s?/u.test(i)){let j=[];while(n\s?(.*)$/u);if(U!==null){j.push(U[1]),n+=1;continue}if(F.trim().length===0){j.push(""),n+=1;continue}break}r.push(Uf("blockquote",{key:`${f}-quote-${n}`},AU(j.join(` -`),`${f}-quote-${n}`)));continue}if(FU(l,n)){let j=n,F=B_(l[n]??""),U=B_(l[n+1]??"");n+=2;let Q=[];while(n0)Q.push(B_(l[n]??"")),n+=1;r.push(cT(F,U,Q,`${f}-table-${j}`));continue}let $=V3(i);if($!==null){let j=n,F=$.ordered,U=$.start,Q=[];while(n$T(L,`${f}-list-${j}-${J}`))));continue}let c=n,A=[];while(n0&&!_T(l,n))A.push(l[n].trim()),n+=1;if(A.length===0)A.push(i.trim()),n+=1;r.push(Uf("p",{key:`${f}-p-${c}`},r0(A.join(` -`),`${f}-p-${c}`)))}return r}function iT(u){return String(u||"").replace(/\r\n/gu,` +`+i.stack}return{value:u,source:f,stack:n,digest:null}}function z4(u,f,l){return{value:u,source:null,stack:l!=null?l:null,digest:f!=null?f:null}}function $2(u,f){try{console.error(f.value)}catch(l){setTimeout(function(){throw l})}}var Uz=typeof WeakMap==="function"?WeakMap:Map;function NJ(u,f,l){l=G0(-1,l),l.tag=3,l.payload={element:null};var r=f.value;return l.callback=function(){yt||(yt=!0,N2=r),$2(u,f)},l}function WJ(u,f,l){l=G0(-1,l),l.tag=3;var r=u.type.getDerivedStateFromError;if(typeof r==="function"){var n=f.value;l.payload=function(){return r(n)},l.callback=function(){$2(u,f)}}var i=u.stateNode;return i!==null&&typeof i.componentDidCatch==="function"&&(l.callback=function(){$2(u,f),typeof r!=="function"&&($n===null?$n=new Set([this]):$n.add(this));var y=f.stack;this.componentDidCatch(f.value,{componentStack:y!==null?y:""})}),l}function Bj(u,f,l){var r=u.pingCache;if(r===null){r=u.pingCache=new Uz;var n=new Set;r.set(f,n)}else n=r.get(f),n===void 0&&(n=new Set,r.set(f,n));n.has(l)||(n.add(l),u=Hz.bind(null,u,f,l),f.then(u,u))}function Vj(u){do{var f;if(f=u.tag===13)f=u.memoizedState,f=f!==null?f.dehydrated!==null?!0:!1:!0;if(f)return u;u=u.return}while(u!==null);return null}function Dj(u,f,l,r,n){if((u.mode&1)===0)return u===f?u.flags|=65536:(u.flags|=128,l.flags|=131072,l.flags&=-52805,l.tag===1&&(l.alternate===null?l.tag=17:(f=G0(-1,1),f.tag=2,_n(l,f,1))),l.lanes|=1),u;return u.flags|=65536,u.lanes=n,u}var Qz=O0.ReactCurrentOwner,Cl=!1;function Ol(u,f,l,r){f.child=u===null?gF(f,null,l,r):Gi(f,u.child,l,r)}function Xj(u,f,l,r,n){l=l.render;var i=f.ref;if(Ni(f,n),r=a2(u,f,l,r,i,n),l=o2(),u!==null&&!Cl)return f.updateQueue=u.updateQueue,f.flags&=-2053,u.lanes&=~n,Z0(u,f,n);return Ef&&l&&P2(f),f.flags|=1,Ol(u,f,r,n),f.child}function Yj(u,f,l,r,n){if(u===null){var i=l.type;if(typeof i==="function"&&!_5(i)&&i.defaultProps===void 0&&l.compare===null&&l.defaultProps===void 0)return f.tag=15,f.type=i,LJ(u,f,i,r,n);return u=M3(l.type,null,r,f,f.mode,n),u.ref=f.ref,u.return=f,f.child=u}if(i=u.child,(u.lanes&n)===0){var y=i.memoizedProps;if(l=l.compare,l=l!==null?l:t_,l(y,r)&&u.ref===f.ref)return Z0(u,f,n)}return f.flags|=1,u=An(i,r),u.ref=f.ref,u.return=f,f.child=u}function LJ(u,f,l,r,n){if(u!==null){var i=u.memoizedProps;if(t_(i,r)&&u.ref===f.ref)if(Cl=!1,f.pendingProps=r=i,(u.lanes&n)!==0)(u.flags&131072)!==0&&(Cl=!0);else return f.lanes=u.lanes,Z0(u,f,n)}return t2(u,f,l,r,n)}function wJ(u,f,l){var r=f.pendingProps,n=r.children,i=u!==null?u.memoizedState:null;if(r.mode==="hidden")if((f.mode&1)===0)f.memoizedState={baseLanes:0,cachePool:null,transitions:null},Wf(Fi,ir),ir|=l;else{if((l&1073741824)===0)return u=i!==null?i.baseLanes|l:l,f.lanes=f.childLanes=1073741824,f.memoizedState={baseLanes:u,cachePool:null,transitions:null},f.updateQueue=null,Wf(Fi,ir),ir|=u,null;f.memoizedState={baseLanes:0,cachePool:null,transitions:null},r=i!==null?i.baseLanes:l,Wf(Fi,ir),ir|=r}else i!==null?(r=i.baseLanes|l,f.memoizedState=null):r=l,Wf(Fi,ir),ir|=r;return Ol(u,f,n,l),f.child}function KJ(u,f){var l=f.ref;if(u===null&&l!==null||u!==null&&u.ref!==l)f.flags|=512,f.flags|=2097152}function t2(u,f,l,r,n){var i=xl(l)?y1:Ll.current;if(i=wi(f,i),Ni(f,n),l=a2(u,f,l,r,i,n),r=o2(),u!==null&&!Cl)return f.updateQueue=u.updateQueue,f.flags&=-2053,u.lanes&=~n,Z0(u,f,n);return Ef&&r&&P2(f),f.flags|=1,Ol(u,f,l,n),f.child}function Sj(u,f,l,r,n){if(xl(l)){var i=!0;a3(f)}else i=!1;if(Ni(f,n),f.stateNode===null)p3(u,f),qJ(f,l,r),_2(f,l,r,n),r=!0;else if(u===null){var{stateNode:y,memoizedProps:_}=f;y.props=_;var $=y.context,A=l.contextType;typeof A==="object"&&A!==null?A=zr(A):(A=xl(l)?y1:Ll.current,A=wi(f,A));var c=l.getDerivedStateFromProps,j=typeof c==="function"||typeof y.getSnapshotBeforeUpdate==="function";j||typeof y.UNSAFE_componentWillReceiveProps!=="function"&&typeof y.componentWillReceiveProps!=="function"||(_!==r||$!==A)&&Hj(f,y,r,A),o0=!1;var F=f.memoizedState;y.state=F,ft(f,r,y,n),$=f.memoizedState,_!==r||F!==$||Rl.current||o0?(typeof c==="function"&&(y2(f,l,c,r),$=f.memoizedState),(_=o0||Oj(f,l,_,r,F,$,A))?(j||typeof y.UNSAFE_componentWillMount!=="function"&&typeof y.componentWillMount!=="function"||(typeof y.componentWillMount==="function"&&y.componentWillMount(),typeof y.UNSAFE_componentWillMount==="function"&&y.UNSAFE_componentWillMount()),typeof y.componentDidMount==="function"&&(f.flags|=4194308)):(typeof y.componentDidMount==="function"&&(f.flags|=4194308),f.memoizedProps=r,f.memoizedState=$),y.props=r,y.state=$,y.context=A,r=_):(typeof y.componentDidMount==="function"&&(f.flags|=4194308),r=!1)}else{y=f.stateNode,aF(u,f),_=f.memoizedProps,A=f.type===f.elementType?_:Sr(f.type,_),y.props=A,j=f.pendingProps,F=y.context,$=l.contextType,typeof $==="object"&&$!==null?$=zr($):($=xl(l)?y1:Ll.current,$=wi(f,$));var U=l.getDerivedStateFromProps;(c=typeof U==="function"||typeof y.getSnapshotBeforeUpdate==="function")||typeof y.UNSAFE_componentWillReceiveProps!=="function"&&typeof y.componentWillReceiveProps!=="function"||(_!==j||F!==$)&&Hj(f,y,r,$),o0=!1,F=f.memoizedState,y.state=F,ft(f,r,y,n);var Q=f.memoizedState;_!==j||F!==Q||Rl.current||o0?(typeof U==="function"&&(y2(f,l,U,r),Q=f.memoizedState),(A=o0||Oj(f,l,A,r,F,Q,$)||!1)?(c||typeof y.UNSAFE_componentWillUpdate!=="function"&&typeof y.componentWillUpdate!=="function"||(typeof y.componentWillUpdate==="function"&&y.componentWillUpdate(r,Q,$),typeof y.UNSAFE_componentWillUpdate==="function"&&y.UNSAFE_componentWillUpdate(r,Q,$)),typeof y.componentDidUpdate==="function"&&(f.flags|=4),typeof y.getSnapshotBeforeUpdate==="function"&&(f.flags|=1024)):(typeof y.componentDidUpdate!=="function"||_===u.memoizedProps&&F===u.memoizedState||(f.flags|=4),typeof y.getSnapshotBeforeUpdate!=="function"||_===u.memoizedProps&&F===u.memoizedState||(f.flags|=1024),f.memoizedProps=r,f.memoizedState=Q),y.props=r,y.state=Q,y.context=$,r=A):(typeof y.componentDidUpdate!=="function"||_===u.memoizedProps&&F===u.memoizedState||(f.flags|=4),typeof y.getSnapshotBeforeUpdate!=="function"||_===u.memoizedProps&&F===u.memoizedState||(f.flags|=1024),r=!1)}return A2(u,f,l,r,i,n)}function A2(u,f,l,r,n,i){KJ(u,f);var y=(f.flags&128)!==0;if(!r&&!y)return n&&Lj(f,l,!1),Z0(u,f,i);r=f.stateNode,Qz.current=f;var _=y&&typeof l.getDerivedStateFromError!=="function"?null:r.render();return f.flags|=1,u!==null&&y?(f.child=Gi(f,u.child,null,i),f.child=Gi(f,null,_,i)):Ol(u,f,_,i),f.memoizedState=r.state,n&&Lj(f,l,!0),f.child}function GJ(u){var f=u.stateNode;f.pendingContext?Wj(u,f.pendingContext,f.pendingContext!==f.context):f.context&&Wj(u,f.context,!1),k2(u,f.containerInfo)}function pj(u,f,l,r,n){return Ki(),C2(n),f.flags|=256,Ol(u,f,l,r),f.child}var c2={dehydrated:null,treeContext:null,retryLane:0};function j2(u){return{baseLanes:u,cachePool:null,transitions:null}}function zJ(u,f,l){var r=f.pendingProps,n=Of.current,i=!1,y=(f.flags&128)!==0,_;if((_=y)||(_=u!==null&&u.memoizedState===null?!1:(n&2)!==0),_)i=!0,f.flags&=-129;else if(u===null||u.memoizedState!==null)n|=1;if(Wf(Of,n&1),u===null){if(n2(f),u=f.memoizedState,u!==null&&(u=u.dehydrated,u!==null))return(f.mode&1)===0?f.lanes=1:u.data==="$!"?f.lanes=8:f.lanes=1073741824,null;return y=r.children,u=r.fallback,i?(r=f.mode,i=f.child,y={mode:"hidden",children:y},(r&1)===0&&i!==null?(i.childLanes=0,i.pendingProps=y):i=Lt(y,r,0,null),u=i1(u,r,l,null),i.return=f,u.return=f,i.sibling=u,f.child=i,f.child.memoizedState=j2(l),f.memoizedState=c2,u):u5(f,y)}if(n=u.memoizedState,n!==null&&(_=n.dehydrated,_!==null))return qz(u,f,y,r,_,n,l);if(i){i=r.fallback,y=f.mode,n=u.child,_=n.sibling;var $={mode:"hidden",children:r.children};return(y&1)===0&&f.child!==n?(r=f.child,r.childLanes=0,r.pendingProps=$,f.deletions=null):(r=An(n,$),r.subtreeFlags=n.subtreeFlags&14680064),_!==null?i=An(_,i):(i=i1(i,y,l,null),i.flags|=2),i.return=f,r.return=f,r.sibling=i,f.child=r,r=i,i=f.child,y=u.child.memoizedState,y=y===null?j2(l):{baseLanes:y.baseLanes|l,cachePool:null,transitions:y.transitions},i.memoizedState=y,i.childLanes=u.childLanes&~l,f.memoizedState=c2,r}return i=u.child,u=i.sibling,r=An(i,{mode:"visible",children:r.children}),(f.mode&1)===0&&(r.lanes=l),r.return=f,r.sibling=null,u!==null&&(l=f.deletions,l===null?(f.deletions=[u],f.flags|=16):l.push(u)),f.child=r,f.memoizedState=null,r}function u5(u,f){return f=Lt({mode:"visible",children:f},u.mode,0,null),f.return=u,u.child=f}function E3(u,f,l,r){return r!==null&&C2(r),Gi(f,u.child,null,l),u=u5(f,f.pendingProps.children),u.flags|=2,f.memoizedState=null,u}function qz(u,f,l,r,n,i,y){if(l){if(f.flags&256)return f.flags&=-257,r=z4(Error(Uu(422))),E3(u,f,y,r);if(f.memoizedState!==null)return f.child=u.child,f.flags|=128,null;return i=r.fallback,n=f.mode,r=Lt({mode:"visible",children:r.children},n,0,null),i=i1(i,n,y,null),i.flags|=2,r.return=f,i.return=f,r.sibling=i,f.child=r,(f.mode&1)!==0&&Gi(f,u.child,null,y),f.child.memoizedState=j2(y),f.memoizedState=c2,i}if((f.mode&1)===0)return E3(u,f,y,null);if(n.data==="$!"){if(r=n.nextSibling&&n.nextSibling.dataset,r)var _=r.dgst;return r=_,i=Error(Uu(419)),r=z4(i,r,void 0),E3(u,f,y,r)}if(_=(y&u.childLanes)!==0,Cl||_){if(r=fl,r!==null){switch(y&-y){case 4:n=2;break;case 16:n=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:n=32;break;case 536870912:n=268435456;break;default:n=0}n=(n&(r.suspendedLanes|y))!==0?0:n,n!==0&&n!==i.retryLane&&(i.retryLane=n,E0(u,n),Mr(r,u,n,-1))}return y5(),r=z4(Error(Uu(421))),E3(u,f,y,r)}if(n.data==="$?")return f.flags|=128,f.child=u.child,f=Bz.bind(null,u),n._reactRetry=f,null;return u=i.treeContext,yr=yn(n.nextSibling),_r=f,Ef=!0,mr=null,u!==null&&(Lr[wr++]=w0,Lr[wr++]=K0,Lr[wr++]=_1,w0=u.id,K0=u.overflow,_1=f),f=u5(f,r.children),f.flags|=4096,f}function mj(u,f,l){u.lanes|=f;var r=u.alternate;r!==null&&(r.lanes|=f),i2(u.return,f,l)}function T4(u,f,l,r,n){var i=u.memoizedState;i===null?u.memoizedState={isBackwards:f,rendering:null,renderingStartTime:0,last:r,tail:l,tailMode:n}:(i.isBackwards=f,i.rendering=null,i.renderingStartTime=0,i.last=r,i.tail=l,i.tailMode=n)}function TJ(u,f,l){var r=f.pendingProps,n=r.revealOrder,i=r.tail;if(Ol(u,f,r.children,l),r=Of.current,(r&2)!==0)r=r&1|2,f.flags|=128;else{if(u!==null&&(u.flags&128)!==0)u:for(u=f.child;u!==null;){if(u.tag===13)u.memoizedState!==null&&mj(u,l,f);else if(u.tag===19)mj(u,l,f);else if(u.child!==null){u.child.return=u,u=u.child;continue}if(u===f)break u;for(;u.sibling===null;){if(u.return===null||u.return===f)break u;u=u.return}u.sibling.return=u.return,u=u.sibling}r&=1}if(Wf(Of,r),(f.mode&1)===0)f.memoizedState=null;else switch(n){case"forwards":l=f.child;for(n=null;l!==null;)u=l.alternate,u!==null&<(u)===null&&(n=l),l=l.sibling;l=n,l===null?(n=f.child,f.child=null):(n=l.sibling,l.sibling=null),T4(f,!1,n,l,i);break;case"backwards":l=null,n=f.child;for(f.child=null;n!==null;){if(u=n.alternate,u!==null&<(u)===null){f.child=n;break}u=n.sibling,n.sibling=l,l=n,n=u}T4(f,!0,l,null,i);break;case"together":T4(f,!1,null,null,void 0);break;default:f.memoizedState=null}return f.child}function p3(u,f){(f.mode&1)===0&&u!==null&&(u.alternate=null,f.alternate=null,f.flags|=2)}function Z0(u,f,l){if(u!==null&&(f.dependencies=u.dependencies),t1|=f.lanes,(l&f.childLanes)===0)return null;if(u!==null&&f.child!==u.child)throw Error(Uu(153));if(f.child!==null){u=f.child,l=An(u,u.pendingProps),f.child=l;for(l.return=f;u.sibling!==null;)u=u.sibling,l=l.sibling=An(u,u.pendingProps),l.return=f;l.sibling=null}return f.child}function Nz(u,f,l){switch(f.tag){case 3:GJ(f),Ki();break;case 5:oF(f);break;case 1:xl(f.type)&&a3(f);break;case 4:k2(f,f.stateNode.containerInfo);break;case 10:var r=f.type._context,n=f.memoizedProps.value;Wf(e3,r._currentValue),r._currentValue=n;break;case 13:if(r=f.memoizedState,r!==null){if(r.dehydrated!==null)return Wf(Of,Of.current&1),f.flags|=128,null;if((l&f.child.childLanes)!==0)return zJ(u,f,l);return Wf(Of,Of.current&1),u=Z0(u,f,l),u!==null?u.sibling:null}Wf(Of,Of.current&1);break;case 19:if(r=(l&f.childLanes)!==0,(u.flags&128)!==0){if(r)return TJ(u,f,l);f.flags|=128}if(n=f.memoizedState,n!==null&&(n.rendering=null,n.tail=null,n.lastEffect=null),Wf(Of,Of.current),r)break;else return null;case 22:case 23:return f.lanes=0,wJ(u,f,l)}return Z0(u,f,l)}var EJ,F2,ZJ,OJ;EJ=function(u,f){for(var l=f.child;l!==null;){if(l.tag===5||l.tag===6)u.appendChild(l.stateNode);else if(l.tag!==4&&l.child!==null){l.child.return=l,l=l.child;continue}if(l===f)break;for(;l.sibling===null;){if(l.return===null||l.return===f)return;l=l.return}l.sibling.return=l.return,l=l.sibling}};F2=function(){};ZJ=function(u,f,l,r){var n=u.memoizedProps;if(n!==r){u=f.stateNode,r1(l0.current);var i=null;switch(l){case"input":n=X4(u,n),r=X4(u,r),i=[];break;case"select":n=Bf({},n,{value:void 0}),r=Bf({},r,{value:void 0}),i=[];break;case"textarea":n=p4(u,n),r=p4(u,r),i=[];break;default:typeof n.onClick!=="function"&&typeof r.onClick==="function"&&(u.onclick=g3)}P4(l,r);var y;l=null;for(A in n)if(!r.hasOwnProperty(A)&&n.hasOwnProperty(A)&&n[A]!=null)if(A==="style"){var _=n[A];for(y in _)_.hasOwnProperty(y)&&(l||(l={}),l[y]="")}else A!=="dangerouslySetInnerHTML"&&A!=="children"&&A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&A!=="autoFocus"&&(l_.hasOwnProperty(A)?i||(i=[]):(i=i||[]).push(A,null));for(A in r){var $=r[A];if(_=n!=null?n[A]:void 0,r.hasOwnProperty(A)&&$!==_&&($!=null||_!=null))if(A==="style")if(_){for(y in _)!_.hasOwnProperty(y)||$&&$.hasOwnProperty(y)||(l||(l={}),l[y]="");for(y in $)$.hasOwnProperty(y)&&_[y]!==$[y]&&(l||(l={}),l[y]=$[y])}else l||(i||(i=[]),i.push(A,l)),l=$;else A==="dangerouslySetInnerHTML"?($=$?$.__html:void 0,_=_?_.__html:void 0,$!=null&&_!==$&&(i=i||[]).push(A,$)):A==="children"?typeof $!=="string"&&typeof $!=="number"||(i=i||[]).push(A,""+$):A!=="suppressContentEditableWarning"&&A!=="suppressHydrationWarning"&&(l_.hasOwnProperty(A)?($!=null&&A==="onScroll"&&Kf("scroll",u),i||_===$||(i=[])):(i=i||[]).push(A,$))}l&&(i=i||[]).push("style",l);var A=i;if(f.updateQueue=A)f.flags|=4}};OJ=function(u,f,l,r){l!==r&&(f.flags|=4)};function my(u,f){if(!Ef)switch(u.tailMode){case"hidden":f=u.tail;for(var l=null;f!==null;)f.alternate!==null&&(l=f),f=f.sibling;l===null?u.tail=null:l.sibling=null;break;case"collapsed":l=u.tail;for(var r=null;l!==null;)l.alternate!==null&&(r=l),l=l.sibling;r===null?f||u.tail===null?u.tail=null:u.tail.sibling=null:r.sibling=null}}function Nl(u){var f=u.alternate!==null&&u.alternate.child===u.child,l=0,r=0;if(f)for(var n=u.child;n!==null;)l|=n.lanes|n.childLanes,r|=n.subtreeFlags&14680064,r|=n.flags&14680064,n.return=u,n=n.sibling;else for(n=u.child;n!==null;)l|=n.lanes|n.childLanes,r|=n.subtreeFlags,r|=n.flags,n.return=u,n=n.sibling;return u.subtreeFlags|=r,u.childLanes=l,f}function Wz(u,f,l){var r=f.pendingProps;switch(M2(f),f.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Nl(f),null;case 1:return xl(f.type)&&s3(),Nl(f),null;case 3:if(r=f.stateNode,zi(),Gf(Rl),Gf(Ll),g2(),r.pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),u===null||u.child===null)z3(f)?f.flags|=4:u===null||u.memoizedState.isDehydrated&&(f.flags&256)===0||(f.flags|=1024,mr!==null&&(w2(mr),mr=null));return F2(u,f),Nl(f),null;case 5:I2(f);var n=r1(J_.current);if(l=f.type,u!==null&&f.stateNode!=null)ZJ(u,f,l,r,n),u.ref!==f.ref&&(f.flags|=512,f.flags|=2097152);else{if(!r){if(f.stateNode===null)throw Error(Uu(166));return Nl(f),null}if(u=r1(l0.current),z3(f)){r=f.stateNode,l=f.type;var i=f.memoizedProps;switch(r[u0]=f,r[j_]=i,u=(f.mode&1)!==0,l){case"dialog":Kf("cancel",r),Kf("close",r);break;case"iframe":case"object":case"embed":Kf("load",r);break;case"video":case"audio":for(n=0;n",u=u.removeChild(u.firstChild)):typeof r.is==="string"?u=y.createElement(l,{is:r.is}):(u=y.createElement(l),l==="select"&&(y=u,r.multiple?y.multiple=!0:r.size&&(y.size=r.size))):u=y.createElementNS(u,l),u[u0]=f,u[j_]=r,EJ(u,f,!1,!1),f.stateNode=u;u:{switch(y=M4(l,r),l){case"dialog":Kf("cancel",u),Kf("close",u),n=r;break;case"iframe":case"object":case"embed":Kf("load",u),n=r;break;case"video":case"audio":for(n=0;nEi&&(f.flags|=128,r=!0,my(i,!1),f.lanes=4194304)}else{if(!r)if(u=lt(y),u!==null){if(f.flags|=128,r=!0,l=u.updateQueue,l!==null&&(f.updateQueue=l,f.flags|=4),my(i,!0),i.tail===null&&i.tailMode==="hidden"&&!y.alternate&&!Ef)return Nl(f),null}else 2*mf()-i.renderingStartTime>Ei&&l!==1073741824&&(f.flags|=128,r=!0,my(i,!1),f.lanes=4194304);i.isBackwards?(y.sibling=f.child,f.child=y):(l=i.last,l!==null?l.sibling=y:f.child=y,i.last=y)}if(i.tail!==null)return f=i.tail,i.rendering=f,i.tail=f.sibling,i.renderingStartTime=mf(),f.sibling=null,l=Of.current,Wf(Of,r?l&1|2:l&1),f;return Nl(f),null;case 22:case 23:return i5(),r=f.memoizedState!==null,u!==null&&u.memoizedState!==null!==r&&(f.flags|=8192),r&&(f.mode&1)!==0?(ir&1073741824)!==0&&(Nl(f),f.subtreeFlags&6&&(f.flags|=8192)):Nl(f),null;case 24:return null;case 25:return null}throw Error(Uu(156,f.tag))}function Lz(u,f){switch(M2(f),f.tag){case 1:return xl(f.type)&&s3(),u=f.flags,u&65536?(f.flags=u&-65537|128,f):null;case 3:return zi(),Gf(Rl),Gf(Ll),g2(),u=f.flags,(u&65536)!==0&&(u&128)===0?(f.flags=u&-65537|128,f):null;case 5:return I2(f),null;case 13:if(Gf(Of),u=f.memoizedState,u!==null&&u.dehydrated!==null){if(f.alternate===null)throw Error(Uu(340));Ki()}return u=f.flags,u&65536?(f.flags=u&-65537|128,f):null;case 19:return Gf(Of),null;case 4:return zi(),null;case 10:return h2(f.type._context),null;case 22:case 23:return i5(),null;case 24:return null;default:return null}}var Z3=!1,Wl=!1,wz=typeof WeakSet==="function"?WeakSet:Set,zu=null;function ji(u,f){var l=u.ref;if(l!==null)if(typeof l==="function")try{l(null)}catch(r){Df(u,f,r)}else l.current=null}function J2(u,f,l){try{l()}catch(r){Df(u,f,r)}}var Pj=!1;function Kz(u,f){if(o4=v3,u=XF(),m2(u)){if("selectionStart"in u)var l={start:u.selectionStart,end:u.selectionEnd};else u:{l=(l=u.ownerDocument)&&l.defaultView||window;var r=l.getSelection&&l.getSelection();if(r&&r.rangeCount!==0){l=r.anchorNode;var{anchorOffset:n,focusNode:i}=r;r=r.focusOffset;try{l.nodeType,i.nodeType}catch(W){l=null;break u}var y=0,_=-1,$=-1,A=0,c=0,j=u,F=null;f:for(;;){for(var U;;){if(j!==l||n!==0&&j.nodeType!==3||(_=y+n),j!==i||r!==0&&j.nodeType!==3||($=y+r),j.nodeType===3&&(y+=j.nodeValue.length),(U=j.firstChild)===null)break;F=j,j=U}for(;;){if(j===u)break f;if(F===l&&++A===n&&(_=y),F===i&&++c===r&&($=y),(U=j.nextSibling)!==null)break;j=F,F=j.parentNode}j=U}l=_===-1||$===-1?null:{start:_,end:$}}else l=null}l=l||{start:0,end:0}}else l=null;d4={focusedElem:u,selectionRange:l},v3=!1;for(zu=f;zu!==null;)if(f=zu,u=f.child,(f.subtreeFlags&1028)!==0&&u!==null)u.return=f,zu=u;else for(;zu!==null;){f=zu;try{var Q=f.alternate;if((f.flags&1024)!==0)switch(f.tag){case 0:case 11:case 15:break;case 1:if(Q!==null){var{memoizedProps:L,memoizedState:w}=Q,J=f.stateNode,N=J.getSnapshotBeforeUpdate(f.elementType===f.type?L:Sr(f.type,L),w);J.__reactInternalSnapshotBeforeUpdate=N}break;case 3:var q=f.stateNode.containerInfo;q.nodeType===1?q.textContent="":q.nodeType===9&&q.documentElement&&q.removeChild(q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(Uu(163))}}catch(W){Df(f,f.return,W)}if(u=f.sibling,u!==null){u.return=f.return,zu=u;break}zu=f.return}return Q=Pj,Pj=!1,Q}function ey(u,f,l){var r=f.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var n=r=r.next;do{if((n.tag&u)===u){var i=n.destroy;n.destroy=void 0,i!==void 0&&J2(f,l,i)}n=n.next}while(n!==r)}}function Nt(u,f){if(f=f.updateQueue,f=f!==null?f.lastEffect:null,f!==null){var l=f=f.next;do{if((l.tag&u)===u){var r=l.create;l.destroy=r()}l=l.next}while(l!==f)}}function U2(u){var f=u.ref;if(f!==null){var l=u.stateNode;switch(u.tag){case 5:u=l;break;default:u=l}typeof f==="function"?f(u):f.current=u}}function HJ(u){var f=u.alternate;f!==null&&(u.alternate=null,HJ(f)),u.child=null,u.deletions=null,u.sibling=null,u.tag===5&&(f=u.stateNode,f!==null&&(delete f[u0],delete f[j_],delete f[f2],delete f[nz],delete f[iz])),u.stateNode=null,u.return=null,u.dependencies=null,u.memoizedProps=null,u.memoizedState=null,u.pendingProps=null,u.stateNode=null,u.updateQueue=null}function BJ(u){return u.tag===5||u.tag===3||u.tag===4}function Mj(u){u:for(;;){for(;u.sibling===null;){if(u.return===null||BJ(u.return))return null;u=u.return}u.sibling.return=u.return;for(u=u.sibling;u.tag!==5&&u.tag!==6&&u.tag!==18;){if(u.flags&2)continue u;if(u.child===null||u.tag===4)continue u;else u.child.return=u,u=u.child}if(!(u.flags&2))return u.stateNode}}function Q2(u,f,l){var r=u.tag;if(r===5||r===6)u=u.stateNode,f?l.nodeType===8?l.parentNode.insertBefore(u,f):l.insertBefore(u,f):(l.nodeType===8?(f=l.parentNode,f.insertBefore(u,l)):(f=l,f.appendChild(u)),l=l._reactRootContainer,l!==null&&l!==void 0||f.onclick!==null||(f.onclick=g3));else if(r!==4&&(u=u.child,u!==null))for(Q2(u,f,l),u=u.sibling;u!==null;)Q2(u,f,l),u=u.sibling}function q2(u,f,l){var r=u.tag;if(r===5||r===6)u=u.stateNode,f?l.insertBefore(u,f):l.appendChild(u);else if(r!==4&&(u=u.child,u!==null))for(q2(u,f,l),u=u.sibling;u!==null;)q2(u,f,l),u=u.sibling}var $l=null,pr=!1;function s0(u,f,l){for(l=l.child;l!==null;)VJ(u,f,l),l=l.sibling}function VJ(u,f,l){if(f0&&typeof f0.onCommitFiberUnmount==="function")try{f0.onCommitFiberUnmount(At,l)}catch(_){}switch(l.tag){case 5:Wl||ji(l,f);case 6:var r=$l,n=pr;$l=null,s0(u,f,l),$l=r,pr=n,$l!==null&&(pr?(u=$l,l=l.stateNode,u.nodeType===8?u.parentNode.removeChild(l):u.removeChild(l)):$l.removeChild(l.stateNode));break;case 18:$l!==null&&(pr?(u=$l,l=l.stateNode,u.nodeType===8?N4(u.parentNode,l):u.nodeType===1&&N4(u,l),__(u)):N4($l,l.stateNode));break;case 4:r=$l,n=pr,$l=l.stateNode.containerInfo,pr=!0,s0(u,f,l),$l=r,pr=n;break;case 0:case 11:case 14:case 15:if(!Wl&&(r=l.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){n=r=r.next;do{var i=n,y=i.destroy;i=i.tag,y!==void 0&&((i&2)!==0?J2(l,f,y):(i&4)!==0&&J2(l,f,y)),n=n.next}while(n!==r)}s0(u,f,l);break;case 1:if(!Wl&&(ji(l,f),r=l.stateNode,typeof r.componentWillUnmount==="function"))try{r.props=l.memoizedProps,r.state=l.memoizedState,r.componentWillUnmount()}catch(_){Df(l,f,_)}s0(u,f,l);break;case 21:s0(u,f,l);break;case 22:l.mode&1?(Wl=(r=Wl)||l.memoizedState!==null,s0(u,f,l),Wl=r):s0(u,f,l);break;default:s0(u,f,l)}}function Cj(u){var f=u.updateQueue;if(f!==null){u.updateQueue=null;var l=u.stateNode;l===null&&(l=u.stateNode=new wz),f.forEach(function(r){var n=Vz.bind(null,u,r);l.has(r)||(l.add(r),r.then(n,n))})}}function Yr(u,f){var l=f.deletions;if(l!==null)for(var r=0;rn&&(n=y),r&=~i}if(r=n,r=mf()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3000>r?3000:4320>r?4320:1960*zz(r/1960))-r,10u?16:u,fn===null)var r=!1;else{if(u=fn,fn=null,_t=0,(lf&6)!==0)throw Error(Uu(331));var n=lf;lf|=4;for(zu=u.current;zu!==null;){var i=zu,y=i.child;if((zu.flags&16)!==0){var _=i.deletions;if(_!==null){for(var $=0;$<_.length;$++){var A=_[$];for(zu=A;zu!==null;){var c=zu;switch(c.tag){case 0:case 11:case 15:ey(8,c,i)}var j=c.child;if(j!==null)j.return=c,zu=j;else for(;zu!==null;){c=zu;var{sibling:F,return:U}=c;if(HJ(c),c===A){zu=null;break}if(F!==null){F.return=U,zu=F;break}zu=U}}}var Q=i.alternate;if(Q!==null){var L=Q.child;if(L!==null){Q.child=null;do{var w=L.sibling;L.sibling=null,L=w}while(L!==null)}}zu=i}}if((i.subtreeFlags&2064)!==0&&y!==null)y.return=i,zu=y;else u:for(;zu!==null;){if(i=zu,(i.flags&2048)!==0)switch(i.tag){case 0:case 11:case 15:ey(9,i,i.return)}var J=i.sibling;if(J!==null){J.return=i.return,zu=J;break u}zu=i.return}}var N=u.current;for(zu=N;zu!==null;){y=zu;var q=y.child;if((y.subtreeFlags&2064)!==0&&q!==null)q.return=y,zu=q;else u:for(y=N;zu!==null;){if(_=zu,(_.flags&2048)!==0)try{switch(_.tag){case 0:case 11:case 15:Nt(9,_)}}catch(z){Df(_,_.return,z)}if(_===y){zu=null;break u}var W=_.sibling;if(W!==null){W.return=_.return,zu=W;break u}zu=_.return}}if(lf=n,Un(),f0&&typeof f0.onPostCommitFiberRoot==="function")try{f0.onPostCommitFiberRoot(At,u)}catch(z){}r=!0}return r}finally{Af=l,Gr.transition=f}}return!1}function vj(u,f,l){f=Ti(l,f),f=NJ(u,f,1),u=_n(u,f,1),f=Hl(),u!==null&&(W_(u,1,f),hl(u,f))}function Df(u,f,l){if(u.tag===3)vj(u,u,l);else for(;f!==null;){if(f.tag===3){vj(f,u,l);break}else if(f.tag===1){var r=f.stateNode;if(typeof f.type.getDerivedStateFromError==="function"||typeof r.componentDidCatch==="function"&&($n===null||!$n.has(r))){u=Ti(l,u),u=WJ(f,u,1),f=_n(f,u,1),u=Hl(),f!==null&&(W_(f,1,u),hl(f,u));break}}f=f.return}}function Hz(u,f,l){var r=u.pingCache;r!==null&&r.delete(f),f=Hl(),u.pingedLanes|=u.suspendedLanes&l,fl===u&&(tl&l)===l&&(sf===4||sf===3&&(tl&130023424)===tl&&500>mf()-r5?n1(u,0):l5|=l),hl(u,f)}function MJ(u,f){f===0&&((u.mode&1)===0?f=1:(f=N3,N3<<=1,(N3&130023424)===0&&(N3=4194304)));var l=Hl();u=E0(u,f),u!==null&&(W_(u,f,l),hl(u,l))}function Bz(u){var f=u.memoizedState,l=0;f!==null&&(l=f.retryLane),MJ(u,l)}function Vz(u,f){var l=0;switch(u.tag){case 13:var{stateNode:r,memoizedState:n}=u;n!==null&&(l=n.retryLane);break;case 19:r=u.stateNode;break;default:throw Error(Uu(314))}r!==null&&r.delete(f),MJ(u,l)}var CJ;CJ=function(u,f,l){if(u!==null)if(u.memoizedProps!==f.pendingProps||Rl.current)Cl=!0;else{if((u.lanes&l)===0&&(f.flags&128)===0)return Cl=!1,Nz(u,f,l);Cl=(u.flags&131072)!==0?!0:!1}else Cl=!1,Ef&&(f.flags&1048576)!==0&&bF(f,d3,f.index);switch(f.lanes=0,f.tag){case 2:var r=f.type;p3(u,f),u=f.pendingProps;var n=wi(f,Ll.current);Ni(f,l),n=a2(null,f,r,u,n,l);var i=o2();return f.flags|=1,typeof n==="object"&&n!==null&&typeof n.render==="function"&&n.$$typeof===void 0?(f.tag=1,f.memoizedState=null,f.updateQueue=null,xl(r)?(i=!0,a3(f)):i=!1,f.memoizedState=n.state!==null&&n.state!==void 0?n.state:null,v2(f),n.updater=qt,f.stateNode=n,n._reactInternals=f,_2(f,r,u,l),f=A2(null,f,r,!0,i,l)):(f.tag=0,Ef&&i&&P2(f),Ol(null,f,n,l),f=f.child),f;case 16:r=f.elementType;u:{switch(p3(u,f),u=f.pendingProps,n=r._init,r=n(r._payload),f.type=r,n=f.tag=Xz(r),u=Sr(r,u),n){case 0:f=t2(null,f,r,u,l);break u;case 1:f=Sj(null,f,r,u,l);break u;case 11:f=Xj(null,f,r,u,l);break u;case 14:f=Yj(null,f,r,Sr(r.type,u),l);break u}throw Error(Uu(306,r,""))}return f;case 0:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),t2(u,f,r,n,l);case 1:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),Sj(u,f,r,n,l);case 3:u:{if(GJ(f),u===null)throw Error(Uu(387));r=f.pendingProps,i=f.memoizedState,n=i.element,aF(u,f),ft(f,r,null,l);var y=f.memoizedState;if(r=y.element,i.isDehydrated)if(i={element:r,isDehydrated:!1,cache:y.cache,pendingSuspenseBoundaries:y.pendingSuspenseBoundaries,transitions:y.transitions},f.updateQueue.baseState=i,f.memoizedState=i,f.flags&256){n=Ti(Error(Uu(423)),f),f=pj(u,f,r,l,n);break u}else if(r!==n){n=Ti(Error(Uu(424)),f),f=pj(u,f,r,l,n);break u}else for(yr=yn(f.stateNode.containerInfo.firstChild),_r=f,Ef=!0,mr=null,l=gF(f,null,r,l),f.child=l;l;)l.flags=l.flags&-3|4096,l=l.sibling;else{if(Ki(),r===n){f=Z0(u,f,l);break u}Ol(u,f,r,l)}f=f.child}return f;case 5:return oF(f),u===null&&n2(f),r=f.type,n=f.pendingProps,i=u!==null?u.memoizedProps:null,y=n.children,e4(r,n)?y=null:i!==null&&e4(r,i)&&(f.flags|=32),KJ(u,f),Ol(u,f,y,l),f.child;case 6:return u===null&&n2(f),null;case 13:return zJ(u,f,l);case 4:return k2(f,f.stateNode.containerInfo),r=f.pendingProps,u===null?f.child=Gi(f,null,r,l):Ol(u,f,r,l),f.child;case 11:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),Xj(u,f,r,n,l);case 7:return Ol(u,f,f.pendingProps,l),f.child;case 8:return Ol(u,f,f.pendingProps.children,l),f.child;case 12:return Ol(u,f,f.pendingProps.children,l),f.child;case 10:u:{if(r=f.type._context,n=f.pendingProps,i=f.memoizedProps,y=n.value,Wf(e3,r._currentValue),r._currentValue=y,i!==null)if(Cr(i.value,y)){if(i.children===n.children&&!Rl.current){f=Z0(u,f,l);break u}}else for(i=f.child,i!==null&&(i.return=f);i!==null;){var _=i.dependencies;if(_!==null){y=i.child;for(var $=_.firstContext;$!==null;){if($.context===r){if(i.tag===1){$=G0(-1,l&-l),$.tag=2;var A=i.updateQueue;if(A!==null){A=A.shared;var c=A.pending;c===null?$.next=$:($.next=c.next,c.next=$),A.pending=$}}i.lanes|=l,$=i.alternate,$!==null&&($.lanes|=l),i2(i.return,l,f),_.lanes|=l;break}$=$.next}}else if(i.tag===10)y=i.type===f.type?null:i.child;else if(i.tag===18){if(y=i.return,y===null)throw Error(Uu(341));y.lanes|=l,_=y.alternate,_!==null&&(_.lanes|=l),i2(y,l,f),y=i.sibling}else y=i.child;if(y!==null)y.return=i;else for(y=i;y!==null;){if(y===f){y=null;break}if(i=y.sibling,i!==null){i.return=y.return,y=i;break}y=y.return}i=y}Ol(u,f,n.children,l),f=f.child}return f;case 9:return n=f.type,r=f.pendingProps.children,Ni(f,l),n=zr(n),r=r(n),f.flags|=1,Ol(u,f,r,l),f.child;case 14:return r=f.type,n=Sr(r,f.pendingProps),n=Sr(r.type,n),Yj(u,f,r,n,l);case 15:return LJ(u,f,f.type,f.pendingProps,l);case 17:return r=f.type,n=f.pendingProps,n=f.elementType===r?n:Sr(r,n),p3(u,f),f.tag=1,xl(r)?(u=!0,a3(f)):u=!1,Ni(f,l),qJ(f,r,n),_2(f,r,n,l),A2(null,f,r,!0,u,l);case 19:return TJ(u,f,l);case 22:return wJ(u,f,l)}throw Error(Uu(156,f.tag))};function RJ(u,f){return JF(u,f)}function Dz(u,f,l,r){this.tag=u,this.key=l,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=f,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Kr(u,f,l,r){return new Dz(u,f,l,r)}function _5(u){return u=u.prototype,!(!u||!u.isReactComponent)}function Xz(u){if(typeof u==="function")return _5(u)?1:0;if(u!==void 0&&u!==null){if(u=u.$$typeof,u===E2)return 11;if(u===Z2)return 14}return 2}function An(u,f){var l=u.alternate;return l===null?(l=Kr(u.tag,f,u.key,u.mode),l.elementType=u.elementType,l.type=u.type,l.stateNode=u.stateNode,l.alternate=u,u.alternate=l):(l.pendingProps=f,l.type=u.type,l.flags=0,l.subtreeFlags=0,l.deletions=null),l.flags=u.flags&14680064,l.childLanes=u.childLanes,l.lanes=u.lanes,l.child=u.child,l.memoizedProps=u.memoizedProps,l.memoizedState=u.memoizedState,l.updateQueue=u.updateQueue,f=u.dependencies,l.dependencies=f===null?null:{lanes:f.lanes,firstContext:f.firstContext},l.sibling=u.sibling,l.index=u.index,l.ref=u.ref,l}function M3(u,f,l,r,n,i){var y=2;if(r=u,typeof u==="function")_5(u)&&(y=1);else if(typeof u==="string")y=5;else u:switch(u){case ri:return i1(l.children,n,i,f);case T2:y=8,n|=8;break;case H4:return u=Kr(12,l,f,n|2),u.elementType=H4,u.lanes=i,u;case B4:return u=Kr(13,l,f,n),u.elementType=B4,u.lanes=i,u;case V4:return u=Kr(19,l,f,n),u.elementType=V4,u.lanes=i,u;case oj:return Lt(l,n,i,f);default:if(typeof u==="object"&&u!==null)switch(u.$$typeof){case sj:y=10;break u;case aj:y=9;break u;case E2:y=11;break u;case Z2:y=14;break u;case a0:y=16,r=null;break u}throw Error(Uu(130,u==null?u:typeof u,""))}return f=Kr(y,l,f,n),f.elementType=u,f.type=r,f.lanes=i,f}function i1(u,f,l,r){return u=Kr(7,u,r,f),u.lanes=l,u}function Lt(u,f,l,r){return u=Kr(22,u,r,f),u.elementType=oj,u.lanes=l,u.stateNode={isHidden:!1},u}function E4(u,f,l){return u=Kr(6,u,null,f),u.lanes=l,u}function Z4(u,f,l){return f=Kr(4,u.children!==null?u.children:[],u.key,f),f.lanes=l,f.stateNode={containerInfo:u.containerInfo,pendingChildren:null,implementation:u.implementation},f}function Yz(u,f,l,r,n){this.tag=f,this.containerInfo=u,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=c4(0),this.expirationTimes=c4(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=c4(0),this.identifierPrefix=r,this.onRecoverableError=n,this.mutableSourceEagerHydrationData=null}function $5(u,f,l,r,n,i,y,_,$){return u=new Yz(u,f,l,_,$),f===1?(f=1,i===!0&&(f|=8)):f=0,i=Kr(3,null,null,f),u.current=i,i.stateNode=u,i.memoizedState={element:r,isDehydrated:l,cache:null,transitions:null,pendingSuspenseBoundaries:null},v2(i),u}function Sz(u,f,l){var r=3{function kJ(){if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=="function")return;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(kJ)}catch(u){console.error(u)}}kJ(),IJ.exports=vJ()});var sJ=nr((F5)=>{var gJ=j5();F5.createRoot=gJ.createRoot,F5.hydrateRoot=gJ.hydrateRoot;var Cz});var gQ=nr((y6)=>{var rO=qf(),nO=Symbol.for("react.element"),iO=Symbol.for("react.fragment"),yO=Object.prototype.hasOwnProperty,_O=rO.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,$O={key:!0,ref:!0,__self:!0,__source:!0};function IQ(u,f,l){var r,n={},i=null,y=null;l!==void 0&&(i=""+l),f.key!==void 0&&(i=""+f.key),f.ref!==void 0&&(y=f.ref);for(r in f)yO.call(f,r)&&!$O.hasOwnProperty(r)&&(n[r]=f[r]);if(u&&u.defaultProps)for(r in f=u.defaultProps,f)n[r]===void 0&&(n[r]=f[r]);return{$$typeof:nO,type:u,key:i,ref:y,props:n,_owner:_O.current}}y6.Fragment=iO;y6.jsx=IQ;y6.jsxs=IQ});var aQ=nr((om,sQ)=>{sQ.exports=gQ()});var ZN=nr((EN)=>{var $y=qf();function TV(u,f){return u===f&&(u!==0||1/u===1/f)||u!==u&&f!==f}var EV=typeof Object.is==="function"?Object.is:TV,ZV=$y.useState,OV=$y.useEffect,HV=$y.useLayoutEffect,BV=$y.useDebugValue;function VV(u,f){var l=f(),r=ZV({inst:{value:l,getSnapshot:f}}),n=r[0].inst,i=r[1];return HV(function(){n.value=l,n.getSnapshot=f,i9(n)&&i({inst:n})},[u,l,f]),OV(function(){return i9(n)&&i({inst:n}),u(function(){i9(n)&&i({inst:n})})},[u]),BV(l),l}function i9(u){var f=u.getSnapshot;u=u.value;try{var l=f();return!EV(u,l)}catch(r){return!0}}function DV(u,f){return f()}var XV=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?DV:VV;EN.useSyncExternalStore=$y.useSyncExternalStore!==void 0?$y.useSyncExternalStore:XV});var HN=nr((bh,ON)=>{ON.exports=ZN()});var VN=nr((BN)=>{var e6=qf(),YV=HN();function SV(u,f){return u===f&&(u!==0||1/u===1/f)||u!==u&&f!==f}var pV=typeof Object.is==="function"?Object.is:SV,mV=YV.useSyncExternalStore,PV=e6.useRef,MV=e6.useEffect,CV=e6.useMemo,RV=e6.useDebugValue;BN.useSyncExternalStoreWithSelector=function(u,f,l,r,n){var i=PV(null);if(i.current===null){var y={hasValue:!1,value:null};i.current=y}else y=i.current;i=CV(function(){function $(U){if(!A){if(A=!0,c=U,U=r(U),n!==void 0&&y.hasValue){var Q=y.value;if(n(Q,U))return j=Q}return j=U}if(Q=j,pV(c,U))return Q;var L=r(U);if(n!==void 0&&n(Q,L))return c=U,Q;return c=U,j=L}var A=!1,c,j,F=l===void 0?null:l;return[function(){return $(f())},F===null?void 0:function(){return $(F())}]},[f,l,r,n]);var _=mV(u,i[0],i[1]);return MV(function(){y.hasValue=!0,y.value=_},[_]),RV(_),_}});var XN=nr((kh,DN)=>{DN.exports=VN()});var bn=Pu(qf(),1);var y3="北京时间";var SK={timeZone:"Asia/Shanghai",hour12:!1},pK={timeZone:"Asia/Shanghai",hour12:!1},mK=new Intl.DateTimeFormat("en-CA",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23"});function s8(u){if(u===null||u===void 0||u==="")return null;let f=u instanceof Date?u:new Date(u);return Number.isNaN(f.getTime())?null:f}function D7(u){let f=s8(u);if(!f)return null;return mK.formatToParts(f).reduce((l,r)=>{if(r.type!=="literal")l[r.type]=r.value;return l},{})}function Nu(u){let f=s8(u);return f?f.toLocaleString("zh-CN",SK):"--"}function tf(u){let f=s8(u);return f?f.toLocaleTimeString("zh-CN",pK):"--"}function a8(u){let f=D7(u);if(!f)return"";let l=f.hour==="24"?"00":f.hour;return`${f.year}-${f.month}-${f.day}T${l}:${f.minute}`}function X7(u=new Date){let f=D7(u);if(!f)return"";return`${f.year}-${f.month}-${f.day}`}function Y7(u){if(!u)return null;let f=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(u);if(!f)return null;let[,l,r,n,i,y,_="00"]=f,$=Date.UTC(Number(l),Number(r)-1,Number(n),Number(i)-8,Number(y),Number(_)),A=new Date($),c=a8(A);return Number.isNaN(A.getTime())||c!==`${l}-${r}-${n}T${i}:${y}`?null:A.toISOString()}var rw=Pu(sJ(),1);var Zt=Pu(qf(),1);var aJ=Pu(qf(),1),G_=aJ.default.createElement;function Rz({active:u=!0,label:f="正在加载"}){if(!u)return null;return G_("span",{className:"loading-spinner-indicator",role:"status","aria-label":f,title:f,"data-testid":"loading-title-indicator"},G_("span",{className:"loading-spinner-ring","aria-hidden":!0}))}function nf({title:u,children:f,loading:l,level:r=2,className:n="",label:i="正在加载"}){return G_(r===3?"h3":"h2",{className:`loading-title ${l?"is-loading":""} ${n}`.trim()},G_("span",{className:"loading-title-text"},f??u),G_(Rz,{active:Boolean(l),label:i}))}class Hi extends Error{unideskRequestError=!0;meta;constructor(u,f){super(u);this.name="UniDeskRequestError",this.meta=f}}function xz(u){return new Promise((f)=>setTimeout(f,u))}function E_(u,f="操作失败"){return u instanceof Error?u.message:String(u||f)}function Tt(u,f=500){if(u===null||u===void 0)return"";let l=typeof u==="string"?u:JSON.stringify(u),r=String(l||"").replace(/\s+/gu," ").trim();return r.length>f?`${r.slice(0,f)}...`:r}function hz(u){try{let f=typeof location<"u"&&location.origin?location.origin:"http://localhost";return new URL(u,f).toString()}catch{return u}}function oJ(u){return String(u.method||"GET").toUpperCase()}function bz(u){if(u===null||u===void 0)return!1;if(typeof u!=="object")return!1;if(typeof Blob<"u"&&u instanceof Blob)return!1;if(typeof FormData<"u"&&u instanceof FormData)return!1;if(typeof URLSearchParams<"u"&&u instanceof URLSearchParams)return!1;if(typeof ArrayBuffer<"u"&&u instanceof ArrayBuffer)return!1;return!0}function dJ(u){let f=new Headers(u.headers||{}),l=bz(u.body)?JSON.stringify(u.body):u.body;if(l&&!f.has("content-type")&&typeof l==="string")f.set("content-type","application/json");return{...u,credentials:u.credentials||"same-origin",body:l,headers:f}}function eJ(u){if(u?.error&&typeof u.error==="object"&&typeof u.error.message==="string")return u.error.message;if(typeof u?.error==="string")return u.error;if(typeof u?.message==="string")return u.message;if(typeof u?.detail==="string")return u.detail;return""}function vz(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return!1;return f.some((l)=>l!==!1&&u[l]===!1)}function z_(u,f,l,r,n={}){return{kind:u,method:l,url:hz(f),occurredAt:r.toISOString(),...n}}function T_(u,f){if(!u)return"请求失败";return`HTTP ${u}${f?` ${f}`:""}`}function uU(u){try{return{body:u?JSON.parse(u):null,parseError:""}}catch(f){return{body:{text:u},parseError:E_(f,"parse failed")}}}async function Eu(u,f={},l=0){let{failureFields:r=["ok"],strictJson:n=!1,retryInvalidJson:i=0,retryDelayMs:y=120,invalidJsonPrefix:_="服务返回了无效 JSON",invalidJsonPreview:$=!1,responsePreviewLength:A=500,...c}=f,j=oJ(c),F=new Date,U;try{U=await fetch(u,dJ(c))}catch(w){let J=E_(w,"网络请求失败");throw new Hi(J,z_("network",u,j,F,{upstreamMessage:J}))}let Q=await U.text(),L=uU(Q);if(L.parseError){if(n&&j==="GET"&&l=300)?T_(u.meta.status,u.meta.statusText):"应用请求失败",i=u.meta.status?T_(u.meta.status):"",y=($)=>!$||$===n||$===i,_=!y(u.message)?u.message:y(u.meta.upstreamMessage)?"":u.meta.upstreamMessage||"";return{title:n,message:_,status:u.meta.status,statusText:u.meta.statusText,method:u.meta.method,url:u.meta.url,occurredAt:kz(u.meta.occurredAt),responsePreview:u.meta.responsePreview,parseError:u.meta.parseError,structured:!0}}let r=E_(u,f).split(/\r?\n/u);return{title:r[0]||f,message:r.slice(1).join(` +`),structured:r.length>1}}function Iz(u,f="操作失败"){let l=J5(u,f),r=[l.title];if(l.message)r.push(`原因: ${l.message}`);if(l.method||l.url)r.push(`请求: ${[l.method,l.url].filter(Boolean).join(" ")}`);if(l.status)r.push(`状态: ${T_(l.status,l.statusText)}`);if(l.occurredAt)r.push(`时间: ${l.occurredAt}`);if(l.parseError)r.push(`解析错误: ${l.parseError}`);if(l.responsePreview&&l.responsePreview!==l.message)r.push(`响应预览: ${l.responsePreview}`);return r.filter(Boolean).join(` +`)}function Hu(u,f="操作失败"){return lU(u)?Iz(u,f):E_(u,f)}var rU=Pu(qf(),1);var Qn=rU.default.createElement;function Z_(u,f){return f?[Qn("dt",{key:`${u}-label`},u),Qn("dd",{key:u},f)]:null}function yf({error:u,wide:f=!1,fallback:l="操作失败",className:r=""}){if(!u)return null;let n=J5(u,l),i=[Z_("请求",[n.method,n.url].filter(Boolean).join(" ")),Z_("状态",n.status?`HTTP ${n.status}${n.statusText?` ${n.statusText}`:""}`:""),Z_("时间",n.occurredAt),Z_("解析错误",n.parseError),Z_("响应预览",n.responsePreview)].filter(Boolean);return Qn("div",{className:`form-error unidesk-error${f?" wide":""}${r?` ${r}`:""}`,role:"alert","data-testid":"unidesk-error"},Qn("div",{className:"unidesk-error-title"},Qn("strong",null,n.title),n.status?Qn("span",{className:"unidesk-error-code"},`HTTP ${n.status}`):null),n.message?Qn("pre",{className:"unidesk-error-message"},n.message):null,i.length>0?Qn("dl",{className:"unidesk-error-details"},i):null)}var r0=Pu(qf(),1),nU=r0.default.createContext(null);function iU({children:u}){let[f,l]=r0.default.useState([]),[r,n]=r0.default.useState(Date.now()),i=r0.default.useCallback((j,F)=>{let Q={id:`notif_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,type:j,message:F,timestamp:Date.now()};l((L)=>{let w=[...L,Q];if(w.length>50)return w.slice(-50);return w})},[]),y=r0.default.useCallback((j)=>{l((F)=>F.filter((U)=>U.id!==j))},[]),_=r0.default.useCallback(()=>{l([]),n(Date.now())},[]),$=r0.default.useMemo(()=>{return f.filter((j)=>j.timestamp>r).length},[f,r]),A=$>0,c={notifications:f,addNotification:i,removeNotification:y,clearNotifications:_,unreadCount:$,hasUnread:A};return gz(nU.Provider,{value:c},u)}var gz=r0.default.createElement;function Vl(){let u=r0.default.useContext(nU);if(!u)throw Error("useNotification must be used within NotificationProvider");return u}var R=Zt.default.createElement,{useEffect:Et}=Zt.default,Bi=Zt.default.useState;function wl(u,f={}){return Eu(u,{failureFields:["ok","success"],...f})}function Dl(u,f){return`${u}/microservices/baidu-netdisk/proxy${f}`}function sz(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}function qn(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=["B","KB","MB","GB","TB"],r=f,n=0;while(r>=1024&&n{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function Di({title:u,text:f}){return R("div",{className:"empty-state"},R("strong",null,u),R("span",null,f))}function Xi({title:u,text:f,href:l,badge:r,testId:n}){return R("a",{className:"doc-link-card",href:l,target:"_blank",rel:"noreferrer","data-testid":n},R("span",null,r||"DOC"),R("strong",null,u),R("p",null,f),R("code",null,l))}function az(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function oz(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function dz(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function ez(u){return Array.isArray(u?.files)?u.files:[]}function uT(u){return Array.isArray(u?.jobs)?u.jobs:[]}function fT(u,f){if(!u||u===f)return f;let l=u.replace(/\/+$/u,""),r=l.slice(0,l.lastIndexOf("/"))||f;return r.lengthx.id==="baidu-netdisk")||null,[n,i]=Bi({loading:!1,actionLoading:!1,error:"",message:"",health:null,account:null,files:null,transfers:null,logs:null,selfTest:null,refreshedAt:null}),[y,_]=Bi("/"),[$,A]=Bi(null),[c,j]=Bi(""),[F,U]=Bi({localPath:"sample.txt",remotePath:"/sample.txt"}),[Q,L]=Bi({fsId:"",localPath:"downloads/"}),{addNotification:w}=Vl(),J=n.health?.baidu?.appRoot||n.account?.rootPath||"/";Et(()=>{U((x)=>{let fu=new Set(["/sample.txt","/apps/UniDeskBaiduNetdisk/sample.txt"]);if(x.remotePath&&!fu.has(x.remotePath))return x;let $u=U5(J,"sample.txt");return x.remotePath===$u?x:{...x,remotePath:$u}})},[J]);async function N(x=y){let $u=await wl(Dl(l,`/api/files?dir=${encodeURIComponent(x||J)}&limit=100`));i((tu)=>({...tu,files:$u}))}async function q(){let x=await wl(Dl(l,"/api/transfers?limit=80"));i((fu)=>({...fu,transfers:x}))}async function W(){if(!r)return;i((x)=>({...x,loading:!0,error:"",message:""}));try{let x=await wl(`${l}/microservices/baidu-netdisk/health`),fu=x?.baidu?.appRoot||J,$u=null,tu=null;if(x?.auth?.loggedIn){$u=await wl(Dl(l,"/api/account?refresh=1"));let qu=y&&y.startsWith(fu)?y:fu;_(qu),tu=await wl(Dl(l,`/api/files?dir=${encodeURIComponent(qu)}&limit=100`))}else _(fu);let ju=await wl(Dl(l,"/api/transfers?limit=80")),Gu=await wl(Dl(l,"/logs?limit=60"));i((qu)=>({...qu,loading:!1,health:x,account:$u?.account||null,files:tu,transfers:ju,logs:Gu,refreshedAt:new Date}))}catch(x){i((fu)=>({...fu,loading:!1,error:Hu(x,"百度网盘服务加载失败")}))}}async function z(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{let x=await wl(Dl(l,"/api/auth/device/start"),{method:"POST",body:{}});A(x.session||null),i((fu)=>({...fu,actionLoading:!1,message:"设备码已生成,请扫码授权"}))}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Hu(x,"创建设备码失败")}))}}async function Z(x=!1){if(!$?.id)return;if(x)i((fu)=>({...fu,actionLoading:!0,error:""}));try{let fu=await wl(Dl(l,`/api/auth/device/status?sessionId=${encodeURIComponent($.id)}`));if(A(fu.session||null),fu.session?.status==="succeeded")i(($u)=>({...$u,actionLoading:!1,message:"授权成功,正在刷新账号与文件列表"})),await W();else if(x)i(($u)=>({...$u,actionLoading:!1}))}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"轮询登录状态失败")}))}}async function H(){i((x)=>({...x,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/auth/logout"),{method:"POST",body:{}}),A(null),i((x)=>({...x,actionLoading:!1,account:null,files:null,message:"本地 token 已清除"})),await W()}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Hu(x,"退出登录失败")}))}}async function E(x){x.preventDefault();let fu=c.trim();if(!fu)return;i(($u)=>({...$u,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/folders"),{method:"POST",body:{path:U5(y,fu)}}),j(""),i(($u)=>({...$u,actionLoading:!1,message:"文件夹已创建"})),await N(y)}catch($u){i((tu)=>({...tu,actionLoading:!1,error:Hu($u,"创建文件夹失败")}))}}async function D(x){if(!x)return;i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/files/manage"),{method:"POST",body:{opera:"delete",filelist:[{path:x}],async:1}}),i((fu)=>({...fu,actionLoading:!1,message:"删除任务已提交"})),await N(y)}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"删除失败")}))}}async function h(x){x.preventDefault(),i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/transfers/upload-from-path"),{method:"POST",body:F}),i((fu)=>({...fu,actionLoading:!1,message:"上传任务已入队"})),await q()}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"上传任务创建失败")}))}}async function V(x){x.preventDefault(),i((fu)=>({...fu,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,"/api/transfers/download-to-path"),{method:"POST",body:Q}),i((fu)=>({...fu,actionLoading:!1,message:"下载任务已入队"})),await q()}catch(fu){i(($u)=>({...$u,actionLoading:!1,error:Hu(fu,"下载任务创建失败")}))}}async function Y(x,fu){i(($u)=>({...$u,actionLoading:!0,error:"",message:""}));try{await wl(Dl(l,`/api/transfers/${encodeURIComponent(x)}/${fu}`),{method:"POST",body:{}}),i(($u)=>({...$u,actionLoading:!1,message:fu==="cancel"?"已请求取消任务":"任务已重新入队"})),await q()}catch($u){i((tu)=>({...tu,actionLoading:!1,error:Hu($u,"任务操作失败")}))}}async function p(){i((x)=>({...x,actionLoading:!0,error:"",message:"正在运行上传/下载自测..."}));try{let x=await wl(Dl(l,"/api/self-test"),{method:"POST",body:{}});i((fu)=>({...fu,actionLoading:!1,selfTest:x,message:`上传/下载自测通过:${x.remotePath||""}`})),await N(y),await q()}catch(x){i((fu)=>({...fu,actionLoading:!1,error:Hu(x,"上传/下载自测失败")}))}}if(Et(()=>{if(!r)return;W();return},[r?.id,r?.runtime?.providerStatus]),Et(()=>{if(!$?.id||$.status!=="pending")return;let x=window.setInterval(()=>void Z(!1),Math.max(5000,Number($.pollIntervalSeconds||5)*1000));return()=>window.clearInterval(x)},[$?.id,$?.status,$?.pollIntervalSeconds]),Et(()=>{if(!r)return;let x=window.setInterval(()=>void q(),5000);return()=>window.clearInterval(x)},[r?.id]),!r)return R(Di,{title:"Baidu Netdisk 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=baidu-netdisk"});let O=az(r),m=dz(r),X=oz(r),v=n.health||{},T=n.account||v.auth?.account||null,S=v.auth||{},k=ez(n.files),I=uT(n.transfers),b=T?.quota||{},o=Boolean(S.loggedIn||T),s=Boolean(S.configured);return R("div",{className:"baidu-netdisk-page","data-testid":"baidu-netdisk-page"},R(J1,{title:"Baidu Netdisk 工作台",eyebrow:"Containerized Storage Gateway",loading:n.loading,actions:R("div",{className:"panel-actions"},R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-env-setup.md",target:"_blank",rel:"noreferrer","data-testid":"baidu-netdisk-config-doc-link"},"配置文档"),R("button",{type:"button",className:"ghost-btn",onClick:W,disabled:n.loading,"data-testid":"baidu-netdisk-refresh"},n.loading?"刷新中":"刷新"),R(H0,{title:"Baidu Netdisk 用户服务",data:r,onOpen:f,testId:"raw-baidu-netdisk-service"}))},R("div",{className:"baidu-netdisk-hero"},R("div",null,R("div",{className:"node-version-line"},R(F1,{status:O.providerStatus==="online"?"online":"warn"},O.providerStatus||"unknown"),R("span",null,r.providerId),R(F1,{status:X.public?"warn":"private"},X.public?"公网暴露":"仅 UniDesk frontend 代理访问")),R("p",{className:"muted paragraph"},r.description)),R("div",{className:"microservice-ref-card"},R("span",null,"Repo"),R("strong",null,m.url||"--"),R("code",null,m.commitId||"--")),R("div",{className:"microservice-ref-card"},R("span",null,"Private Backend"),R("strong",null,`${X.nodeBindHost||"--"}:${X.nodePort||"--"}`),R("code",null,`${m.composeFile||"--"} / ${m.composeService||"--"}`))),R(yf,{error:n.error,wide:!0})),R("div",{className:"metric-grid"},R(Vi,{label:"Health",value:v.ok?"OK":"--",hint:v.storage?.postgres||"postgres",tone:v.ok?"ok":"warn"}),R(Vi,{label:"OAuth",value:s?"已配置":"待配置",hint:s?"client + secret + token key":"需要设置 UNIDESK_BAIDU_NETDISK_*",tone:s?"ok":"warn"}),R(Vi,{label:"Login",value:o?"已登录":"未登录",hint:T?.username||"Device Code QR",tone:o?"ok":"warn"}),R(Vi,{label:"Work Root",value:lT(J),hint:J}),R(Vi,{label:"Quota",value:qn(b.used),hint:b.total?`${b.usedPercent||0}% / ${qn(b.total)}`:"授权后刷新"}),R(Vi,{label:"Transfers",value:sz(I.length),hint:`running ${n.transfers?.counts?.running||0} / failed ${n.transfers?.counts?.failed||0}`})),R(J1,{title:"文件浏览器",eyebrow:y,className:"baidu-files-panel",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"ghost-btn",onClick:()=>{let x=fT(y,J);_(x),N(x)},disabled:!o||y===J},"上级"),R("button",{type:"button",className:"ghost-btn",onClick:()=>N(y),disabled:!o},"刷新文件"),R(H0,{title:"Baidu Files",data:n.files,onOpen:f,testId:"raw-baidu-files"}))},R("form",{className:"baidu-pathbar",onSubmit:(x)=>{x.preventDefault(),N(y)}},R("input",{value:y,onChange:(x)=>_(x.target.value),disabled:!o}),R("button",{type:"submit",className:"ghost-btn",disabled:!o},"打开路径")),R("form",{className:"baidu-pathbar",onSubmit:E},R("input",{value:c,onChange:(x)=>j(x.target.value),placeholder:"新文件夹名称",disabled:!o}),R("button",{type:"submit",className:"primary-btn",disabled:!o||!c.trim()},"新建文件夹")),!o?R(Di,{title:"等待授权",text:"登录后通过 /api/files 读取工作目录文件列表"}):k.length===0?R(Di,{title:"目录为空",text:"可以从 staging 目录上传文件或新建文件夹"}):R("div",{className:"table-wrap","data-testid":"baidu-netdisk-file-table"},R("table",null,R("thead",null,R("tr",null,R("th",null,"名称"),R("th",null,"类型"),R("th",null,"大小"),R("th",null,"修改时间"),R("th",null,"fs_id"),R("th",null,"操作"))),R("tbody",null,k.map((x)=>R("tr",{key:x.fsId||x.path},R("td",null,R("strong",null,x.serverFilename||x.path),R("code",null,x.path||"--")),R("td",null,R(F1,{status:x.isDir?"queued":"private"},x.isDir?"DIR":"FILE")),R("td",null,x.isDir?"--":qn(x.size)),R("td",null,x.serverMtime?Nu(x.serverMtime*1000):"--"),R("td",null,R("code",null,x.fsId||"--")),R("td",null,R("div",{className:"inline-actions"},x.isDir?R("button",{type:"button",className:"ghost-btn",onClick:()=>{_(x.path),N(x.path)}},"打开"):R("button",{type:"button",className:"ghost-btn",onClick:()=>L((fu)=>({...fu,fsId:x.fsId}))},"填入下载"),R("button",{type:"button",className:"ghost-btn",onClick:()=>D(x.path),disabled:n.actionLoading},"删除"))))))))),R("div",{className:"baidu-netdisk-grid"},R(J1,{title:"配置与文档",eyebrow:"Deployment References",className:"baidu-docs-panel",actions:R("div",{className:"panel-actions inline-actions"},R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-env-setup.md",target:"_blank",rel:"noreferrer"},"打开环境配置"),R("a",{className:"ghost-btn",href:"/docs/issue/baidu-netdisk-user-service.md",target:"_blank",rel:"noreferrer"},"打开服务方案"))},R("p",{className:"muted paragraph"},s?"OAuth 运行时变量已配置;如需轮换密钥、迁移部署或排查代理边界,可直接打开下面的项目内文档。":"首次使用请先按环境变量配置文档填入百度应用 client id / secret,然后重建 baidu-netdisk 服务并刷新本页。"),R("div",{className:"baidu-doc-grid","data-testid":"baidu-netdisk-doc-links"},R(Xi,{title:"环境变量配置",text:"填写 UNIDESK_BAIDU_NETDISK_CLIENT_ID、CLIENT_SECRET、TOKEN_KEY,并执行重建与健康检查。",href:"/docs/issue/baidu-netdisk-env-setup.md",badge:"SETUP",testId:"baidu-netdisk-env-doc-card"}),R(Xi,{title:"服务方案与 API",text:"说明 OAuth Device Code、根目录工作区、staging 上传下载任务和后端 API 设计。",href:"/docs/issue/baidu-netdisk-user-service.md",badge:"DESIGN"}),R(Xi,{title:"用户服务安全边界",text:"查看 UniDesk microservice 私有代理、允许路径、frontendOnly 和密钥边界规则。",href:"/docs/reference/microservices.md",badge:"REF"}),R(Xi,{title:"部署与重建流程",text:"查看 server rebuild、Compose 编排、健康检查和交付验证的长期规则。",href:"/docs/reference/deployment.md",badge:"DEPLOY"}),R(Xi,{title:"CLI 验证命令",text:"查看 microservice health/proxy、server rebuild、job status 等命令入口。",href:"/docs/reference/cli.md",badge:"CLI"}),R(Xi,{title:"百度设备码模式",text:"打开百度官方 OAuth Device Code 文档,对照扫码登录和轮询参数。",href:"https://pan.baidu.com/union/doc/fl1x114ti",badge:"OFFICIAL"}))),R(J1,{title:"设备码登录",eyebrow:"OAuth Device Code",className:"baidu-login-panel",loading:n.actionLoading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"primary-btn",onClick:z,disabled:n.actionLoading||!s,"data-testid":"baidu-netdisk-start-login"},"生成二维码"),$?.id?R("button",{type:"button",className:"ghost-btn",onClick:()=>Z(!0),disabled:n.actionLoading},"检查状态"):null,o?R("button",{type:"button",className:"ghost-btn",onClick:H,disabled:n.actionLoading},"清除本地登录"):null,R(H0,{title:"Baidu Device Session",data:$||S.latestSession,onOpen:f,testId:"raw-baidu-device-session"}))},R("div",{className:"baidu-login-card","data-testid":"baidu-netdisk-login-card"},R("div",{className:"baidu-qr-frame"},$?.qrcodeUrl?R("img",{src:$.qrcodeUrl,alt:"百度网盘设备码授权二维码","data-testid":"baidu-netdisk-qrcode"}):R(Di,{title:s?"等待二维码":"OAuth 未配置",text:s?"点击生成二维码后使用百度网盘或百度 App 扫码":"设置 client id、secret 和 token key 后重建服务"})),R("div",{className:"claudeqq-login-copy"},R("div",{className:"node-version-line"},R(F1,{status:o?"online":$?.status==="pending"?"warn":"unknown"},o?"已登录":$?.status||"未开始"),R("span",null,$?.secondsRemaining!==void 0?`${$.secondsRemaining}s`:"--"),R("span",null,"scope basic,netdisk")),R("p",{className:"muted paragraph"},o?"access token / refresh token 已加密保存到 PostgreSQL;前端只看到脱敏登录态。":"后端使用百度 OAuth Device Code 轮询换取 token;二维码过期后重新生成即可。"),R("div",{className:"microservice-ref-card"},R("span",null,"User Code"),R("strong",null,$?.userCode||"--"),R("code",null,$?.verificationUrl||"https://openapi.baidu.com/device")),R("div",{className:"microservice-ref-card"},R("span",null,"Expires"),R("strong",null,$?.expiresAt?Nu($.expiresAt):"--"),R("code",null,$?.error||"no token exposed"))))),R(J1,{title:"账号与容量",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Account",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(H0,{title:"Baidu Account",data:T,onOpen:f,testId:"raw-baidu-account"}))},T?R("div",{className:"baidu-account-card"},R("div",{className:"node-version-line"},R(F1,{status:"online"},"connected"),R("span",null,T.baiduUid||"--"),R("span",null,`VIP ${T.vipType??"--"}`)),R("h3",null,T.username||"Baidu Netdisk"),R("p",{className:"muted paragraph"},`工作目录固定在 ${T.rootPath||J};v1 上传/下载只读写容器 staging 目录,不把大文件字节流穿过 UniDesk proxy。`),R("div",{className:"quota-bar"},R("span",{style:{width:`${Math.max(0,Math.min(100,Number(b.usedPercent||0)))}%`}})),R("div",{className:"microservice-ref-card"},R("span",null,"Quota"),R("strong",null,`${qn(b.used)} / ${qn(b.total)}`),R("code",null,`${b.usedPercent||0}% used`))):R(Di,{title:"尚未登录",text:"扫码授权后这里会显示账号、UID、会员状态和容量"})),R(J1,{title:"传输任务",eyebrow:"staging path jobs",className:"baidu-transfers-panel",loading:n.actionLoading,actions:R("div",{className:"panel-actions inline-actions"},R("button",{type:"button",className:"primary-btn",onClick:p,disabled:!o||n.actionLoading,"data-testid":"baidu-netdisk-self-test"},"运行自测"),R("button",{type:"button",className:"ghost-btn",onClick:q},"刷新任务"),R(H0,{title:"Baidu Transfers",data:n.transfers,onOpen:f,testId:"raw-baidu-transfers"}))},R("div",{className:"baidu-transfer-forms"},R("form",{className:"stack-form",onSubmit:h,"data-testid":"baidu-upload-form"},R("label",null,"容器 staging 文件",R("input",{value:F.localPath,onChange:(x)=>U((fu)=>({...fu,localPath:x.target.value})),placeholder:"sample.txt"})),R("label",null,"百度网盘目标路径",R("input",{value:F.remotePath,onChange:(x)=>U((fu)=>({...fu,remotePath:x.target.value})),placeholder:U5(J,"sample.txt")})),R("button",{type:"submit",className:"primary-btn",disabled:!o||n.actionLoading},"上传 staging 文件")),R("form",{className:"stack-form",onSubmit:V,"data-testid":"baidu-download-form"},R("label",null,"文件 fs_id",R("input",{value:Q.fsId,onChange:(x)=>L((fu)=>({...fu,fsId:x.target.value})),placeholder:"从文件表填入"})),R("label",null,"保存到 staging 路径",R("input",{value:Q.localPath,onChange:(x)=>L((fu)=>({...fu,localPath:x.target.value})),placeholder:"downloads/"})),R("button",{type:"submit",className:"primary-btn",disabled:!o||!Q.fsId||n.actionLoading},"下载到 staging"))),n.selfTest?R("div",{className:"baidu-account-card","data-testid":"baidu-netdisk-self-test-result"},R("div",{className:"node-version-line"},R(F1,{status:n.selfTest.ok?"online":"warn"},n.selfTest.ok?"self-test ok":"self-test"),R("span",null,qn(n.selfTest.sizeBytes))),R("h3",null,n.selfTest.remotePath||"Baidu self-test"),R("div",{className:"microservice-ref-card"},R("span",null,"fs_id"),R("strong",null,n.selfTest.fsId||"--"),R("code",null,n.selfTest.downloadedPath||"--")),R("div",{className:"microservice-ref-card"},R("span",null,"MD5"),R("strong",null,n.selfTest.downloadedMd5||"--"),R("code",null,n.selfTest.expectedMd5||"--")),R(H0,{title:"Baidu Self Test",data:n.selfTest,onOpen:f,testId:"raw-baidu-self-test"})):null,I.length===0?R(Di,{title:"暂无传输任务",text:"上传/下载任务会在后端容器内执行,避免大文件穿过 UniDesk proxy"}):R("div",{className:"table-wrap","data-testid":"baidu-transfer-table"},R("table",null,R("thead",null,R("tr",null,R("th",null,"状态"),R("th",null,"方向"),R("th",null,"路径"),R("th",null,"进度"),R("th",null,"时间"),R("th",null,"操作"))),R("tbody",null,I.map((x)=>R("tr",{key:x.id},R("td",null,R(F1,{status:x.status},x.status)),R("td",null,x.direction),R("td",null,R("strong",null,x.remotePath||x.fsId||"--"),R("code",null,x.localPath||"--"),x.error?R("span",{className:"form-error"},x.error):null),R("td",null,R(rT,{percent:x.progressPercent}),R("span",{className:"muted"},`${qn(x.bytesDone)} / ${qn(x.sizeBytes)}`)),R("td",null,Nu(x.updatedAt)),R("td",null,R("div",{className:"inline-actions"},["queued","running"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>Y(x.id,"cancel")},"取消"):null,["failed","canceled"].includes(x.status)?R("button",{type:"button",className:"ghost-btn",onClick:()=>Y(x.id,"retry")},"重试"):null,R(H0,{title:`Transfer ${x.id}`,data:x,onOpen:f}))))))))),R(J1,{title:"安全与日志",eyebrow:"redacted diagnostics",className:"baidu-wide-panel",loading:n.loading,actions:R("div",{className:"panel-actions inline-actions"},R(H0,{title:"Baidu Health",data:v,onOpen:f,testId:"raw-baidu-health"}),R(H0,{title:"Baidu Logs",data:n.logs,onOpen:f,testId:"raw-baidu-logs"}))},R("div",{className:"policy-grid"},R("article",null,R("b",null,"私有后端"),R("span",null,"4244 只在 Compose 网络 expose,浏览器经 UniDesk 同源代理访问")),R("article",null,R("b",null,"Token 加密"),R("span",null,"access/refresh token 使用 BAIDU_NETDISK_TOKEN_KEY 加密后写入 PostgreSQL")),R("article",null,R("b",null,"无浏览器大文件流"),R("span",null,"上传/下载以容器 staging 目录为边界,避免 proxy 文本通道传输大字节流"))))))}var Bt=Pu(qf(),1);var a=Bt.default.createElement,{useEffect:nT}=Bt.default,Ot=Bt.default.useState,U1={label:"主用户私聊账号",userId:645275593};function Q5(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}async function Nn(u,f={}){return Eu(u,{failureFields:["ok","success"],...f})}async function iT(u){let f=await fetch(u,{credentials:"same-origin"}),l=await f.text();try{return l?JSON.parse(l):{ok:f.ok,status:f.status}}catch{return{ok:f.ok,status:f.status,text:l}}}function Ht({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return a("span",{className:`status-badge ${l}`},f||u||"unknown")}function Yi({label:u,value:f,hint:l,tone:r}){return a("article",{className:`metric-card ${r||""}`},a("div",{className:"metric-label"},u),a("div",{className:"metric-value"},f),a("div",{className:"metric-hint"},l))}function Si({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return a("section",{className:`panel ${n||""}`},a("div",{className:"panel-head"},a("div",null,f?a("p",{className:"panel-eyebrow"},f):null,a(nf,{title:u,loading:i})),l?a("div",{className:"panel-actions"},l):null),a("div",{className:"panel-body"},r))}function O_({title:u,data:f,onOpen:l,testId:r}){return a("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function H_({title:u,text:f}){return a("div",{className:"empty-state"},a("strong",null,u),a("span",null,f))}function yT(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function _T(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function $T(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Wn(u,f){return`${u}/microservices/claudeqq/proxy${f}`}function tT(u){return Array.isArray(u?.events)?u.events.slice(0,80):[]}function AT(u){return Array.isArray(u?.subscriptions)?u.subscriptions.slice(0,50):[]}function cT(u){return Array.isArray(u?.messages)?u.messages.slice(0,30):[]}function _U(u){let f=u?.text??u?.message??u?.raw?.raw_message;if(typeof f!=="string")return"--";return f.length>180?`${f.slice(0,177)}...`:f}function $U(u){let f=u?.groupId??u?.group_id??(u?.message_type==="group"?u?.target_id:void 0),l=u?.userId??u?.user_id??(u?.message_type==="private"?u?.target_id:void 0);if(f)return`群 ${f}`;if(l)return`私聊 ${l}`;return"--"}function tU({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((T)=>T.id==="claudeqq")||null,[n,i]=Ot({loading:!1,qrLoading:!1,error:"",health:null,status:null,napcatLogin:null,napcatQrcode:null,qrcodeFetched:!1,qrcodeRefreshedAt:null,events:null,subscriptions:null,sent:null,refreshedAt:null}),[y,_]=Ot({targetType:"private",targetId:String(U1.userId),message:""}),[$,A]=Ot({name:"unidesk-callback",targetUrl:"",eventTypes:"message",secret:""}),[c,j]=Ot(""),{addNotification:F}=Vl();async function U(){if(!r)return;i((T)=>({...T,loading:!0,error:""}));try{let[T,S,k,I,b]=await Promise.all([iT(`${l}/microservices/claudeqq/health`),Nn(Wn(l,"/api/server/status")),Nn(Wn(l,"/api/events/recent?limit=60")),Nn(Wn(l,"/api/events/subscriptions")),Nn(Wn(l,"/api/messages/sent?limit=20"))]);if(i((o)=>({...o,loading:!1,error:"",health:T,status:S,events:k,subscriptions:I,sent:b,refreshedAt:new Date})),!n.qrcodeFetched)Q(!1)}catch(T){i((S)=>({...S,loading:!1,error:Hu(T,"ClaudeQQ 加载失败")}))}}async function Q(T=!0){if(!r)return;i((S)=>({...S,qrLoading:!0,error:T?"":S.error}));try{let S=await Nn(Wn(l,"/api/napcat/login")),k=S?.napcat?.qrcode||S?.qrcode||null;i((I)=>({...I,qrLoading:!1,error:"",napcatLogin:S,napcatQrcode:k,qrcodeFetched:!0,qrcodeRefreshedAt:new Date}))}catch(S){i((k)=>({...k,qrLoading:!1,error:T||!k.napcatQrcode?Hu(S,"NapCat 二维码加载失败"):k.error}))}}async function L(T){T.preventDefault(),j("");let S=Number(y.targetId);if(!Number.isFinite(S)||S<=0||y.message.trim().length===0){i((k)=>({...k,error:"请填写 QQ 目标和消息内容"}));return}try{await Nn(Wn(l,"/api/push/text"),{method:"POST",body:JSON.stringify({userId:y.targetType==="private"?S:void 0,groupId:y.targetType==="group"?S:void 0,message:y.message})});let k="消息推送请求已提交";_((I)=>({...I,targetType:"private",targetId:String(U1.userId),message:""})),j(k),F("success",k),await U()}catch(k){i((I)=>({...I,error:Hu(k,"发送失败")}))}}async function w(T){if(T.preventDefault(),j(""),$.targetUrl.trim().length===0){i((S)=>({...S,error:"请填写订阅回调 URL"}));return}try{await Nn(Wn(l,"/api/events/subscriptions"),{method:"POST",body:JSON.stringify({name:$.name,targetUrl:$.targetUrl,eventTypes:$.eventTypes.split(",").map((k)=>k.trim()).filter(Boolean),secret:$.secret||void 0,enabled:!0})});let S="事件订阅已创建";j(S),F("success",S),await U()}catch(S){i((k)=>({...k,error:Hu(S,"订阅失败")}))}}async function J(T){if(!T)return;j("");try{await Nn(Wn(l,`/api/events/subscriptions/${encodeURIComponent(T)}`),{method:"DELETE"});let S="事件订阅已删除";j(S),F("success",S),await U()}catch(S){i((k)=>({...k,error:Hu(S,"删除订阅失败")}))}}if(nT(()=>{if(!r)return;U();return},[r?.id,r?.runtime?.providerStatus]),!r)return a(H_,{title:"ClaudeQQ 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=claudeqq"});let N=yT(r),q=$T(r),W=_T(r),z=n.health||{},Z=n.status||{},H=n.napcatLogin||{},E=z.napcat||Z.napcat||{},D={...H.napcat||{},...E,qrcode:n.napcatQrcode||{},webui:E.webui||H.napcat?.webui},h=H.login||{},V=n.napcatQrcode||{},Y=tT(n.events),p=AT(n.subscriptions),O=cT(n.sent),m=Boolean(D.httpConnected||h.ready),X=String(D.loginState||h.state||(m?"logged_in":"unknown")),v=Boolean(V.available&&V.dataUrl);return a("div",{className:"claudeqq-page","data-testid":"claudeqq-page"},a(Si,{title:"ClaudeQQ 工作台",eyebrow:"D601 QQ Event Gateway",loading:n.loading,actions:a("div",{className:"panel-actions"},a("button",{type:"button",className:"ghost-btn",onClick:U,disabled:n.loading,"data-testid":"claudeqq-refresh-button"},n.loading?"刷新中":"刷新"),a(O_,{title:"ClaudeQQ 用户服务",data:r,onOpen:f,testId:"raw-claudeqq-service"}))},a("div",{className:"findjob-hero"},a("div",null,a("div",{className:"node-version-line"},a(Ht,{status:N.providerStatus==="online"?"online":"warn"},N.providerStatus||"unknown"),a("span",null,r.providerId),a("span",null,W.public?"公网暴露":"仅 UniDesk frontend 代理访问")),a("p",{className:"muted paragraph"},r.description)),a("div",{className:"microservice-ref-card"},a("span",null,"Repo"),a("strong",null,q.url||"--"),a("code",null,q.commitId||"--")),a("div",{className:"microservice-ref-card"},a("span",null,"D601 Docker"),a("strong",null,`${W.nodeBindHost||"--"}:${W.nodePort||"--"}`),a("code",null,`${q.composeFile||"--"} / ${q.composeService||"--"}`))),a(yf,{error:n.error,wide:!0})),a("div",{className:"metric-grid"},a(Yi,{label:"Health",value:z.ok||z.status==="ok"?"OK":"--",hint:"D601 /health",tone:z.ok||z.status==="ok"?"ok":"warn"}),a(Yi,{label:"NapCat HTTP",value:D.httpConnected||D.http?.connected?"OK":"离线",hint:`${D.httpHost||z.napcat?.httpHost||"--"}:${D.httpPort||z.napcat?.httpPort||"--"}`}),a(Yi,{label:"NapCat WS",value:D.wsConnected||D.ws?.connected?"OK":"离线",hint:`${D.wsHost||z.napcat?.wsHost||"--"}:${D.wsPort||z.napcat?.wsPort||"--"}`}),a(Yi,{label:"事件缓存",value:Q5(n.events?.count??Y.length),hint:"recent QQ events"}),a(Yi,{label:"订阅",value:Q5(n.subscriptions?.count??p.length),hint:"webhook subscribers"}),a(Yi,{label:"已发送",value:Q5(n.sent?.count??O.length),hint:"sent message log"})),a("div",{className:"findjob-grid"},a(Si,{title:"NapCat 容器登录",eyebrow:"QR Login",className:"claudeqq-login-panel",loading:n.qrLoading,actions:a("div",{className:"panel-actions inline-actions"},a("button",{type:"button",className:"ghost-btn",onClick:()=>Q(!0),disabled:n.qrLoading,"data-testid":"claudeqq-napcat-refresh"},n.qrLoading?"刷新中":"手动刷新二维码"),a(O_,{title:"NapCat Login",data:n.napcatLogin,onOpen:f,testId:"raw-claudeqq-napcat-login"}))},a("div",{className:"claudeqq-login-card","data-testid":"claudeqq-napcat-login"},a("div",{className:"claudeqq-qr-frame"},v?a("img",{src:V.dataUrl,alt:"NapCat QQ 登录二维码","data-testid":"claudeqq-napcat-qrcode"}):a(H_,{title:"等待二维码",text:"NapCat 容器启动后会把登录二维码写入 cache/qrcode.png"})),a("div",{className:"claudeqq-login-copy"},a("div",{className:"node-version-line"},a(Ht,{status:m?"online":v?"warn":"unknown"},m?"已登录":v?"待扫码":"等待二维码"),a("span",null,X),a("span",null,"D601 containerized")),a("p",{className:"muted paragraph"},m?"NapCat 已登录,ClaudeQQ 可通过容器内 HTTP/WS 链路收发 QQ 消息。":"用手机 QQ 扫描二维码授权登录。二维码只在首次加载或手动刷新时更新,D601 的 NapCat 端口仍只绑定 127.0.0.1。"),a("div",{className:"microservice-ref-card"},a("span",null,"NapCat WebUI"),a("strong",null,D.webui?.url||"http://napcat:6099/webui"),a("code",null,"local-only / proxied QR login")),a("div",{className:"microservice-ref-card"},a("span",null,"QR Source"),a("strong",null,V.modifiedAt?Nu(V.modifiedAt):n.qrcodeRefreshedAt?Nu(n.qrcodeRefreshedAt):"--"),a("code",null,V.file||"/napcat/cache/qrcode.png"))))),a(Si,{title:"消息推送",eyebrow:"Push API"},a("div",{className:"microservice-ref-card"},a("span",null,U1.label),a("strong",null,String(U1.userId)),a("code",null,"private userId / 默认推送测试目标")),a("form",{className:"stack-form",onSubmit:L,"data-testid":"claudeqq-push-form"},a("label",null,"目标类型",a("select",{value:y.targetType,onChange:(T)=>_((S)=>({...S,targetType:T.target.value}))},a("option",{value:"private"},"私聊 userId"),a("option",{value:"group"},"群 groupId"))),a("label",null,"QQ ID",a("input",{value:y.targetId,onChange:(T)=>_((S)=>({...S,targetId:T.target.value})),placeholder:String(U1.userId)})),a("label",null,"消息内容",a("textarea",{value:y.message,onChange:(T)=>_((S)=>({...S,message:T.target.value})),rows:4,placeholder:"通过 ClaudeQQ 推送一条 QQ 消息"})),a("button",{type:"submit",className:"primary-btn"},"发送 QQ 消息")),a("p",{className:"muted paragraph"},`主 server 和其他用户服务可通过 UniDesk 同源代理调用 /api/push/text;当前人工推送测试默认使用 ${U1.label} ${U1.userId},不需要暴露 D601 后端端口。`)),a(Si,{title:"QQ 事件订阅",eyebrow:"Webhook Subscription",loading:n.loading},a("form",{className:"stack-form",onSubmit:w,"data-testid":"claudeqq-subscription-form"},a("label",null,"订阅名称",a("input",{value:$.name,onChange:(T)=>A((S)=>({...S,name:T.target.value}))})),a("label",null,"回调 URL",a("input",{value:$.targetUrl,onChange:(T)=>A((S)=>({...S,targetUrl:T.target.value})),placeholder:"http://host.docker.internal:18080/..."})),a("label",null,"事件类型",a("input",{value:$.eventTypes,onChange:(T)=>A((S)=>({...S,eventTypes:T.target.value})),placeholder:"message,notice"})),a("label",null,"签名密钥",a("input",{value:$.secret,onChange:(T)=>A((S)=>({...S,secret:T.target.value})),placeholder:"可选,生成 x-claudeqq-signature"})),a("button",{type:"submit",className:"primary-btn"},"创建订阅")),p.length===0?a(H_,{title:"暂无订阅",text:"可以为 main server 或其他用户服务注册 HTTP webhook"}):a("div",{className:"table-wrap","data-testid":"claudeqq-subscription-table"},a("table",null,a("thead",null,a("tr",null,a("th",null,"名称"),a("th",null,"状态"),a("th",null,"事件"),a("th",null,"回调"),a("th",null,"最近投递"),a("th",null,"操作"))),a("tbody",null,p.map((T)=>a("tr",{key:T.id},a("td",null,a("strong",null,T.name||T.id),a("code",null,T.id||"--")),a("td",null,a(Ht,{status:T.enabled?"online":"warn"},T.enabled?"enabled":"disabled")),a("td",null,Array.isArray(T.eventTypes)?T.eventTypes.join(", "):"message"),a("td",null,T.targetUrl||"--"),a("td",null,T.lastDelivery?`${T.lastDelivery.ok?"OK":"FAIL"} ${Nu(T.lastDelivery.at)}`:"--"),a("td",null,a("button",{type:"button",className:"ghost-btn",onClick:()=>J(T.id)},"删除"))))))),a("div",{className:"panel-actions inline-actions"},a(O_,{title:"ClaudeQQ Subscriptions",data:n.subscriptions,onOpen:f,testId:"raw-claudeqq-subscriptions"}))),a(Si,{title:"最近 QQ 事件",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Event Stream",loading:n.loading},Y.length===0?a(H_,{title:"暂无事件",text:"等待 NapCat WebSocket 上报 QQ 消息事件,或通过订阅 API 消费后续事件"}):a("div",{className:"table-wrap","data-testid":"claudeqq-event-list"},a("table",null,a("thead",null,a("tr",null,a("th",null,"时间"),a("th",null,"类型"),a("th",null,"会话"),a("th",null,"消息"),a("th",null,"ID"))),a("tbody",null,Y.map((T)=>a("tr",{key:T.id},a("td",null,Nu(T.receivedAt||T.timestamp)),a("td",null,a(Ht,{status:T.postType||T.eventType},T.postType||T.eventType||"--")),a("td",null,$U(T)),a("td",null,_U(T)),a("td",null,a("code",null,T.messageId||T.id||"--"))))))),a("div",{className:"panel-actions inline-actions"},a(O_,{title:"ClaudeQQ Events",data:n.events,onOpen:f,testId:"raw-claudeqq-events"}))),a(Si,{title:"已发送消息",eyebrow:`${O.length} Sent`,loading:n.loading},O.length===0?a(H_,{title:"暂无发送记录",text:"发送日志来自 ClaudeQQ bot_workspace/messages/sent_messages.jsonl"}):a("div",{className:"table-wrap"},a("table",null,a("thead",null,a("tr",null,a("th",null,"时间"),a("th",null,"目标"),a("th",null,"消息"),a("th",null,"结果"))),a("tbody",null,O.map((T,S)=>a("tr",{key:T.id||S},a("td",null,Nu(T.timestamp||T.sentAt||T.createdAt)),a("td",null,$U(T)),a("td",null,_U(T)),a("td",null,T.status||T.messageId||T.message_id||"--")))))),a("div",{className:"panel-actions inline-actions"},a(O_,{title:"ClaudeQQ Sent Messages",data:n.sent,onOpen:f,testId:"raw-claudeqq-sent"})))))}var P_=Pu(qf(),1);var jU=Pu(qf(),1),Uf=jU.default.createElement;function FU({markdown:u,className:f,testId:l}){let r=String(u??"").trimEnd(),n=["markdown-body",f].filter(Boolean).join(" ");return Uf("div",{className:n,"data-testid":l},JU(r,"md"))}function JU(u,f){let l=jT(u).split(` +`),r=[],n=0;while(n\s?/u.test(i)){let j=[];while(n\s?(.*)$/u);if(U!==null){j.push(U[1]),n+=1;continue}if(F.trim().length===0){j.push(""),n+=1;continue}break}r.push(Uf("blockquote",{key:`${f}-quote-${n}`},JU(j.join(` +`),`${f}-quote-${n}`)));continue}if(QU(l,n)){let j=n,F=B_(l[n]??""),U=B_(l[n+1]??"");n+=2;let Q=[];while(n0)Q.push(B_(l[n]??"")),n+=1;r.push(qT(F,U,Q,`${f}-table-${j}`));continue}let $=Dt(i);if($!==null){let j=n,F=$.ordered,U=$.start,Q=[];while(nUT(w,`${f}-list-${j}-${J}`))));continue}let A=n,c=[];while(n0&&!JT(l,n))c.push(l[n].trim()),n+=1;if(c.length===0)c.push(i.trim()),n+=1;r.push(Uf("p",{key:`${f}-p-${A}`},n0(c.join(` +`),`${f}-p-${A}`)))}return r}function jT(u){return String(u||"").replace(/\r\n/gu,` `).replace(/\r/gu,` -`).trimEnd()}function jU(u){let f=u.match(/^\s*(```+|~~~+)\s*([A-Za-z0-9_-]+)?\s*$/u);if(f===null)return null;let l=f[1];return{marker:l.startsWith("`")?"`":"~",length:l.length,language:f[2]||""}}function yT(u,f){let l=u.trim();return l.length>=f.length&&l.split("").every((r)=>r===f.marker)}function qc(u){return/^(?: {4}|\t)/u.test(u)}function _U(u,f,l){let r=f.trim().length>0?`language-${jT(f)}`:void 0;return Uf("pre",{key:l,className:"markdown-code-block"},Uf("code",{className:r},u))}function _T(u,f){let l=u[f]??"";if(l.trim().length===0)return!0;return jU(l)!==null||qc(l)||/^(#{1,6})\s+.+$/u.test(l)||/^\s*(?:---+|\*\*\*+|___+)\s*$/u.test(l)||/^\s*>\s?/u.test(l)||FU(u,f)||V3(l)!==null}function V3(u){let f=u.match(/^\s{0,3}[-*+]\s+(.+)$/u);if(f!==null)return{ordered:!1,text:f[1]};let l=u.match(/^\s{0,3}(\d+)[.)]\s+(.+)$/u);if(l!==null)return{ordered:!0,start:Number(l[1]),text:l[2]};return null}function $T(u,f){let l=u.match(/^\[([ xX])\]\s+(.+)$/u);if(l!==null){let r=l[1].toLowerCase()==="x";return Uf("li",{key:f,className:"task-list-item"},Uf("input",{type:"checkbox",checked:r,readOnly:!0,tabIndex:-1}),Uf("span",null,r0(l[2],`${f}-task`)))}return Uf("li",{key:f},r0(u,f))}function FU(u,f){let l=u[f]??"",r=u[f+1]??"";if(!l.includes("|")||!r.includes("|"))return!1;let n=B_(l),i=B_(r);return n.length>1&&i.length===n.length&&i.every((y)=>/^:?-{3,}:?$/u.test(y.trim()))}function B_(u){let f=u.trim();if(f.startsWith("|"))f=f.slice(1);if(f.endsWith("|"))f=f.slice(0,-1);return f.split("|").map((l)=>l.trim())}function tT(u){let f=u.trim();if(f.startsWith(":")&&f.endsWith(":"))return"center";if(f.endsWith(":"))return"right";if(f.startsWith(":"))return"left";return}function cT(u,f,l,r){let n=f.map(tT);return Uf("div",{key:r,className:"markdown-table-wrap"},Uf("table",null,Uf("thead",null,Uf("tr",null,u.map((i,y)=>Uf("th",{key:`${r}-h-${y}`,style:n[y]?{textAlign:n[y]}:void 0},r0(i,`${r}-h-${y}`))))),Uf("tbody",null,l.map((i,y)=>Uf("tr",{key:`${r}-r-${y}`},u.map((_,$)=>Uf("td",{key:`${r}-r-${y}-${$}`,style:n[$]?{textAlign:n[$]}:void 0},r0(i[$]||"",`${r}-r-${y}-${$}`))))))))}function r0(u,f,l={}){let r=[],n=/`([^`\n]+)`|\[([^\]\n]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)|(https?:\/\/[^\s<>)]+)|\*\*([^*\n]+)\*\*|__([^_\n]+)__|~~([^~\n]+)~~|\*([^*\n]+)\*|_([^_\n]+)_/gu,i=l.linkify!==!1,y=0,_=0;for(let $ of u.matchAll(n)){let c=$[0],A=$.index??0;B3(r,u.slice(y,A),`${f}-text-${_}`),y=A+c.length;let j=`${f}-inline-${_}`;if(_+=1,$[1]!==void 0){r.push(Uf("code",{key:j},$[1]));continue}if($[2]!==void 0&&$[3]!==void 0){if(!i){B3(r,c,`${j}-literal`);continue}r.push($U($[2],$[3],j));continue}if($[4]!==void 0){if(!i){B3(r,c,`${j}-literal`);continue}r.push($U($[4],$[4],j));continue}let F=$[5]??$[6];if(F!==void 0){r.push(Uf("strong",{key:j},r0(F,`${j}-strong`)));continue}if($[7]!==void 0){r.push(Uf("del",{key:j},r0($[7],`${j}-del`)));continue}let U=$[8]??$[9];if(U!==void 0)r.push(Uf("em",{key:j},r0(U,`${j}-em`)))}return B3(r,u.slice(y),`${f}-text-tail`),r}function B3(u,f,l){if(f.length===0)return;f.split(` -`).forEach((n,i)=>{if(i>0)u.push(Uf("br",{key:`${l}-br-${i}`}));if(n.length>0)u.push(n)})}function $U(u,f,l){let r=AT(f);if(r===null)return Uf("span",{key:l},u);let n=/^(?:https?:|mailto:)/iu.test(r);return Uf("a",{key:l,href:r,target:n?"_blank":void 0,rel:n?"noreferrer":void 0},r0(u,`${l}-label`,{linkify:!1}))}function AT(u){let f=String(u||"").trim();if(/^(?:https?:|mailto:)/iu.test(f))return f;if(f.startsWith("/")&&!f.startsWith("//"))return f;if(f.startsWith("#"))return f;return null}function jT(u){return String(u||"").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-").replace(/^-+|-+$/gu,"")||"text"}var Gc=Mu(Qf(),1);var Yu=Gc.default.createElement,{useEffect:FT,useRef:JU}=Gc.default;function JT(u,f){return BU(u.toTrace(f))}function UT(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.floor(f/1000),r=Math.floor(l/3600),n=Math.floor(l%3600/60),i=l%60;if(r>0)return`${r}h ${String(n).padStart(2,"0")}m`;if(n>0)return`${n}m ${String(i).padStart(2,"0")}s`;return`${i}s`}function Mr(u){let f=Number(u);return Number.isFinite(f)&&f>=0?f:null}function pi(u,f=180){let l=String(u||"").replace(/\s+/gu," ").trim();return l.length>f?`${l.slice(0,f-1)}…`:l}function QT(u){if(!u)return 0;return u.split(/\r?\n/u).length}function wc(u){return{ran:"Ran",explored:"Explored",edited:"Edited",toolGroup:"Tool calls",plan:"Plan",message:"Message",system:"System",error:"Error"}[u]||"Message"}function Lc(u){let f=Number(u||0);return Number.isFinite(f)&&f>0?`… +${Math.floor(f)} lines`:""}function qT(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,Number(l?.seq??0)),0)}function UU(u){return["explored","edited","ran"].includes(String(u?.kind||""))}function GU(u){let f={read:0,edit:0,run:0};for(let l of u){let r=String(l?.kind||"");if(r==="explored")f.read+=1;else if(r==="edited")f.edit+=1;else if(r==="ran")f.run+=1}return f}function zU(u){let f=GU(u);return`${f.read} read, ${f.edit} edit, ${f.run} run`}function TU(u){return u.replace(/^['"`([{<]+/u,"").replace(/['"`)\]}>.,;:]+$/u,"").replace(/:\d+(?::\d+)?$/u,"").trim()}function QU(u){let l=String(u||"").match(/(?:~|\.{1,2}|\/)?(?:[A-Za-z0-9_.@+-]+\/)+[A-Za-z0-9_.@+-]+|[A-Za-z0-9_.@+-]+\.(?:c|cc|cpp|h|hpp|js|jsx|ts|tsx|json|md|py|sh|toml|ya?ml|txt|log|lock)/gu)||[],r=[];for(let n of l){let i=TU(n);if(i.length<2||i.includes("..."))continue;if(/^(http|https|status|method)$/iu.test(i))continue;if(!r.includes(i))r.push(i)}return r}function Nc(u,f=4){if(u.length===0)return"--";let l=u.slice(0,f).join(", ");return u.length>f?`${l} +${u.length-f}`:l}function qU(u){let f="";for(let l of u){if(l.length===0)continue;if(f.length>0&&!f.endsWith(` +`).trimEnd()}function UU(u){let f=u.match(/^\s*(```+|~~~+)\s*([A-Za-z0-9_-]+)?\s*$/u);if(f===null)return null;let l=f[1];return{marker:l.startsWith("`")?"`":"~",length:l.length,language:f[2]||""}}function FT(u,f){let l=u.trim();return l.length>=f.length&&l.split("").every((r)=>r===f.marker)}function q5(u){return/^(?: {4}|\t)/u.test(u)}function AU(u,f,l){let r=f.trim().length>0?`language-${WT(f)}`:void 0;return Uf("pre",{key:l,className:"markdown-code-block"},Uf("code",{className:r},u))}function JT(u,f){let l=u[f]??"";if(l.trim().length===0)return!0;return UU(l)!==null||q5(l)||/^(#{1,6})\s+.+$/u.test(l)||/^\s*(?:---+|\*\*\*+|___+)\s*$/u.test(l)||/^\s*>\s?/u.test(l)||QU(u,f)||Dt(l)!==null}function Dt(u){let f=u.match(/^\s{0,3}[-*+]\s+(.+)$/u);if(f!==null)return{ordered:!1,text:f[1]};let l=u.match(/^\s{0,3}(\d+)[.)]\s+(.+)$/u);if(l!==null)return{ordered:!0,start:Number(l[1]),text:l[2]};return null}function UT(u,f){let l=u.match(/^\[([ xX])\]\s+(.+)$/u);if(l!==null){let r=l[1].toLowerCase()==="x";return Uf("li",{key:f,className:"task-list-item"},Uf("input",{type:"checkbox",checked:r,readOnly:!0,tabIndex:-1}),Uf("span",null,n0(l[2],`${f}-task`)))}return Uf("li",{key:f},n0(u,f))}function QU(u,f){let l=u[f]??"",r=u[f+1]??"";if(!l.includes("|")||!r.includes("|"))return!1;let n=B_(l),i=B_(r);return n.length>1&&i.length===n.length&&i.every((y)=>/^:?-{3,}:?$/u.test(y.trim()))}function B_(u){let f=u.trim();if(f.startsWith("|"))f=f.slice(1);if(f.endsWith("|"))f=f.slice(0,-1);return f.split("|").map((l)=>l.trim())}function QT(u){let f=u.trim();if(f.startsWith(":")&&f.endsWith(":"))return"center";if(f.endsWith(":"))return"right";if(f.startsWith(":"))return"left";return}function qT(u,f,l,r){let n=f.map(QT);return Uf("div",{key:r,className:"markdown-table-wrap"},Uf("table",null,Uf("thead",null,Uf("tr",null,u.map((i,y)=>Uf("th",{key:`${r}-h-${y}`,style:n[y]?{textAlign:n[y]}:void 0},n0(i,`${r}-h-${y}`))))),Uf("tbody",null,l.map((i,y)=>Uf("tr",{key:`${r}-r-${y}`},u.map((_,$)=>Uf("td",{key:`${r}-r-${y}-${$}`,style:n[$]?{textAlign:n[$]}:void 0},n0(i[$]||"",`${r}-r-${y}-${$}`))))))))}function n0(u,f,l={}){let r=[],n=/`([^`\n]+)`|\[([^\]\n]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)|(https?:\/\/[^\s<>)]+)|\*\*([^*\n]+)\*\*|__([^_\n]+)__|~~([^~\n]+)~~|\*([^*\n]+)\*|_([^_\n]+)_/gu,i=l.linkify!==!1,y=0,_=0;for(let $ of u.matchAll(n)){let A=$[0],c=$.index??0;Vt(r,u.slice(y,c),`${f}-text-${_}`),y=c+A.length;let j=`${f}-inline-${_}`;if(_+=1,$[1]!==void 0){r.push(Uf("code",{key:j},$[1]));continue}if($[2]!==void 0&&$[3]!==void 0){if(!i){Vt(r,A,`${j}-literal`);continue}r.push(cU($[2],$[3],j));continue}if($[4]!==void 0){if(!i){Vt(r,A,`${j}-literal`);continue}r.push(cU($[4],$[4],j));continue}let F=$[5]??$[6];if(F!==void 0){r.push(Uf("strong",{key:j},n0(F,`${j}-strong`)));continue}if($[7]!==void 0){r.push(Uf("del",{key:j},n0($[7],`${j}-del`)));continue}let U=$[8]??$[9];if(U!==void 0)r.push(Uf("em",{key:j},n0(U,`${j}-em`)))}return Vt(r,u.slice(y),`${f}-text-tail`),r}function Vt(u,f,l){if(f.length===0)return;f.split(` +`).forEach((n,i)=>{if(i>0)u.push(Uf("br",{key:`${l}-br-${i}`}));if(n.length>0)u.push(n)})}function cU(u,f,l){let r=NT(f);if(r===null)return Uf("span",{key:l},u);let n=/^(?:https?:|mailto:)/iu.test(r);return Uf("a",{key:l,href:r,target:n?"_blank":void 0,rel:n?"noreferrer":void 0},n0(u,`${l}-label`,{linkify:!1}))}function NT(u){let f=String(u||"").trim();if(/^(?:https?:|mailto:)/iu.test(f))return f;if(f.startsWith("/")&&!f.startsWith("//"))return f;if(f.startsWith("#"))return f;return null}function WT(u){return String(u||"").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-").replace(/^-+|-+$/gu,"")||"text"}var G5=Pu(qf(),1);var Su=G5.default.createElement,{useEffect:LT,useRef:qU}=G5.default;function wT(u,f){return XU(u.toTrace(f))}function KT(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.floor(f/1000),r=Math.floor(l/3600),n=Math.floor(l%3600/60),i=l%60;if(r>0)return`${r}h ${String(n).padStart(2,"0")}m`;if(n>0)return`${n}m ${String(i).padStart(2,"0")}s`;return`${i}s`}function Rr(u){let f=Number(u);return Number.isFinite(f)&&f>=0?f:null}function mi(u,f=180){let l=String(u||"").replace(/\s+/gu," ").trim();return l.length>f?`${l.slice(0,f-1)}…`:l}function GT(u){if(!u)return 0;return u.split(/\r?\n/u).length}function L5(u){return{ran:"Ran",explored:"Explored",edited:"Edited",toolGroup:"Tool calls",plan:"Plan",message:"Message",system:"System",error:"Error"}[u]||"Message"}function w5(u){let f=Number(u||0);return Number.isFinite(f)&&f>0?`… +${Math.floor(f)} lines`:""}function zT(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,Number(l?.seq??0)),0)}function NU(u){return["explored","edited","ran"].includes(String(u?.kind||""))}function EU(u){let f={read:0,edit:0,run:0};for(let l of u){let r=String(l?.kind||"");if(r==="explored")f.read+=1;else if(r==="edited")f.edit+=1;else if(r==="ran")f.run+=1}return f}function ZU(u){let f=EU(u);return`${f.read} read, ${f.edit} edit, ${f.run} run`}function OU(u){return u.replace(/^['"`([{<]+/u,"").replace(/['"`)\]}>.,;:]+$/u,"").replace(/:\d+(?::\d+)?$/u,"").trim()}function WU(u){let l=String(u||"").match(/(?:~|\.{1,2}|\/)?(?:[A-Za-z0-9_.@+-]+\/)+[A-Za-z0-9_.@+-]+|[A-Za-z0-9_.@+-]+\.(?:c|cc|cpp|h|hpp|js|jsx|ts|tsx|json|md|py|sh|toml|ya?ml|txt|log|lock)/gu)||[],r=[];for(let n of l){let i=OU(n);if(i.length<2||i.includes("..."))continue;if(/^(http|https|status|method)$/iu.test(i))continue;if(!r.includes(i))r.push(i)}return r}function N5(u,f=4){if(u.length===0)return"--";let l=u.slice(0,f).join(", ");return u.length>f?`${l} +${u.length-f}`:l}function LU(u){let f="";for(let l of u){if(l.length===0)continue;if(f.length>0&&!f.endsWith(` `)&&!l.startsWith(` `))f+=` -`;f+=l}return f}function EU(u){let f=String(u||"").replace(/\r\n/gu,` +`;f+=l}return f}function HU(u){let f=String(u||"").replace(/\r\n/gu,` `).replace(/\r/gu,` `).trimEnd();return f.length>0?f.split(` -`):[]}function Kc(u){let f=String(u.status||"").trim();if(f.length>0)return f;let l=String(u.bodyPreview||"");return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(l)?.[1]||"item/fileChange"}function NT(u){let f=String(u.bodyPreview||"");return/file changes status=([A-Za-z0-9_-]+)/u.exec(f)?.[1]}function WT(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function ZU(u){if(String(u.kind||"")!=="edited")return!1;let f=String(u.status||""),l=String(u.title||""),r=String(u.bodyPreview||""),n=String(u.commandPreview||"");if(l==="Edited files")return!0;if(/^item\/fileChange\//u.test(f))return!0;if((f==="item/started"||f==="item/completed")&&/file changes status=/u.test(r))return!0;if(/^Success\. Updated the following files:/mu.test(r))return!0;if(/^diff --git /mu.test(r))return!0;return/^([AMDRCU?]{1,2})\s+\S+/mu.test(r)||n.length>0&&X3(r).length>0}function mi(u){return TU(String(u||"").replace(/^[ab]\//u,"").trim())}function zc(u){let f=/^([AMDRCU?]{1,2})\s+(.+)$/u.exec(u);if(!f)return null;let l=mi(f[2]||"");return l.length>0?{status:f[1]||"M",path:l}:null}function Tc(u){let f=/^\*\*\*\s+(Add|Update|Delete)\s+File:\s+(.+)$/u.exec(u);if(f){let r=f[1]==="Add"?"A":f[1]==="Delete"?"D":"M",n=mi(f[2]||"");return n.length>0?{status:r,path:n}:null}let l=/^\*\*\*\s+Move to:\s+(.+)$/u.exec(u);if(l){let r=mi(l[1]||"");return r.length>0?{status:"R",path:r}:null}return null}function X3(u){let f=[],l=(n,i)=>{let y=mi(i);if(y.length===0||y==="/dev/null")return;let _=f.find(($)=>$.path===y);if(_){if(_.status==="M"&&n!=="M")_.status=n;return}f.push({status:n,path:y})},r="";for(let n of EU(u)){let i=zc(n)||Tc(n);if(i!==null){l(i.status,i.path),r=i.path;continue}let y=/^diff --git a\/(.+?) b\/(.+)$/u.exec(n);if(y){let j=y[2]||y[1]||"";l("M",j),r=mi(j);continue}let _=/^\+\+\+ b\/(.+)$/u.exec(n);if(_&&_[1]!=="/dev/null"){l("M",_[1]||""),r=mi(_[1]||"");continue}if(/^new file mode /u.exec(n)&&r)l("A",r);if(/^deleted file mode /u.exec(n)&&r)l("D",r);let A=/^rename to (.+)$/u.exec(n);if(A)l("R",A[1]||"")}return f}function wT(u){if(zc(u)!==null||Tc(u)!==null)return"file";if(/^(diff --git |index |--- |\+\+\+ |\*\*\* Begin Patch|\*\*\* End Patch)/u.test(u))return"meta";if(/^@@ /u.test(u))return"hunk";if(/^\+/u.test(u))return"add";if(/^-/u.test(u))return"del";if(/^(Success\.|No changes|Updated\b|Created\b|Deleted\b|Added\s+\d+\s+lines?|Wrote\s+\d+\s+lines?|Read\s+\d+\s+files?|\.\.\.\[patch content truncated)/iu.test(u))return"note";return"context"}function Ec(u){return EU(u).map((f)=>{let l=zc(f)||Tc(f);if(l!==null)return{text:f,kind:"file",path:l.path,status:l.status};return{text:f,kind:wT(f)}})}function LT(u){return u.reduce((f,l)=>{if(l.kind==="add")f.added+=1;else if(l.kind==="del")f.removed+=1;return f},{added:0,removed:0})}function NU(u,f){return`${f} ${u} line${u===1?"":"s"}`}function KT(u,f){let l=[];if(u>0)l.push(NU(u,"Added"));if(f>0)l.push(NU(f,"removed"));return l.join(", ")}function GT(u){for(let l=u.length-1;l>=0;l-=1){let r=String(u[l]?.status||"").trim();if(r.length>0)return r}let f=String(u[u.length-1]?.method||"").trim();if(f==="item/fileChange/outputDelta")return"updated";if(f==="item/started")return"started";if(f==="item/completed")return"completed";return f.replace(/^item\//u,"")||"changed"}function zT(u){return`${u} file${u===1?"":"s"}`}function OU(u){let f=u.length>0?u:[],l=qU(f.map((F)=>String(F.bodyPreview||""))),n=qU(f.map((F)=>String(F.bodyPreview||"")).filter((F)=>F.trim().length>0&&!WT(F)))||l,i=X3(n||l),y=f.map((F)=>({method:Kc(F),status:NT(F),at:F.at})),_=Ec(n||l),$=LT(_),c=KT($.added,$.removed),A=i.length>0?zT(i.length):"",j=c.length>0?`${c}${A?` in ${A}`:""}`:i.length>0?A:pi(n||l||"File changes",72);return{status:GT(y),summary:j,files:i,stages:y,lines:_,addedLines:$.added,removedLines:$.removed,rawText:l}}function TT(u){let f=u[0],l=u[u.length-1]||f,r=OU(u);return{...f,seq:Number.isFinite(Number(l?.seq))?Number(l?.seq):Number(f?.seq??0),at:l?.at||f?.at,title:r.files.length>0?`Edited ${r.summary}`:"Edited files",status:r.status,commandPreview:"",commandOmittedLines:void 0,bodyPreview:r.rawText,bodyOmittedLines:u.reduce((n,i)=>n+Number(i.bodyOmittedLines||0),0)||void 0,rawSeqs:u.flatMap((n)=>Array.isArray(n?.rawSeqs)?n.rawSeqs:[n?.seq]).filter((n)=>n!==void 0),editObservation:r}}function ET(u){let f=Array.isArray(u)?u:[],l=[],r=[],n=()=>{if(r.length===0)return;l.push(TT(r)),r=[]};for(let i of f){if(ZU(i)){if(Kc(i)==="item/started"&&r.length>0)n();if(r.push(i),Kc(i)==="item/completed")n();continue}n(),l.push(i)}return n(),l}function HU(u){let f=[],l=[],r=[],n=(c,A)=>{for(let j of A)if(!c.includes(j))c.push(j)};for(let c of u){let A=String(c?.kind||""),j=[c?.commandPreview,c?.bodyPreview,c?.title].map((F)=>String(F||"")).join(` -`);if(A==="explored")n(f,QU(j));else if(A==="edited")n(l,QU(j));else if(A==="ran"){let F=String(c?.commandPreview||c?.title||"").trim();if(F.length>0&&!r.includes(F))r.push(pi(F,90))}}let i=u.map((c)=>Date.parse(String(c?.at||""))).filter((c)=>Number.isFinite(c)),y=i.length>=2?Math.max(0,Math.max(...i)-Math.min(...i)):0,_=u.reduce((c,A)=>c+(Mr(A?.durationMs)??Mr(A?.elapsedMs)??0),0),$=y>0?y:_;return{readFiles:f,editedFiles:l,runCommands:r,durationLabel:UT($)}}function ZT(u,f=3){let l=Array.isArray(u)?u:[],r=[],n=[],i=Math.max(0,f),y=new Set;for(let $=l.length-1;$>=0&&i>0;$-=1){let c=l[$];if(!UU(c))continue;y.add(c),i-=1}let _=()=>{if(n.length>=2){let $=GU(n);r.push({seq:Number(n[0]?.seq??0),at:n[0]?.at||n.at(-1)?.at,kind:"toolGroup",title:zU(n),status:`${n.length} calls`,items:n,counts:$,digest:HU(n),rawSeqs:n.flatMap((c)=>Array.isArray(c?.rawSeqs)?c.rawSeqs:[c?.seq]).filter((c)=>c!==void 0)})}else r.push(...n);n=[]};for(let $ of l){if(UU($)&&!y.has($)){n.push($);continue}_(),r.push($)}return _(),r}function BU(u){return(Array.isArray(u)?u:[]).map((f,l)=>({...f,seq:Number.isFinite(Number(f?.seq))?Number(f.seq):l+1,kind:String(f?.kind||"message"),at:f?.at===void 0?void 0:String(f.at),durationMs:Mr(f?.durationMs)??void 0,title:f?.title===void 0?void 0:String(f.title),status:f?.status===void 0?void 0:String(f.status)}))}function V_(u){let f=Mr(u?.state?.time?.start)??Mr(u?.time?.start),l=Mr(u?.state?.time?.end)??Mr(u?.time?.end);return Mr(u?.durationMs)??Mr(u?.elapsedMs)??Mr(u?.timing?.durationMs)??Mr(u?.metadata?.durationMs)??(f!==null&&l!==null&&l>=f?l-f:null)??void 0}function D_(u,f){return u?.createdAt||u?.updatedAt||u?.completedAt||f||void 0}function Wc(u,f){return u?.id||u?.messageId||f}function OT(u,f=1200){if(typeof u==="string")return u;if(u===void 0||u===null)return"";try{return pi(JSON.stringify(u),f)}catch{return pi(String(u),f)}}function VU(u,f,l){if(typeof u?.metadata?.diff==="string"&&u.metadata.diff.length>0)return u.metadata.diff;if(typeof u?.metadata?.filediff?.patch==="string"&&u.metadata.filediff.patch.length>0)return u.metadata.filediff.patch;if(typeof u?.output==="string"&&u.output.length>0)return u.output;if(typeof u?.result==="string"&&u.result.length>0)return u.result;if(typeof f?.output==="string"&&f.output.length>0)return f.output;if(typeof l?.output==="string"&&l.output.length>0)return l.output;if(typeof u?.metadata?.output==="string"&&u.metadata.output.length>0)return u.metadata.output;return""}function D3(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return"";for(let l of f){let r=u[l];if(typeof r==="string"&&r.length>0)return r;if(r!==void 0&&r!==null&&typeof r!=="object")return String(r)}return""}function WU(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return null;for(let l of f){let r=Number(u[l]);if(Number.isFinite(r))return r}return null}function DU(u,f){let l=f?.input&&typeof f.input==="object"&&!Array.isArray(f.input)?f.input:u?.input&&typeof u.input==="object"&&!Array.isArray(u.input)?u.input:{},r=D3(l,["command","cmd","script"]);if(r.length>0)return r;if(typeof u?.command==="string"&&u.command.length>0)return u.command;if(typeof f?.command==="string"&&f.command.length>0)return f.command;let n=String(u?.tool||u?.title||"tool"),i=D3(l,["filePath","filepath","path"])||D3(u,["filePath","filepath","path"]),y=D3(l,["pattern","query"]),_=WU(l,["offset"]),$=WU(l,["limit"]),c=[n];if(y.length>0)c.push(y);if(i.length>0)c.push(i);if(_!==null)c.push(`offset=${_}`);if($!==null)c.push(`limit=${$}`);return c.length>1?c.join(" "):n}function HT(u,f){let l=u?.part&&typeof u.part==="object"&&!Array.isArray(u.part)?u.part:{},r=String(u?.type||u?.event||u?.name||l?.type||"").toLowerCase(),n=String(l?.type||"").toLowerCase(),i=u?.at||u?.timestamp||l?.updatedAt||l?.createdAt,y=Number.isFinite(Number(u?.seq))?Number(u.seq):f;if(r==="step_start"||r==="step-start"||n==="step-start")return null;if(r==="step_finish"||r==="step-finish"||n==="step-finish")return null;if(n==="tool"||/tool|bash|command/iu.test(`${r} ${n}`)){let $=l?.state&&typeof l.state==="object"&&!Array.isArray(l.state)?l.state:{},c=DU(l,$),A=VU($,l,u),j=XU(c,String(l?.tool||l?.title||"")),F=j==="edited"?{status:String($?.status||l?.status||u?.status||""),summary:pi(A||c,72),files:X3(A),stages:[],lines:Ec(A),addedLines:0,removedLines:0,rawText:A}:void 0;return{seq:y,at:D_(l,i),kind:j,title:String($?.title||l?.title||$?.metadata?.description||l?.tool||"OpenCode tool"),status:String($?.status||l?.status||u?.status||""),commandPreview:c,bodyPreview:A,durationMs:V_(l),rawSeqs:[l?.id||l?.callID||u?.sessionID||y],editObservation:F}}let _=OT(l?.text??l?.content??l?.delta??u?.text??u?.content??u?.delta,3000).trim();if(_.length>0)return{seq:y,at:D_(l,i),kind:n==="reasoning"?"message":/error|failed/iu.test(`${r} ${n}`)?"error":"message",title:n==="reasoning"?"Reasoning":/error|failed/iu.test(`${r} ${n}`)?"OpenCode error":"Assistant message",status:`opencode/${r||n||"event"}`,bodyPreview:_,durationMs:V_(l),rawSeqs:[l?.id||u?.sessionID||y]};return null}function XU(u,f){let l=`${f} ${u}`.toLowerCase();if(/\b(read|grep|glob|list|ls|find|search|view|cat|sed|rg|head|tail|wc|file)\b/iu.test(l))return"explored";if(/\b(edit|write|patch|apply|update|create|delete|apply_patch|git apply|cat >|tee .*<<|sed -i|python3? .*write_text|mkdir|rm |touch )\b/iu.test(l))return"edited";return"ran"}function BT(u){let f=[],l=1;for(let r of Array.isArray(u)?u:[]){if(r?.kind&&r?.title){let _=String(r?.status||"");if(_==="opencode/step-start"||_==="opencode/step-finish")continue;f.push({...r,seq:Number.isFinite(Number(r?.seq))?Number(r.seq):l++});continue}let n=r?.createdAt||r?.updatedAt||r?.completedAt,i=String(r?.role||"assistant").toLowerCase(),y=Array.isArray(r?.parts)?r.parts:[];if(y.length===0){if(r?.part&&(r?.sessionID||String(r?.type||"").startsWith("step_")||String(r?.type||"").includes("tool"))){let _=HT(r,l);if(_!==null)f.push(_),l=Math.max(l+1,Number(_.seq)+1)}else if(r?.textPreview)f.push({seq:l++,at:n,kind:"message",title:`${i||"assistant"} message`,status:i,bodyPreview:String(r.textPreview),rawSeqs:[r?.messageId||l]});continue}for(let _ of y){let $=String(_?.type||"").toLowerCase();if($==="step-start"||$==="step-finish")continue;if($==="text"||$==="reasoning"){let A=String(_?.textPreview||r?.textPreview||"").trim();if(A.length===0)continue;f.push({seq:l++,at:D_(_,n),kind:"message",title:$==="reasoning"?"Reasoning":i==="user"?"User message":i==="system"?"System message":"Assistant message",status:$==="reasoning"?"reasoning":i,bodyPreview:A,durationMs:V_(_),rawSeqs:[Wc(_,l)]});continue}if($==="tool"){let A=_?.state&&typeof _.state==="object"&&!Array.isArray(_.state)?_.state:{},j=DU(_,A),F=VU(A,_,{}),U=XU(j,String(_?.tool||_?.title||"")),Q=U==="edited"?{status:String(A?.status||_?.status||""),summary:pi(F||j,72),files:X3(F),stages:[],lines:Ec(F),addedLines:0,removedLines:0,rawText:F}:void 0;f.push({seq:l++,at:D_(_,n),kind:U,title:String(_?.title||_?.tool||"tool"),status:String(_?.status||""),commandPreview:j,bodyPreview:F,durationMs:V_(_),rawSeqs:[Wc(_,l)],editObservation:Q});continue}let c=String(_?.textPreview||_?.title||$||"").trim();if(c)f.push({seq:l++,at:D_(_,n),kind:"system",title:$||"part",bodyPreview:c,status:String(_?.status||""),durationMs:V_(_),rawSeqs:[Wc(_,l)]})}}return f}var YU={source:"opencode",toTrace:BT};function VT(u){return String(u||"unknown").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-")||"unknown"}function wU(u){let f=String(u||"M").toUpperCase();if(f.startsWith("A")||f==="??")return"added";if(f.startsWith("D"))return"deleted";if(f.startsWith("R"))return"renamed";return"modified"}function DT(u){if(u==="item/fileChange/outputDelta")return"delta";return u.replace(/^item\//u,"")}function XT(u,f){if(u.kind==="file"){let n=String(u.status||"M");return Yu("div",{key:`${f}-${u.text}`,className:`codex-edit-diff-line file ${wU(n)}`},Yu("span",{className:`codex-edit-file-status ${wU(n)}`},n),Yu("code",null,u.path||u.text.replace(/^([AMDRCU?]{1,2})\s+/u,"")))}let l=u.kind==="add"||u.kind==="del"?u.text.slice(0,1):u.kind==="hunk"?"@@":u.kind==="note"?"ok":"",r=u.kind==="add"||u.kind==="del"?u.text.slice(1):u.text;return Yu("div",{key:`${f}-${u.text}`,className:`codex-edit-diff-line ${u.kind}`},Yu("span",{className:"codex-edit-diff-sign"},l),Yu("code",null,r||" "))}function YT(u,f){let l=u.lines.length>0?u.lines:u.files.map((n)=>({text:`${n.status} ${n.path}`,kind:"file",path:n.path,status:n.status})),r=Number(u.addedLines||0)+Number(u.removedLines||0)>0;return Yu("div",{className:"codex-edit-observation","data-testid":"codex-edit-observation"},Yu("div",{className:"codex-edit-observation-head"},Yu("span",{className:"codex-edit-window-controls","aria-hidden":"true"},Yu("i",null),Yu("i",null),Yu("i",null)),Yu("strong",null,r?"git diff":"git diff --stat"),Yu("code",null,u.summary||"File changes")),u.stages.length>0?Yu("div",{className:"codex-edit-stage-strip"},u.stages.map((n,i)=>Yu("span",{key:`${n.method}-${i}`,className:`codex-edit-stage ${VT(n.status||n.method)}`},Yu("b",null,DT(n.method)),n.status?Yu("em",null,n.status):null))):null,l.length>0?Yu("div",{className:"codex-edit-diff",role:"list"},l.map(XT)):null,f?Yu("div",{className:"codex-edit-omitted"},`${f} (查看原始JSON获取完整记录)`):null)}function LU(u,f,l){let r=Lc(l);return Yu("div",{className:`codex-transcript-stream ${u}`,"data-testid":`codex-trace-${u}`},Yu("span",{className:"codex-transcript-stream-label"},u),Yu("pre",{className:"codex-transcript-body"},f,r?` -${r} (查看原始JSON获取完整记录)`:""))}function SU(u,f=!1){let l=String(u.kind||"message"),r=["ran","explored","edited"].includes(l),n=Lc(u.commandOmittedLines),i=Lc(u.bodyOmittedLines),y=String(u.commandPreview||(r?u.title||"":"")),_=String(u.stdoutPreview||""),$=String(u.stderrPreview||""),c=_.length>0||$.length>0,A=Boolean(u.foldedReferencePrompt)&&String(u.fullPrompt||"").length>0,j=l==="edited"&&(u.editObservation!==void 0||ZU(u))?u.editObservation||OU([u]):null;return Yu("article",{key:`${u.seq}-${l}`,className:`codex-transcript-item ${l} ${f?"nested":""}`},Yu("div",{className:"codex-transcript-main"},Yu("div",{className:"codex-transcript-title"},Yu("span",{className:"codex-output-channel"},wc(l)),r&&j===null?null:Yu("strong",null,j!==null?"File changes":String(u.title||wc(l))),u.status?Yu("code",null,String(j?.status||u.status)):null,Yu("time",null,Nu(u.at))),y&&j===null?Yu("pre",{className:"codex-transcript-command"},y,n?` -${n}`:""):null,j!==null?YT(j,i):c?Yu("div",{className:"codex-transcript-streams"},_.length>0?LU("stdout",_,u.stdoutOmittedLines):null,$.length>0?LU("stderr",$,u.stderrOmittedLines):null):u.bodyPreview?Yu("pre",{className:"codex-transcript-body"},String(u.bodyPreview),i?` -${i} (查看原始JSON获取完整记录)`:""):null,A?Yu("details",{className:"codex-initial-prompt-full","data-testid":"codex-initial-prompt-full"},Yu("summary",null,Yu("span",null,"引用注入已折叠,点击查看最终传入 Codex 的完整 prompt"),Yu("code",null,`${u.fullPromptLines||QT(String(u.fullPrompt||""))} lines / ${u.fullPromptChars||String(u.fullPrompt||"").length} chars`)),Yu("pre",{className:"codex-transcript-body codex-transcript-full-prompt","data-testid":"codex-initial-prompt-full-text"},String(u.fullPrompt||""))):null))}function ST(u){let f=Array.isArray(u.items)?u.items:[],l=u.digest&&typeof u.digest==="object"?u.digest:HU(f);return Yu("article",{key:`${u.seq}-toolGroup`,className:"codex-transcript-item toolGroup"},Yu("div",{className:"codex-transcript-main"},Yu("details",{className:"codex-tool-group","data-testid":"codex-tool-group"},Yu("summary",null,Yu("div",{className:"codex-tool-group-head"},Yu("span",{className:"codex-output-channel"},wc("toolGroup")),Yu("strong",null,String(u.title||zU(f))),Yu("code",null,String(u.status||`${f.length} calls`)),Yu("time",null,Nu(u.at)))),Yu("div",{className:"codex-tool-group-digest"},Yu("span",null,`read: ${Nc(Array.isArray(l.readFiles)?l.readFiles:[])}`),Yu("span",null,`edit: ${Nc(Array.isArray(l.editedFiles)?l.editedFiles:[])}`),Yu("span",null,`run: ${Nc(Array.isArray(l.runCommands)?l.runCommands:[],2)}`),Yu("span",null,`duration: ${l.durationLabel||"--"}`)),Yu("div",{className:"codex-tool-group-items"},f.map((r)=>SU(r,!0))))))}var mT=16;function KU(u){return u.scrollHeight-u.scrollTop-u.clientHeight<=mT}function Y3({items:u,input:f,port:l,autoScroll:r=!1,loading:n=!1,hasDetail:i=!0,emptyText:y="等待 Trace 输出...",loadingText:_="正在加载完整 Trace...",testId:$="trace-output",className:c="codex-transcript",keepRecentToolCalls:A=3,collapseTools:j=!0}){let F=JU(null),U=JU(!0),Q=ET(l?JT(l,f):BU(u)),w=j?ZT(Q,A):Q,L=qT(Q);FT(()=>{let q=F.current;if(!r||!q)return;if(!U.current&&!KU(q))return;q.scrollTop=q.scrollHeight,U.current=!0},[r,Q.length,L]);let N={className:c,ref:F,onScroll:(q)=>{let W=q.currentTarget;U.current=KU(W)},"data-testid":$};if(n&&!i)return Yu("div",N,Yu("div",{className:"codex-output-empty"},_));return Yu("div",N,w.length===0?Yu("div",{className:"codex-output-empty"},y):w.map((q)=>String(q.kind||"")==="toolGroup"?ST(q):SU(q)))}var mU=Mu(Qf(),1),N1=mU.default.createElement;function S3(...u){return u.filter(Boolean).join(" ")}function pU({title:u,children:f,actions:l,onClose:r,className:n,backdropClassName:i,bodyClassName:y,actionsClassName:_,titleId:$,testId:c,closeTestId:A,closeLabel:j="关闭",disableClose:F=!1,closeOnBackdrop:U=!0}){let Q={className:S3("raw-dialog","unidesk-dialog",n),role:"dialog","aria-modal":"true"};if($)Q["aria-labelledby"]=$;else if(typeof u==="string")Q["aria-label"]=u;if(c)Q["data-testid"]=c;return N1("div",{className:S3("modal-backdrop","unidesk-dialog-backdrop",i),role:"presentation",onClick:(w)=>{if(U&&!F&&w.target===w.currentTarget)r()}},N1("section",Q,N1("div",{className:"raw-dialog-head unidesk-dialog-head"},N1("strong",$?{id:$}:null,u),N1("button",{type:"button",className:"ghost-btn",onClick:r,disabled:F,"data-testid":A},j)),N1("div",{className:S3("unidesk-dialog-body",y)},f),l?N1("div",{className:S3("unidesk-dialog-actions",_)},l):null))}var K=P_.default.createElement,{useEffect:Gn,useMemo:PU,useRef:Df}=P_.default,Iu=P_.default.useState,pT=120,eU=24,uQ=48,PT=1200;function Zc(){return typeof document>"u"||document.visibilityState!=="hidden"}function $l(u,f="操作失败"){return Hu(u,f)}function Rr(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.floor(f/1000),r=Math.floor(l/3600),n=Math.floor(l%3600/60),i=l%60;if(r>0)return`${r}h ${String(n).padStart(2,"0")}m`;if(n>0)return`${n}m ${String(i).padStart(2,"0")}s`;return`${i}s`}function X0(u){if(u===null||u===void 0||u==="")return null;let f=u instanceof Date?u.getTime():new Date(u).getTime();return Number.isFinite(f)?f:null}function fQ(u,f=Date.now()){let l=X0(u);if(l===null)return"--";let r=Math.max(0,Math.floor((f-l)/1000));if(r<1)return"刚刚";let n=Math.floor(r/86400),i=Math.floor(r%86400/3600),y=Math.floor(r%3600/60),_=r%60;if(n>0)return`${n}天${i>0?`${i}小时`:""}前`;if(i>0)return`${i}小时${y>0?`${y}分钟`:""}前`;if(y>0)return`${y}分钟${_}秒前`;return`${_}秒前`}function lQ(...u){let f="",l=-1/0;for(let r of u){let n=String(r||"");if(n.length===0)continue;let i=X0(r);if(i!==null&&i>=l)f=n,l=i;else if(f.length===0)f=n}return f}function MT(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";if(f<1000)return`${Math.round(f)}ms`;return`${(f/1000).toFixed(f<1e4?2:1)}s`}function Xc(u,f=180){let l=String(u||"").replace(/\s+/gu," ").trim();return l.length>f?`${l.slice(0,f-1)}…`:l}async function Rf(u,f={}){return Eu(u,{strictJson:!0,retryInvalidJson:1,invalidJsonPrefix:"Code Queue 返回了无效 JSON",invalidJsonPreview:!0,responsePreviewLength:PT,...f})}function K1({status:u,children:f,title:l}){let r=String(u||"unknown").toLowerCase();return K("span",{className:`status-badge ${r}`,title:l},f||u||"unknown")}function Mi({title:u,eyebrow:f,summary:l,actions:r,children:n,className:i,loading:y}){return K("section",{className:`panel ${i||""}`},K("div",{className:"panel-head"},K("div",null,f?K("p",{className:"panel-eyebrow"},f):null,K(nf,{title:u,loading:y}),l?K("div",{className:"panel-summary"},l):null),r?K("div",{className:"panel-actions"},r):null),K("div",{className:"panel-body"},n))}function rQ({title:u,data:f,onOpen:l,testId:r}){return K("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function G1({title:u,text:f}){return K("div",{className:"empty-state"},K("strong",null,u),K("span",null,f))}function CT(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function RT(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function xf(u,f){return`${u}/code-queue-direct${f}`}function xT(u){return`${u}/microservices/oa-event-flow/proxy/api/events/stream?tags=${encodeURIComponent("service:code-queue")}`}function Rc(){return{headers:{"cache-control":"no-cache","x-unidesk-no-cache":"1"}}}function tl(u){return Array.isArray(u?.tasks)?u.tasks:[]}function Kn(u){return u?.pagination&&typeof u.pagination==="object"&&!Array.isArray(u.pagination)?u.pagination:{}}function MU(u){let f=Date.parse(String(u?.updatedAt||u?.createdAt||""));return Number.isFinite(f)?f:0}function CU(u){return X0(u?.queueEnteredAt)??X0(u?.createdAt)??X0(u?.updatedAt)??0}function hT(u,f){let l=CU(u)-CU(f);if(l!==0)return l;let r=(X0(u?.createdAt)??0)-(X0(f?.createdAt)??0);if(r!==0)return r;return String(u?.id||"").localeCompare(String(f?.id||""))}function bT(u,f=""){let l=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length>0&&!l.has(i))l.set(i,n)}return Array.from(l.values()).sort((r,n)=>{let i=sU(r)-sU(n);if(i!==0)return i;let y=String(r?.id||"")===f?0:1,_=String(n?.id||"")===f?0:1;if(y!==_)return y-_;return MU(n)-MU(r)})}function Pi(u,f=""){let l=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length===0)continue;l.set(i,{...l.get(i)||{},...n})}return bT([Array.from(l.values())],f)}function Y_(u){return Array.isArray(u?.activeTaskIds)?u.activeTaskIds.map((f)=>String(f||"")).filter(Boolean):[String(u?.activeTaskId||"")].filter(Boolean)}var Tn="__all__",vT="(max-width: 760px)",kT="(min-width: 761px)";function xl(u){return!u||u===Tn}function IT(){return typeof window<"u"&&window.matchMedia(vT).matches}function gT(u){return xl(u)?"":`&queueId=${encodeURIComponent(u)}`}function Yc(u){return String(u||"").trim().replace(/\s+/gu," ").slice(0,200)}function sT(u){let f=Yc(u);return f.length===0?"":`&search=${encodeURIComponent(f)}`}function xc(u,f=""){return`${gT(u)}${sT(f)}`}function m3(u,f){return Number(u?.counts?.[f]||0)}function RU(u,f=""){let l=new Map;for(let n of Array.isArray(u?.queues)?u.queues:[]){let i=String(n?.id||"").trim();if(i.length>0)l.set(i,{...n,name:String(n?.name||i).trim()||i})}for(let n of[String(u?.defaultQueueId||"default"),f].map((i)=>i.trim()).filter(Boolean))if(!l.has(n))l.set(n,{id:n,name:n,total:0,counts:{},activeTaskId:null,runnableTaskId:null,processing:!1});return Array.from(l.values()).sort((n,i)=>{let y=String(n?.id||"")===String(u?.defaultQueueId||"default")?0:1,_=String(i?.id||"")===String(u?.defaultQueueId||"default")?0:1;if(y!==_)return y-_;return String(n?.id||"").localeCompare(String(i?.id||""))})}function nQ(u){let f=String(u?.id||"default"),l=String(u?.name||"").trim();return l.length>0?l:f}function Sc(u){let f=String(u?.id||"default"),l=nQ(u);return l===f?f:`${l} (${f})`}function S_(u){let f=m3(u,"running")+m3(u,"judging"),l=m3(u,"queued")+m3(u,"retry_wait"),r=Number(u?.total||0),n=[Sc(u),`${r} tasks`];if(f>0)n.push(`${f} running`);if(l>0)n.push(`${l} queued`);return n.join(" · ")}function Ri(u,f){if(xl(f))return null;return u.find((l)=>String(l?.id||"")===f)||null}function xU(u,f,l,r){if(xl(l)){let i=Y_(u);return String(u?.activeTaskId||i[0]||r.find((y)=>IU(y))?.id||"")}let n=Ri(f,l);return String(n?.activeTaskId||r.find((i)=>IU(i))?.id||"")}function aT(u,f,l){if(!xl(f)){let r=Ri(u,f);return String(r?.runnableTaskId||l.find((n)=>String(n?.status||"")==="queued"||String(n?.status||"")==="retry_wait")?.id||"")}return String(l.find((r)=>String(r?.status||"")==="queued"||String(r?.status||"")==="retry_wait")?.id||"")}async function oT(u,f=Tn,l=""){return Rf(xf(u,`/api/tasks/overview?limit=${eU}&transcriptLimit=1&compact=1&selected=0${xc(f,l)}`),Rc())}async function dT(u,f,l=0,r=Tn,n=""){return Rf(xf(u,`/api/tasks/overview?limit=${eU}&transcriptLimit=3&compact=1&afterSeq=${encodeURIComponent(String(Math.max(0,l)))}&preferId=${encodeURIComponent(f)}${xc(r,n)}`),Rc())}async function hU(u,f,l,r=uQ,n=""){return Rf(xf(u,`/api/tasks/overview?limit=${encodeURIComponent(String(r))}&transcriptLimit=1&compact=1&selected=0&includeActive=0&stats=0&beforeId=${encodeURIComponent(l)}${xc(f,n)}`),Rc())}async function eT(u,f){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-summary`))}async function uE(u,f,l,r=null){let n=r===null||r===void 0||String(r).length===0?"":`&attempt=${encodeURIComponent(String(r))}`;return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/prompt?part=${encodeURIComponent(l)}${n}`))}async function fE(u,f,l=0,r=500,n=null){let i=n===null||n===void 0||String(n).length===0?"":`&attempt=${encodeURIComponent(String(n))}`;return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-steps?afterSeq=${encodeURIComponent(String(l))}&limit=${encodeURIComponent(String(r))}${i}`))}async function lE(u,f,l){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-step?seq=${encodeURIComponent(String(l))}`))}async function rE(u,f){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/read`),{method:"POST",body:{}})}async function nE(u){return Rf(xf(u,"/api/tasks/read-all"),{method:"POST",body:{}})}function iE(u){return Array.isArray(u?.output)?u.output:[]}function yE(u){return Array.isArray(u?.attempts)?u.attempts:[]}function Oc(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function _E(u){return u.split(/^\s*---+\s*$/gmu).map((f)=>f.trim()).filter(Boolean)}function bU(u){let f=Number(u);return Number.isFinite(f)?Math.max(1,Math.min(50,Math.floor(f))):1}function W1(u){let f=[];for(let l of u.split(/[\s,,;;]+/u)){let r=l.trim();if(/^codex_\d+_[A-Za-z0-9_-]+$/u.test(r)&&!f.includes(r))f.push(r)}return f}function $E(u,f){let l=W1(f);if(l.length===0)return u;return[`引用 Code Queue 任务 ${l.join(" ")}。后端会在入队时只注入这些任务的 initial prompt 和 final response 全文;中间执行过程不注入,如需补充核查可运行:${l.map((r)=>`bun scripts/cli.ts codex task ${r}`).join(";")}`,"","本次任务:",u].join(` -`)}function tE(u){let r=u.trimStart();if(!r.startsWith("# Code Queue 已解析引用上下文"))return{hasInjection:!1,reference:"",userPrompt:u};let n=u.length-r.length,i=u.lastIndexOf(` +`):[]}function K5(u){let f=String(u.status||"").trim();if(f.length>0)return f;let l=String(u.bodyPreview||"");return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(l)?.[1]||"item/fileChange"}function TT(u){let f=String(u.bodyPreview||"");return/file changes status=([A-Za-z0-9_-]+)/u.exec(f)?.[1]}function ET(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function BU(u){if(String(u.kind||"")!=="edited")return!1;let f=String(u.status||""),l=String(u.title||""),r=String(u.bodyPreview||""),n=String(u.commandPreview||"");if(l==="Edited files")return!0;if(/^item\/fileChange\//u.test(f))return!0;if((f==="item/started"||f==="item/completed")&&/file changes status=/u.test(r))return!0;if(/^Success\. Updated the following files:/mu.test(r))return!0;if(/^diff --git /mu.test(r))return!0;return/^([AMDRCU?]{1,2})\s+\S+/mu.test(r)||n.length>0&&Yt(r).length>0}function pi(u){return OU(String(u||"").replace(/^[ab]\//u,"").trim())}function z5(u){let f=/^([AMDRCU?]{1,2})\s+(.+)$/u.exec(u);if(!f)return null;let l=pi(f[2]||"");return l.length>0?{status:f[1]||"M",path:l}:null}function T5(u){let f=/^\*\*\*\s+(Add|Update|Delete)\s+File:\s+(.+)$/u.exec(u);if(f){let r=f[1]==="Add"?"A":f[1]==="Delete"?"D":"M",n=pi(f[2]||"");return n.length>0?{status:r,path:n}:null}let l=/^\*\*\*\s+Move to:\s+(.+)$/u.exec(u);if(l){let r=pi(l[1]||"");return r.length>0?{status:"R",path:r}:null}return null}function Yt(u){let f=[],l=(n,i)=>{let y=pi(i);if(y.length===0||y==="/dev/null")return;let _=f.find(($)=>$.path===y);if(_){if(_.status==="M"&&n!=="M")_.status=n;return}f.push({status:n,path:y})},r="";for(let n of HU(u)){let i=z5(n)||T5(n);if(i!==null){l(i.status,i.path),r=i.path;continue}let y=/^diff --git a\/(.+?) b\/(.+)$/u.exec(n);if(y){let j=y[2]||y[1]||"";l("M",j),r=pi(j);continue}let _=/^\+\+\+ b\/(.+)$/u.exec(n);if(_&&_[1]!=="/dev/null"){l("M",_[1]||""),r=pi(_[1]||"");continue}if(/^new file mode /u.exec(n)&&r)l("A",r);if(/^deleted file mode /u.exec(n)&&r)l("D",r);let c=/^rename to (.+)$/u.exec(n);if(c)l("R",c[1]||"")}return f}function ZT(u){if(z5(u)!==null||T5(u)!==null)return"file";if(/^(diff --git |index |--- |\+\+\+ |\*\*\* Begin Patch|\*\*\* End Patch)/u.test(u))return"meta";if(/^@@ /u.test(u))return"hunk";if(/^\+/u.test(u))return"add";if(/^-/u.test(u))return"del";if(/^(Success\.|No changes|Updated\b|Created\b|Deleted\b|Added\s+\d+\s+lines?|Wrote\s+\d+\s+lines?|Read\s+\d+\s+files?|\.\.\.\[patch content truncated)/iu.test(u))return"note";return"context"}function E5(u){return HU(u).map((f)=>{let l=z5(f)||T5(f);if(l!==null)return{text:f,kind:"file",path:l.path,status:l.status};return{text:f,kind:ZT(f)}})}function OT(u){return u.reduce((f,l)=>{if(l.kind==="add")f.added+=1;else if(l.kind==="del")f.removed+=1;return f},{added:0,removed:0})}function wU(u,f){return`${f} ${u} line${u===1?"":"s"}`}function HT(u,f){let l=[];if(u>0)l.push(wU(u,"Added"));if(f>0)l.push(wU(f,"removed"));return l.join(", ")}function BT(u){for(let l=u.length-1;l>=0;l-=1){let r=String(u[l]?.status||"").trim();if(r.length>0)return r}let f=String(u[u.length-1]?.method||"").trim();if(f==="item/fileChange/outputDelta")return"updated";if(f==="item/started")return"started";if(f==="item/completed")return"completed";return f.replace(/^item\//u,"")||"changed"}function VT(u){return`${u} file${u===1?"":"s"}`}function VU(u){let f=u.length>0?u:[],l=LU(f.map((F)=>String(F.bodyPreview||""))),n=LU(f.map((F)=>String(F.bodyPreview||"")).filter((F)=>F.trim().length>0&&!ET(F)))||l,i=Yt(n||l),y=f.map((F)=>({method:K5(F),status:TT(F),at:F.at})),_=E5(n||l),$=OT(_),A=HT($.added,$.removed),c=i.length>0?VT(i.length):"",j=A.length>0?`${A}${c?` in ${c}`:""}`:i.length>0?c:mi(n||l||"File changes",72);return{status:BT(y),summary:j,files:i,stages:y,lines:_,addedLines:$.added,removedLines:$.removed,rawText:l}}function DT(u){let f=u[0],l=u[u.length-1]||f,r=VU(u);return{...f,seq:Number.isFinite(Number(l?.seq))?Number(l?.seq):Number(f?.seq??0),at:l?.at||f?.at,title:r.files.length>0?`Edited ${r.summary}`:"Edited files",status:r.status,commandPreview:"",commandOmittedLines:void 0,bodyPreview:r.rawText,bodyOmittedLines:u.reduce((n,i)=>n+Number(i.bodyOmittedLines||0),0)||void 0,rawSeqs:u.flatMap((n)=>Array.isArray(n?.rawSeqs)?n.rawSeqs:[n?.seq]).filter((n)=>n!==void 0),editObservation:r}}function XT(u){let f=Array.isArray(u)?u:[],l=[],r=[],n=()=>{if(r.length===0)return;l.push(DT(r)),r=[]};for(let i of f){if(BU(i)){if(K5(i)==="item/started"&&r.length>0)n();if(r.push(i),K5(i)==="item/completed")n();continue}n(),l.push(i)}return n(),l}function DU(u){let f=[],l=[],r=[],n=(A,c)=>{for(let j of c)if(!A.includes(j))A.push(j)};for(let A of u){let c=String(A?.kind||""),j=[A?.commandPreview,A?.bodyPreview,A?.title].map((F)=>String(F||"")).join(` +`);if(c==="explored")n(f,WU(j));else if(c==="edited")n(l,WU(j));else if(c==="ran"){let F=String(A?.commandPreview||A?.title||"").trim();if(F.length>0&&!r.includes(F))r.push(mi(F,90))}}let i=u.map((A)=>Date.parse(String(A?.at||""))).filter((A)=>Number.isFinite(A)),y=i.length>=2?Math.max(0,Math.max(...i)-Math.min(...i)):0,_=u.reduce((A,c)=>A+(Rr(c?.durationMs)??Rr(c?.elapsedMs)??0),0),$=y>0?y:_;return{readFiles:f,editedFiles:l,runCommands:r,durationLabel:KT($)}}function YT(u,f=3){let l=Array.isArray(u)?u:[],r=[],n=[],i=Math.max(0,f),y=new Set;for(let $=l.length-1;$>=0&&i>0;$-=1){let A=l[$];if(!NU(A))continue;y.add(A),i-=1}let _=()=>{if(n.length>=2){let $=EU(n);r.push({seq:Number(n[0]?.seq??0),at:n[0]?.at||n.at(-1)?.at,kind:"toolGroup",title:ZU(n),status:`${n.length} calls`,items:n,counts:$,digest:DU(n),rawSeqs:n.flatMap((A)=>Array.isArray(A?.rawSeqs)?A.rawSeqs:[A?.seq]).filter((A)=>A!==void 0)})}else r.push(...n);n=[]};for(let $ of l){if(NU($)&&!y.has($)){n.push($);continue}_(),r.push($)}return _(),r}function XU(u){return(Array.isArray(u)?u:[]).map((f,l)=>({...f,seq:Number.isFinite(Number(f?.seq))?Number(f.seq):l+1,kind:String(f?.kind||"message"),at:f?.at===void 0?void 0:String(f.at),durationMs:Rr(f?.durationMs)??void 0,title:f?.title===void 0?void 0:String(f.title),status:f?.status===void 0?void 0:String(f.status)}))}function V_(u){let f=Rr(u?.state?.time?.start)??Rr(u?.time?.start),l=Rr(u?.state?.time?.end)??Rr(u?.time?.end);return Rr(u?.durationMs)??Rr(u?.elapsedMs)??Rr(u?.timing?.durationMs)??Rr(u?.metadata?.durationMs)??(f!==null&&l!==null&&l>=f?l-f:null)??void 0}function D_(u,f){return u?.createdAt||u?.updatedAt||u?.completedAt||f||void 0}function W5(u,f){return u?.id||u?.messageId||f}function ST(u,f=1200){if(typeof u==="string")return u;if(u===void 0||u===null)return"";try{return mi(JSON.stringify(u),f)}catch{return mi(String(u),f)}}function YU(u,f,l){if(typeof u?.metadata?.diff==="string"&&u.metadata.diff.length>0)return u.metadata.diff;if(typeof u?.metadata?.filediff?.patch==="string"&&u.metadata.filediff.patch.length>0)return u.metadata.filediff.patch;if(typeof u?.output==="string"&&u.output.length>0)return u.output;if(typeof u?.result==="string"&&u.result.length>0)return u.result;if(typeof f?.output==="string"&&f.output.length>0)return f.output;if(typeof l?.output==="string"&&l.output.length>0)return l.output;if(typeof u?.metadata?.output==="string"&&u.metadata.output.length>0)return u.metadata.output;return""}function Xt(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return"";for(let l of f){let r=u[l];if(typeof r==="string"&&r.length>0)return r;if(r!==void 0&&r!==null&&typeof r!=="object")return String(r)}return""}function KU(u,f){if(!u||typeof u!=="object"||Array.isArray(u))return null;for(let l of f){let r=Number(u[l]);if(Number.isFinite(r))return r}return null}function SU(u,f){let l=f?.input&&typeof f.input==="object"&&!Array.isArray(f.input)?f.input:u?.input&&typeof u.input==="object"&&!Array.isArray(u.input)?u.input:{},r=Xt(l,["command","cmd","script"]);if(r.length>0)return r;if(typeof u?.command==="string"&&u.command.length>0)return u.command;if(typeof f?.command==="string"&&f.command.length>0)return f.command;let n=String(u?.tool||u?.title||"tool"),i=Xt(l,["filePath","filepath","path"])||Xt(u,["filePath","filepath","path"]),y=Xt(l,["pattern","query"]),_=KU(l,["offset"]),$=KU(l,["limit"]),A=[n];if(y.length>0)A.push(y);if(i.length>0)A.push(i);if(_!==null)A.push(`offset=${_}`);if($!==null)A.push(`limit=${$}`);return A.length>1?A.join(" "):n}function pT(u,f){let l=u?.part&&typeof u.part==="object"&&!Array.isArray(u.part)?u.part:{},r=String(u?.type||u?.event||u?.name||l?.type||"").toLowerCase(),n=String(l?.type||"").toLowerCase(),i=u?.at||u?.timestamp||l?.updatedAt||l?.createdAt,y=Number.isFinite(Number(u?.seq))?Number(u.seq):f;if(r==="step_start"||r==="step-start"||n==="step-start")return null;if(r==="step_finish"||r==="step-finish"||n==="step-finish")return null;if(n==="tool"||/tool|bash|command/iu.test(`${r} ${n}`)){let $=l?.state&&typeof l.state==="object"&&!Array.isArray(l.state)?l.state:{},A=SU(l,$),c=YU($,l,u),j=pU(A,String(l?.tool||l?.title||"")),F=j==="edited"?{status:String($?.status||l?.status||u?.status||""),summary:mi(c||A,72),files:Yt(c),stages:[],lines:E5(c),addedLines:0,removedLines:0,rawText:c}:void 0;return{seq:y,at:D_(l,i),kind:j,title:String($?.title||l?.title||$?.metadata?.description||l?.tool||"OpenCode tool"),status:String($?.status||l?.status||u?.status||""),commandPreview:A,bodyPreview:c,durationMs:V_(l),rawSeqs:[l?.id||l?.callID||u?.sessionID||y],editObservation:F}}let _=ST(l?.text??l?.content??l?.delta??u?.text??u?.content??u?.delta,3000).trim();if(_.length>0)return{seq:y,at:D_(l,i),kind:n==="reasoning"?"message":/error|failed/iu.test(`${r} ${n}`)?"error":"message",title:n==="reasoning"?"Reasoning":/error|failed/iu.test(`${r} ${n}`)?"OpenCode error":"Assistant message",status:`opencode/${r||n||"event"}`,bodyPreview:_,durationMs:V_(l),rawSeqs:[l?.id||u?.sessionID||y]};return null}function pU(u,f){let l=`${f} ${u}`.toLowerCase();if(/\b(read|grep|glob|list|ls|find|search|view|cat|sed|rg|head|tail|wc|file)\b/iu.test(l))return"explored";if(/\b(edit|write|patch|apply|update|create|delete|apply_patch|git apply|cat >|tee .*<<|sed -i|python3? .*write_text|mkdir|rm |touch )\b/iu.test(l))return"edited";return"ran"}function mT(u){let f=[],l=1;for(let r of Array.isArray(u)?u:[]){if(r?.kind&&r?.title){let _=String(r?.status||"");if(_==="opencode/step-start"||_==="opencode/step-finish")continue;f.push({...r,seq:Number.isFinite(Number(r?.seq))?Number(r.seq):l++});continue}let n=r?.createdAt||r?.updatedAt||r?.completedAt,i=String(r?.role||"assistant").toLowerCase(),y=Array.isArray(r?.parts)?r.parts:[];if(y.length===0){if(r?.part&&(r?.sessionID||String(r?.type||"").startsWith("step_")||String(r?.type||"").includes("tool"))){let _=pT(r,l);if(_!==null)f.push(_),l=Math.max(l+1,Number(_.seq)+1)}else if(r?.textPreview)f.push({seq:l++,at:n,kind:"message",title:`${i||"assistant"} message`,status:i,bodyPreview:String(r.textPreview),rawSeqs:[r?.messageId||l]});continue}for(let _ of y){let $=String(_?.type||"").toLowerCase();if($==="step-start"||$==="step-finish")continue;if($==="text"||$==="reasoning"){let c=String(_?.textPreview||r?.textPreview||"").trim();if(c.length===0)continue;f.push({seq:l++,at:D_(_,n),kind:"message",title:$==="reasoning"?"Reasoning":i==="user"?"User message":i==="system"?"System message":"Assistant message",status:$==="reasoning"?"reasoning":i,bodyPreview:c,durationMs:V_(_),rawSeqs:[W5(_,l)]});continue}if($==="tool"){let c=_?.state&&typeof _.state==="object"&&!Array.isArray(_.state)?_.state:{},j=SU(_,c),F=YU(c,_,{}),U=pU(j,String(_?.tool||_?.title||"")),Q=U==="edited"?{status:String(c?.status||_?.status||""),summary:mi(F||j,72),files:Yt(F),stages:[],lines:E5(F),addedLines:0,removedLines:0,rawText:F}:void 0;f.push({seq:l++,at:D_(_,n),kind:U,title:String(_?.title||_?.tool||"tool"),status:String(_?.status||""),commandPreview:j,bodyPreview:F,durationMs:V_(_),rawSeqs:[W5(_,l)],editObservation:Q});continue}let A=String(_?.textPreview||_?.title||$||"").trim();if(A)f.push({seq:l++,at:D_(_,n),kind:"system",title:$||"part",bodyPreview:A,status:String(_?.status||""),durationMs:V_(_),rawSeqs:[W5(_,l)]})}}return f}var mU={source:"opencode",toTrace:mT};function PT(u){return String(u||"unknown").toLowerCase().replace(/[^a-z0-9_-]+/gu,"-")||"unknown"}function GU(u){let f=String(u||"M").toUpperCase();if(f.startsWith("A")||f==="??")return"added";if(f.startsWith("D"))return"deleted";if(f.startsWith("R"))return"renamed";return"modified"}function MT(u){if(u==="item/fileChange/outputDelta")return"delta";return u.replace(/^item\//u,"")}function CT(u,f){if(u.kind==="file"){let n=String(u.status||"M");return Su("div",{key:`${f}-${u.text}`,className:`codex-edit-diff-line file ${GU(n)}`},Su("span",{className:`codex-edit-file-status ${GU(n)}`},n),Su("code",null,u.path||u.text.replace(/^([AMDRCU?]{1,2})\s+/u,"")))}let l=u.kind==="add"||u.kind==="del"?u.text.slice(0,1):u.kind==="hunk"?"@@":u.kind==="note"?"ok":"",r=u.kind==="add"||u.kind==="del"?u.text.slice(1):u.text;return Su("div",{key:`${f}-${u.text}`,className:`codex-edit-diff-line ${u.kind}`},Su("span",{className:"codex-edit-diff-sign"},l),Su("code",null,r||" "))}function RT(u,f){let l=u.lines.length>0?u.lines:u.files.map((n)=>({text:`${n.status} ${n.path}`,kind:"file",path:n.path,status:n.status})),r=Number(u.addedLines||0)+Number(u.removedLines||0)>0;return Su("div",{className:"codex-edit-observation","data-testid":"codex-edit-observation"},Su("div",{className:"codex-edit-observation-head"},Su("span",{className:"codex-edit-window-controls","aria-hidden":"true"},Su("i",null),Su("i",null),Su("i",null)),Su("strong",null,r?"git diff":"git diff --stat"),Su("code",null,u.summary||"File changes")),u.stages.length>0?Su("div",{className:"codex-edit-stage-strip"},u.stages.map((n,i)=>Su("span",{key:`${n.method}-${i}`,className:`codex-edit-stage ${PT(n.status||n.method)}`},Su("b",null,MT(n.method)),n.status?Su("em",null,n.status):null))):null,l.length>0?Su("div",{className:"codex-edit-diff",role:"list"},l.map(CT)):null,f?Su("div",{className:"codex-edit-omitted"},`${f} (查看原始JSON获取完整记录)`):null)}function zU(u,f,l){let r=w5(l);return Su("div",{className:`codex-transcript-stream ${u}`,"data-testid":`codex-trace-${u}`},Su("span",{className:"codex-transcript-stream-label"},u),Su("pre",{className:"codex-transcript-body"},f,r?` +${r} (查看原始JSON获取完整记录)`:""))}function PU(u,f=!1){let l=String(u.kind||"message"),r=["ran","explored","edited"].includes(l),n=w5(u.commandOmittedLines),i=w5(u.bodyOmittedLines),y=String(u.commandPreview||(r?u.title||"":"")),_=String(u.stdoutPreview||""),$=String(u.stderrPreview||""),A=_.length>0||$.length>0,c=Boolean(u.foldedReferencePrompt)&&String(u.fullPrompt||"").length>0,j=l==="edited"&&(u.editObservation!==void 0||BU(u))?u.editObservation||VU([u]):null;return Su("article",{key:`${u.seq}-${l}`,className:`codex-transcript-item ${l} ${f?"nested":""}`},Su("div",{className:"codex-transcript-main"},Su("div",{className:"codex-transcript-title"},Su("span",{className:"codex-output-channel"},L5(l)),r&&j===null?null:Su("strong",null,j!==null?"File changes":String(u.title||L5(l))),u.status?Su("code",null,String(j?.status||u.status)):null,Su("time",null,Nu(u.at))),y&&j===null?Su("pre",{className:"codex-transcript-command"},y,n?` +${n}`:""):null,j!==null?RT(j,i):A?Su("div",{className:"codex-transcript-streams"},_.length>0?zU("stdout",_,u.stdoutOmittedLines):null,$.length>0?zU("stderr",$,u.stderrOmittedLines):null):u.bodyPreview?Su("pre",{className:"codex-transcript-body"},String(u.bodyPreview),i?` +${i} (查看原始JSON获取完整记录)`:""):null,c?Su("details",{className:"codex-initial-prompt-full","data-testid":"codex-initial-prompt-full"},Su("summary",null,Su("span",null,"引用注入已折叠,点击查看最终传入 Codex 的完整 prompt"),Su("code",null,`${u.fullPromptLines||GT(String(u.fullPrompt||""))} lines / ${u.fullPromptChars||String(u.fullPrompt||"").length} chars`)),Su("pre",{className:"codex-transcript-body codex-transcript-full-prompt","data-testid":"codex-initial-prompt-full-text"},String(u.fullPrompt||""))):null))}function xT(u){let f=Array.isArray(u.items)?u.items:[],l=u.digest&&typeof u.digest==="object"?u.digest:DU(f);return Su("article",{key:`${u.seq}-toolGroup`,className:"codex-transcript-item toolGroup"},Su("div",{className:"codex-transcript-main"},Su("details",{className:"codex-tool-group","data-testid":"codex-tool-group"},Su("summary",null,Su("div",{className:"codex-tool-group-head"},Su("span",{className:"codex-output-channel"},L5("toolGroup")),Su("strong",null,String(u.title||ZU(f))),Su("code",null,String(u.status||`${f.length} calls`)),Su("time",null,Nu(u.at)))),Su("div",{className:"codex-tool-group-digest"},Su("span",null,`read: ${N5(Array.isArray(l.readFiles)?l.readFiles:[])}`),Su("span",null,`edit: ${N5(Array.isArray(l.editedFiles)?l.editedFiles:[])}`),Su("span",null,`run: ${N5(Array.isArray(l.runCommands)?l.runCommands:[],2)}`),Su("span",null,`duration: ${l.durationLabel||"--"}`)),Su("div",{className:"codex-tool-group-items"},f.map((r)=>PU(r,!0))))))}function hT(u){let f=[u.title,u.status,u.bodyPreview,u.commandPreview,u.stderrPreview,u.stdoutPreview].map((l)=>String(l||"")).join(` +`);return/\b(error|failed|failure|interrupt|interrupted|cancell?ed|watchdog|timeout|closed|refused|aborted|exception)\b/iu.test(f)}function MU(u,f){if(f)return u;return u.flatMap((l)=>{if(String(l.kind||"")==="system"&&!hT(l))return[];if(String(l.kind||"")!=="toolGroup"||!Array.isArray(l.items))return[l];let r=MU(l.items,f);return[{...l,items:r}]})}var bT=16;function TU(u){return u.scrollHeight-u.scrollTop-u.clientHeight<=bT}function St({items:u,input:f,port:l,autoScroll:r=!1,loading:n=!1,hasDetail:i=!0,emptyText:y="等待 Trace 输出...",loadingText:_="正在加载完整 Trace...",testId:$="trace-output",className:A="codex-transcript",keepRecentToolCalls:c=3,collapseTools:j=!0,showSystemEvents:F=!1}){let U=qU(null),Q=qU(!0),L=MU(XT(l?wT(l,f):XU(u)),Boolean(F)),w=j?YT(L,c):L,J=zT(L);LT(()=>{let W=U.current;if(!r||!W)return;if(!Q.current&&!TU(W))return;W.scrollTop=W.scrollHeight,Q.current=!0},[r,L.length,J]);let q={className:A,ref:U,onScroll:(W)=>{let z=W.currentTarget;Q.current=TU(z)},"data-testid":$};if(n&&!i)return Su("div",q,Su("div",{className:"codex-output-empty"},_));return Su("div",q,w.length===0?Su("div",{className:"codex-output-empty"},y):w.map((W)=>String(W.kind||"")==="toolGroup"?xT(W):PU(W)))}var CU=Pu(qf(),1),Q1=CU.default.createElement;function pt(...u){return u.filter(Boolean).join(" ")}function RU({title:u,children:f,actions:l,onClose:r,className:n,backdropClassName:i,bodyClassName:y,actionsClassName:_,titleId:$,testId:A,closeTestId:c,closeLabel:j="关闭",disableClose:F=!1,closeOnBackdrop:U=!0}){let Q={className:pt("raw-dialog","unidesk-dialog",n),role:"dialog","aria-modal":"true"};if($)Q["aria-labelledby"]=$;else if(typeof u==="string")Q["aria-label"]=u;if(A)Q["data-testid"]=A;return Q1("div",{className:pt("modal-backdrop","unidesk-dialog-backdrop",i),role:"presentation",onClick:(L)=>{if(U&&!F&&L.target===L.currentTarget)r()}},Q1("section",Q,Q1("div",{className:"raw-dialog-head unidesk-dialog-head"},Q1("strong",$?{id:$}:null,u),Q1("button",{type:"button",className:"ghost-btn",onClick:r,disabled:F,"data-testid":c},j)),Q1("div",{className:pt("unidesk-dialog-body",y)},f),l?Q1("div",{className:pt("unidesk-dialog-actions",_)},l):null))}var K=P_.default.createElement,{useEffect:wn,useMemo:xU,useRef:Xf}=P_.default,bu=P_.default.useState,vT=120,rQ=24,nQ=48,kT=1200;function Z5(){return typeof document>"u"||document.visibilityState!=="hidden"}function cl(u,f="操作失败"){return Hu(u,f)}function hr(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.floor(f/1000),r=Math.floor(l/3600),n=Math.floor(l%3600/60),i=l%60;if(r>0)return`${r}h ${String(n).padStart(2,"0")}m`;if(n>0)return`${n}m ${String(i).padStart(2,"0")}s`;return`${i}s`}function X0(u){if(u===null||u===void 0||u==="")return null;let f=u instanceof Date?u.getTime():new Date(u).getTime();return Number.isFinite(f)?f:null}function iQ(u,f=Date.now()){let l=X0(u);if(l===null)return"--";let r=Math.max(0,Math.floor((f-l)/1000));if(r<1)return"刚刚";let n=Math.floor(r/86400),i=Math.floor(r%86400/3600),y=Math.floor(r%3600/60),_=r%60;if(n>0)return`${n}天${i>0?`${i}小时`:""}前`;if(i>0)return`${i}小时${y>0?`${y}分钟`:""}前`;if(y>0)return`${y}分钟${_}秒前`;return`${_}秒前`}function yQ(...u){let f="",l=-1/0;for(let r of u){let n=String(r||"");if(n.length===0)continue;let i=X0(r);if(i!==null&&i>=l)f=n,l=i;else if(f.length===0)f=n}return f}function IT(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";if(f<1000)return`${Math.round(f)}ms`;return`${(f/1000).toFixed(f<1e4?2:1)}s`}function Y5(u,f=180){let l=String(u||"").replace(/\s+/gu," ").trim();return l.length>f?`${l.slice(0,f-1)}…`:l}async function Rf(u,f={}){return Eu(u,{strictJson:!0,retryInvalidJson:1,invalidJsonPrefix:"Code Queue 返回了无效 JSON",invalidJsonPreview:!0,responsePreviewLength:kT,...f})}function L1({status:u,children:f,title:l}){let r=String(u||"unknown").toLowerCase();return K("span",{className:`status-badge ${r}`,title:l},f||u||"unknown")}function Mi({title:u,eyebrow:f,summary:l,actions:r,children:n,className:i,loading:y}){return K("section",{className:`panel ${i||""}`},K("div",{className:"panel-head"},K("div",null,f?K("p",{className:"panel-eyebrow"},f):null,K(nf,{title:u,loading:y}),l?K("div",{className:"panel-summary"},l):null),r?K("div",{className:"panel-actions"},r):null),K("div",{className:"panel-body"},n))}function _Q({title:u,data:f,onOpen:l,testId:r}){return K("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function w1({title:u,text:f}){return K("div",{className:"empty-state"},K("strong",null,u),K("span",null,f))}function gT(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function sT(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function xf(u,f){return`${u}/code-queue-direct${f}`}function aT(u){return`${u}/microservices/oa-event-flow/proxy/api/events/stream?tags=${encodeURIComponent("service:code-queue")}`}function x5(){return{headers:{"cache-control":"no-cache","x-unidesk-no-cache":"1"}}}function jl(u){return Array.isArray(u?.tasks)?u.tasks:[]}function Ln(u){return u?.pagination&&typeof u.pagination==="object"&&!Array.isArray(u.pagination)?u.pagination:{}}function hU(u){let f=Date.parse(String(u?.updatedAt||u?.createdAt||""));return Number.isFinite(f)?f:0}function bU(u){return X0(u?.queueEnteredAt)??X0(u?.createdAt)??X0(u?.updatedAt)??0}function oT(u,f){let l=bU(u)-bU(f);if(l!==0)return l;let r=(X0(u?.createdAt)??0)-(X0(f?.createdAt)??0);if(r!==0)return r;return String(u?.id||"").localeCompare(String(f?.id||""))}function dT(u,f=""){let l=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length>0&&!l.has(i))l.set(i,n)}return Array.from(l.values()).sort((r,n)=>{let i=eU(r)-eU(n);if(i!==0)return i;let y=String(r?.id||"")===f?0:1,_=String(n?.id||"")===f?0:1;if(y!==_)return y-_;return hU(n)-hU(r)})}function Pi(u,f=""){let l=new Map;for(let r of u)for(let n of r){let i=String(n?.id||"");if(i.length===0)continue;l.set(i,{...l.get(i)||{},...n})}return dT([Array.from(l.values())],f)}function Y_(u){return Array.isArray(u?.activeTaskIds)?u.activeTaskIds.map((f)=>String(f||"")).filter(Boolean):[String(u?.activeTaskId||"")].filter(Boolean)}var Gn="__all__",eT="(max-width: 760px)",uE="(min-width: 761px)";function bl(u){return!u||u===Gn}function fE(){return typeof window<"u"&&window.matchMedia(eT).matches}function lE(u){return bl(u)?"":`&queueId=${encodeURIComponent(u)}`}function S5(u){return String(u||"").trim().replace(/\s+/gu," ").slice(0,200)}function rE(u){let f=S5(u);return f.length===0?"":`&search=${encodeURIComponent(f)}`}function h5(u,f=""){return`${lE(u)}${rE(f)}`}function mt(u,f){return Number(u?.counts?.[f]||0)}function vU(u,f=""){let l=new Map;for(let n of Array.isArray(u?.queues)?u.queues:[]){let i=String(n?.id||"").trim();if(i.length>0)l.set(i,{...n,name:String(n?.name||i).trim()||i})}for(let n of[String(u?.defaultQueueId||"default"),f].map((i)=>i.trim()).filter(Boolean))if(!l.has(n))l.set(n,{id:n,name:n,total:0,counts:{},activeTaskId:null,runnableTaskId:null,processing:!1});return Array.from(l.values()).sort((n,i)=>{let y=String(n?.id||"")===String(u?.defaultQueueId||"default")?0:1,_=String(i?.id||"")===String(u?.defaultQueueId||"default")?0:1;if(y!==_)return y-_;return String(n?.id||"").localeCompare(String(i?.id||""))})}function $Q(u){let f=String(u?.id||"default"),l=String(u?.name||"").trim();return l.length>0?l:f}function p5(u){let f=String(u?.id||"default"),l=$Q(u);return l===f?f:`${l} (${f})`}function S_(u){let f=mt(u,"running")+mt(u,"judging"),l=mt(u,"queued")+mt(u,"retry_wait"),r=Number(u?.total||0),n=[p5(u),`${r} tasks`];if(f>0)n.push(`${f} running`);if(l>0)n.push(`${l} queued`);return n.join(" · ")}function Ri(u,f){if(bl(f))return null;return u.find((l)=>String(l?.id||"")===f)||null}function kU(u,f,l,r){if(bl(l)){let i=Y_(u);return String(u?.activeTaskId||i[0]||r.find((y)=>oU(y))?.id||"")}let n=Ri(f,l);return String(n?.activeTaskId||r.find((i)=>oU(i))?.id||"")}function nE(u,f,l){if(!bl(f)){let r=Ri(u,f);return String(r?.runnableTaskId||l.find((n)=>String(n?.status||"")==="queued"||String(n?.status||"")==="retry_wait")?.id||"")}return String(l.find((r)=>String(r?.status||"")==="queued"||String(r?.status||"")==="retry_wait")?.id||"")}async function iE(u,f=Gn,l=""){return Rf(xf(u,`/api/tasks/overview?limit=${rQ}&transcriptLimit=1&compact=1&selected=0${h5(f,l)}`),x5())}async function yE(u,f,l=0,r=Gn,n=""){return Rf(xf(u,`/api/tasks/overview?limit=${rQ}&transcriptLimit=3&compact=1&afterSeq=${encodeURIComponent(String(Math.max(0,l)))}&preferId=${encodeURIComponent(f)}${h5(r,n)}`),x5())}async function IU(u,f,l,r=nQ,n=""){return Rf(xf(u,`/api/tasks/overview?limit=${encodeURIComponent(String(r))}&transcriptLimit=1&compact=1&selected=0&includeActive=0&stats=0&beforeId=${encodeURIComponent(l)}${h5(f,n)}`),x5())}async function _E(u,f){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-summary`))}async function $E(u,f,l,r=null){let n=r===null||r===void 0||String(r).length===0?"":`&attempt=${encodeURIComponent(String(r))}`;return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/prompt?part=${encodeURIComponent(l)}${n}`))}async function tE(u,f,l=0,r=500,n=null){let i=n===null||n===void 0||String(n).length===0?"":`&attempt=${encodeURIComponent(String(n))}`;return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-steps?afterSeq=${encodeURIComponent(String(l))}&limit=${encodeURIComponent(String(r))}${i}`))}async function AE(u,f,l){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/trace-step?seq=${encodeURIComponent(String(l))}`))}async function cE(u,f){return Rf(xf(u,`/api/tasks/${encodeURIComponent(f)}/read`),{method:"POST",body:{}})}async function jE(u){return Rf(xf(u,"/api/tasks/read-all"),{method:"POST",body:{}})}function FE(u){return Array.isArray(u?.output)?u.output:[]}function JE(u){return Array.isArray(u?.attempts)?u.attempts:[]}function O5(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function UE(u){return u.split(/^\s*---+\s*$/gmu).map((f)=>f.trim()).filter(Boolean)}function gU(u){let f=Number(u);return Number.isFinite(f)?Math.max(1,Math.min(50,Math.floor(f))):1}function q1(u){let f=[];for(let l of u.split(/[\s,,;;]+/u)){let r=l.trim();if(/^codex_\d+_[A-Za-z0-9_-]+$/u.test(r)&&!f.includes(r))f.push(r)}return f}function QE(u,f){let l=q1(f);if(l.length===0)return u;return[`引用 Code Queue 任务 ${l.join(" ")}。后端会在入队时只注入这些任务的 initial prompt 和 final response 全文;中间执行过程不注入,如需补充核查可运行:${l.map((r)=>`bun scripts/cli.ts codex task ${r}`).join(";")}`,"","本次任务:",u].join(` +`)}function qE(u){let r=u.trimStart();if(!r.startsWith("# Code Queue 已解析引用上下文"))return{hasInjection:!1,reference:"",userPrompt:u};let n=u.length-r.length,i=u.lastIndexOf(` # 本次任务 -`);if(i0?u.split(/\r\n|\r|\n/u).length:0}function iQ(u){let f=String(u?.displayPrompt||"");if(f.length>0)return f;let l=String(u?.prompt||"");return cE(tE(l).userPrompt)}function _r(u){return u?._traceSummary&&typeof u._traceSummary==="object"&&!Array.isArray(u._traceSummary)?u._traceSummary:null}function x3(u){return u?._promptDetails&&typeof u._promptDetails==="object"&&!Array.isArray(u._promptDetails)?u._promptDetails:{}}function hc(u){let f=_r(u)?.prompt;return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function yQ(u){let f=_r(u)?.execution;return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function vU(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):0}function D0(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):null}function _Q(u){let f=Hf(u?.traceStats);if(f&&(u?.statsSource==="oa-event-flow"||f.source==="oa-event-flow"))return f;let l=_r(u),r=Hf(l?.traceStats);if(r&&(l?.statsSource==="oa-event-flow"||r.source==="oa-event-flow"))return r;return null}function AE(u,f){let l=Hf(f?.traceStats)||Hf(f?.execution?.traceStats),r=String(f?.statsSource||f?.execution?.statsSource||"");if(l&&(r==="oa-event-flow"||l.source==="oa-event-flow"))return l;return null}function jE(u,f){return D0(_Q(u)?.[f])}function $Q(u){let f=jE(u,"stepCount");if(f!==null)return f;let l=_r(u);if(l!==null)return FE(l);return null}function FE(u){let f=Hf(u?.traceStats);if(!f||u?.statsSource!=="oa-event-flow"&&f.source!=="oa-event-flow")return null;return D0(f.stepCount)}function p3(u){if(!u||u?._traceSummaryLoaded!==!0)return!1;let f=_r(u),l=String(u?._traceSummaryUpdatedAt||f?.updatedAt||""),r=String(u?.updatedAt||"");if(r.length>0){let n=X0(l),i=X0(r);if(n!==null&&i!==null){if(n+10?l:iQ(u)}function tQ(u){let f=_r(u);return String(f?.finalResponse||u?.finalResponse||"").trimEnd()}function cQ(u){let l=_r(u)?.lastJudge||u?.lastJudge;return l&&typeof l==="object"&&!Array.isArray(l)?l:null}function Hf(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function JE(u){let f=_r(u)?.attempts;if(Array.isArray(f)&&f.length>0)return f;let l=yQ(u),r=tQ(u),n=cQ(u);if(Object.keys(l).length===0&&r.length===0&&n===null)return[];return[{index:Number(u?.currentAttempt||1),mode:u?.currentMode||"initial",startedAt:u?.startedAt,finishedAt:u?.finishedAt,terminalStatus:u?.status,execution:l,finalResponse:r,finalResponseChars:r.length,judge:n}]}function UE(u,f){return Hf(f?.execution)||yQ(u)}function QE(u,f,l,r){let n=_r(u),i=Number(n?.currentAttempt||u?.currentAttempt||0),y=Number(l),_=Number.isFinite(y)&&y>0&&y===i,$=lQ(u?.updatedAt,n?.updatedAt);if(_&&!f?.finishedAt&&$.length>0)return $;return String(f?.updatedAt||f?.finishedAt||r.effectiveEndAt||(_?$:"")||$||u?.finishedAt||u?.startedAt||"")}function qE(u,f){let l=String(f?.finalResponse||f?.finalResponsePreview||"");if(Object.prototype.hasOwnProperty.call(f||{},"finalResponse")||Object.prototype.hasOwnProperty.call(f||{},"finalResponsePreview"))return l.trimEnd();return l.length>0?l.trimEnd():tQ(u)}function AQ(u,f){if(Object.prototype.hasOwnProperty.call(f||{},"judge"))return Hf(f?.judge);return cQ(u)}function NE(u,f,l){if(!YE(u))return!1;if(bc(f,l))return!1;if(f?.finishedAt)return!1;if(["succeeded","failed","canceled"].includes(String(f?.terminalStatus||"")))return!1;let r=_r(u),n=Number(r?.currentAttempt||u?.currentAttempt||0),i=Number(l);if(Number.isFinite(i)&&i>0&&Number.isFinite(n)&&n>0)return i===n;return!0}function jQ(u){return`feedback:${String(u||"latest")}`}function WE(u,f,l){let r=String(f?.feedbackPrompt||"").trimEnd(),n=String(f?.feedbackPromptPreview||r||"").trimEnd(),i=Number(f?.feedbackPromptChars||r.length||n.length||0),y=Number(f?.feedbackPromptLines||L1(r||n));if(r.length>0||n.length>0||i>0)return{text:r,preview:n,chars:i,lines:y,source:f?.feedbackPromptSource||"judge-feedback",forAttempt:f?.feedbackPromptForAttempt||Number(l||0)+1,truncated:Boolean(f?.feedbackPromptTruncated)};let _=AQ(u,f),$=String(_?.continuePrompt||"").trimEnd();if(_?.decision==="retry"&&$.length>0)return{text:"",preview:$,chars:$.length,lines:L1($),source:"judge-continue-prompt",forAttempt:Number(l||0)+1,truncated:!1};return null}function wE(u){let f=hc(u);return Boolean(f.hasReferenceInjection||Number(f.referencePromptChars||0)>0||u?.referenceInjection||u?.referenceInjectionSummary)}function FQ(u,f=null){if(f!==null&&f!==void 0){let r=(Hf(u?._traceStepsByAttempt)||{})[String(f)];return Array.isArray(r)?r:[]}return Array.isArray(u?._traceSteps)?u._traceSteps:[]}function mc(u){let l=[u?.seq,...Array.isArray(u?.rawSeqs)?u.rawSeqs:[]].map((r)=>Number(r)).filter((r)=>Number.isFinite(r));return l.length>0?Math.max(...l):0}function LE(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,mc(l)),0)}function KE(u,f){let l=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(f)?f:[]]){let n=String(r?.seq??`${r?.title||"step"}:${r?.at||""}`);l.set(n,{...l.get(n)||{},...r})}return Array.from(l.values()).sort((r,n)=>mc(r)-mc(n))}function xi(u){return(Array.isArray(u?.summaryLines)?u.summaryLines:[]).map((f)=>String(f||""))}function GE(u){let f=String(u?.kind||"").trim().toLowerCase(),l=String(u?.status||"").trim().toLowerCase();return f==="error"||l==="error"}function h3(u){let f=String(u?.status||"").trim();if(f.length>0)return f;let l=xi(u).join(` -`);return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(l)?.[1]||""}function kU(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function zE(u){let f=xi(u);for(let r=f.length-1;r>=0;r-=1){let n=/file changes status=([A-Za-z0-9_-]+)/u.exec(f[r]||"")?.[1];if(n)return n}let l=h3(u);if(l==="item/fileChange/outputDelta")return"updated";if(l==="item/started")return"started";if(l==="item/completed")return"completed";return l.replace(/^item\//u,"")||String(u?.status||"changed")}function TE(u){if(String(u?.kind||"")!=="edited")return!1;let f=String(u?.title||""),l=String(u?.status||""),r=xi(u).join(` -`);if(f==="Edited files")return!0;if(/^item\/fileChange\//u.test(l))return!0;if((l==="item/started"||l==="item/completed")&&/file changes status=/u.test(r))return!0;if(/^Success\. Updated the following files:/mu.test(r))return!0;if(/^diff --git /mu.test(r))return!0;return/^([AMDRCU?]{1,2})\s+\S+/mu.test(r)}function EE(u){if(u.length<=1)return u[0];let f=u.find((i)=>h3(i)==="item/fileChange/outputDelta")||u.find((i)=>xi(i).some((y)=>!kU(y)))||u.at(-1)||u[0],l=u.flatMap((i)=>Array.isArray(i?.rawSeqs)?i.rawSeqs:[i?.seq]).filter((i)=>i!==void 0),r=u.flatMap(xi).filter((i)=>i.trim().length>0&&!kU(i)),n=u[u.length-1]||f;return{...f,at:f?.at||n?.at,title:String(f?.title||"Edited files"),status:zE(n),summaryLines:r.length>0?r:xi(f),rawSeqs:l}}function ZE(u){let f=Array.isArray(u)?u:[],l=[],r=[],n=()=>{if(r.length>0)l.push(EE(r));r=[]};for(let i of f){if(TE(i)){if(h3(i)==="item/started"&&r.length>0)n();if(r.push(i),h3(i)==="item/completed")n();continue}n(),l.push(i)}return n(),l}function OE(u){return{...u}}function pc(u,f=null){if(f!==null&&f!==void 0){let l=Hf(u?._traceStepsLoadedByAttempt)||{};return Boolean(l[String(f)])}return Boolean(u?._traceStepsLoaded)}function Pc(u){return u?._traceStepDetails&&typeof u._traceStepDetails==="object"&&!Array.isArray(u._traceStepDetails)?u._traceStepDetails:{}}function HE(u,f){let l=Number(u?.index);return Number.isFinite(l)?l:f+1}function bc(u,f){return Boolean(u?.synthetic)||Number(f)<=0}function b3(u){let f=Number(u);return Number.isFinite(f)?String(f):void 0}function BE(u){let f=u?.timing&&typeof u.timing==="object"?u.timing:{},l=String(u?.status||"");if(["queued"].includes(l))return`等待 ${Rr(f.queueWaitMs??f.totalElapsedMs)}`;if(["running","judging","retry_wait"].includes(l))return`耗时 ${Rr(f.durationMs??f.totalElapsedMs)}`;return`耗时 ${Rr(f.durationMs??f.totalElapsedMs)}`}function m_(u){return String(u?.queueId||"default")}function JQ(u){return Hf(u?.queuedReason)}function UQ(u){let f=String(u?.queuedReasonLabel||"").trim();if(f.length>0)return f.toUpperCase();let l=JQ(u),r=String(l?.label||"").trim();return r.length>0?r.toUpperCase():""}function VE(u){let f=String(u?.status||"unknown");if(f!=="queued")return f;let l=UQ(u);return l.length>0?`QUEUED(${l})`:"QUEUED"}function DE(u){if(String(u?.status||"")!=="queued")return;let f=JQ(u),l=String(f?.message||"").trim(),r=UQ(u);if(l.length>0&&r.length>0)return`${r}: ${l}`;if(l.length>0)return l;return r.length>0?r:void 0}function XE(u){return{system:"SYS",user:"YOU",assistant:"GPT",reasoning:"THINK",command:"CMD",diff:"DIFF",tool:"TOOL",error:"ERR"}[u]||u.toUpperCase()}function IU(u){return["running","judging","retry_wait"].includes(String(u?.status||""))}function YE(u){return String(u?.status||"")==="running"}function Cr(u){return["succeeded","failed","canceled"].includes(String(u?.status||""))}function QQ(u){if(u?.promptEditable===!0)return!0;if(u?.promptEditable===!1)return!1;return String(u?.status||"")==="queued"&&!u?.startedAt&&Number(u?.currentAttempt||0)===0&&!u?.codexThreadId&&!u?.nextMode}function V0(u){if(!Cr(u))return!1;if(u?.terminalUnread===!0)return!0;if(u?.terminalUnread===!1)return!1;return!u?.readAt}function Cf(u){let f=Number(u||0);return Number.isFinite(f)?f:0}function SE(u){return Cf(u.queued)+Cf(u.retry_wait)}function mE(u){return Cf(u.running)+Cf(u.judging)}function pE(u,f){return Hf(u?.statistics)||Hf(f?.statistics)||{}}function PE(u){return Array.isArray(u?.daily)?u.daily:[]}function ME(u){return Hf(u?.totals)||{}}function vc(u,f){let l=Number(u?.[f]??0);return Number.isFinite(l)&&l>0?l:0}function Hc(u,f){return u.reduce((l,r)=>Math.max(l,vc(r,f)),0)}var w1=700,gU=220,zn=30,Ci=24,p_=184,Mc=p_-Ci;function qQ(u,f){if(f<=1)return w1/2;return zn+u*(w1-zn*2)/(f-1)}function NQ(u,f){let l=f>0?f:1;return p_-Math.min(1,u/l)*Mc}function Bc(u,f,l){let r=u.length>0?u:[{[f]:0}],n=r.length>1?r:[r[0],r[0]];return n.map((i,y)=>`${qQ(y,n.length).toFixed(2)},${NQ(vc(i,f),l).toFixed(2)}`).join(" ")}function B0(u){let f=String(u||"");return/^\d{4}-\d{2}-\d{2}$/u.test(f)?f.slice(5):f||"--"}function P3(u){if(!u)return"";return`${String(u.seriesKey||"")}:${String(u.row?.date||u.index||"")}`}function CE(u,f,l,r){let n=vc(u,r.key);return{...r,row:u,index:f,value:n,valueLabel:r.format(n),x:qQ(f,l),y:NQ(n,r.max),seriesKey:r.key}}function sU(u){if(V0(u))return 0;return{running:1,judging:2,retry_wait:3,queued:4,succeeded:8,failed:8,canceled:8}[String(u?.status||"")]??9}function X_(u){if(!u)return!1;if(u?._traceSummaryLoaded===!0)return!1;return u?.summaryOnly===!0||u?._metaLoaded!==!0}function RE(u){return Boolean(u?._metaLoaded)||u?.summaryOnly===!1}function xE(u,f,l){let r=String(u?.[l]||""),n=String(f?.[l]||"");return r.length>n.length?r:n}function Cc(u,f,l){let r=Array.isArray(u?.[l])?u[l]:[],n=Array.isArray(f?.[l])?f[l]:[];if(n.length===0&&r.length>0)return r;return r.length>n.length?r:n}function aU(u,f){let l=f?.summaryOnly===!0&&RE(u),r={...u,...f};if(!l)return r;for(let n of["prompt","basePrompt","displayPrompt","finalResponse"])r[n]=xE(u,f,n);for(let n of["promptHistory","attempts","output","events"])r[n]=Cc(u,f,n);if(u?.referenceInjection?.items&&!f?.referenceInjection?.items)r.referenceInjection=u.referenceInjection;if(u?.referenceInjectionSummary&&!f?.referenceInjectionSummary)r.referenceInjectionSummary=u.referenceInjectionSummary;r.summaryOnly=u?.summaryOnly===!1?!1:f.summaryOnly,r._metaLoaded=u?._metaLoaded,r._detailLoaded=u?._detailLoaded,r._transcriptComplete=u?._transcriptComplete,r._transcriptPreview=Object.prototype.hasOwnProperty.call(f,"_transcriptPreview")?f._transcriptPreview:u?._transcriptPreview;for(let n of["_traceSummary","_traceSummaryLoaded","_traceSteps","_traceStepsLoaded","_traceStepsByAttempt","_traceStepsLoadedByAttempt","_traceStepsNextAfterSeqByAttempt","_traceStepDetails","_promptDetails"])if(!Object.prototype.hasOwnProperty.call(f,n)&&Object.prototype.hasOwnProperty.call(u||{},n))r[n]=u[n];return r}function hE(u){let f=u?.selected,l=f?.task&&typeof f.task==="object"?f.task:null;if(l!==null){let n=Boolean(f?.preview);return{...l,transcript:Array.isArray(f?.transcript)?f.transcript:[],_detailLoaded:Array.isArray(f?.transcript)&&f.transcript.length>0,_transcriptComplete:Boolean(!n&&!f?.hasMore&&Cr(l)),_transcriptPreview:n,_summaryLoaded:!0}}let r=tl(u)[0];return r?{...r,_summaryLoaded:!0}:null}function Vc(u,f){let l=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(f)?f:[]]){let n=`${Number(r?.seq??0)}:${String(r?.kind||"message")}`,i=l.get(n);if(!i){l.set(n,r);continue}let y={...i,...r};for(let[_,$]of[["bodyPreview","bodyOmittedLines"],["commandPreview","commandOmittedLines"]]){let c=String(i?.[_]||""),A=String(r?.[_]||"");if(c.length>A.length)y[_]=i[_],y[$]=i[$]}l.set(n,y)}return Array.from(l.values()).sort((r,n)=>Number(r?.seq??0)-Number(n?.seq??0))}function M3(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,Number(l?.seq??0)),0)}function oU(u,f=8){let l=Array.from(new Set((Array.isArray(u)?u:[]).map((n)=>Number(n?.seq??0)).filter((n)=>Number.isFinite(n)&&n>0))).sort((n,i)=>n-i);if(l.length===0)return 0;let r=l[Math.max(0,l.length-f)]??0;return Math.max(0,r-0.001)}function bE(u,f){let l=Array.isArray(u?.codeModels)?u.codeModels:Array.isArray(u?.codexModels)?u.codexModels:[],r=["gpt-5.5","gpt-5.4-mini","gpt-5.4","minimax-m2.7"];return Array.from(new Set([...l,...r,f].map((n)=>String(n||"").trim()).filter(Boolean)))}function vE(u,f){let r=(Array.isArray(u?.executionProviders)?u.executionProviders:[]).map((y)=>({id:String(y?.id||"").trim(),label:String(y?.label||y?.id||"").trim(),defaultWorkdir:String(y?.defaultWorkdir||"").trim(),kind:String(y?.kind||"").trim()})).filter((y)=>y.id.length>0),n=String(u?.mainProviderId||u?.defaultProviderId||"main-server").trim()||"main-server",i=new Map;for(let y of[...r,{id:n,label:`${n} (master)`,defaultWorkdir:String(u?.defaultWorkdir||"/root/unidesk"),kind:"local"},f?{id:f,label:f,defaultWorkdir:R3(u,f),kind:""}:null].filter(Boolean))if(!i.has(y.id))i.set(y.id,y);return Array.from(i.values())}function R3(u,f){let l=String(f||"").trim(),r=u?.defaultWorkdirByProvider&&typeof u.defaultWorkdirByProvider==="object"?u.defaultWorkdirByProvider:{};if(typeof r[l]==="string"&&String(r[l]).trim().length>0)return String(r[l]).trim();let n=Array.isArray(u?.executionProviders)?u.executionProviders.find((y)=>String(y?.id||"")===l):null;if(typeof n?.defaultWorkdir==="string"&&n.defaultWorkdir.trim().length>0)return n.defaultWorkdir.trim();let i=String(u?.mainProviderId||u?.defaultProviderId||"main-server");return l===i?String(u?.defaultWorkdir||"/root/unidesk"):String(u?.remoteDefaultWorkdir||"/home/ubuntu")}function kE(u){return $Q(u)}function IE({task:u,selected:f,onSelect:l,onCopy:r,onReference:n,onMarkRead:i,copied:y,markingRead:_}){let $=u?.lastJudge||{},c=String(u?.id||""),A=V0(u),j=lQ(u?.updatedAt,_r(u)?.updatedAt),F=`最近更新: ${fQ(j)}`,U=kE(u),Q=U===null?"--":String(U),w=U===null?"STEP 统计中心同步中":"STEP 来自 OA Event Flow 统计中心";return K("article",{role:"button",tabIndex:0,className:`codex-task-card ${f?"selected":""} ${A?"unread-terminal":""}`,onClick:l,onKeyDown:(L)=>{if(L.key==="Enter"||L.key===" ")L.preventDefault(),l()},"data-unread-terminal":A?"true":"false","data-testid":`codex-task-${u?.id||"unknown"}`},A?K("span",{className:"codex-unread-badge",title:"待读","aria-label":"待读","data-testid":`codex-unread-task-${c||"unknown"}`}):null,K("div",{className:"codex-task-card-head"},K("div",{className:"codex-task-status-line"},K(K1,{status:u?.status,title:DE(u)},VE(u))),K("span",{className:"mono-text"},`${u?.currentAttempt||0}/${u?.maxAttempts||0}`)),K("div",{className:"codex-task-id-row"},K("code",{title:c},c||"unknown"),K("div",{className:"codex-task-id-actions"},K("button",{type:"button",className:"codex-copy-id-btn",onClick:(L)=>{L.stopPropagation(),n(c)},"data-testid":`codex-reference-task-${c||"unknown"}`},"引用"),K("button",{type:"button",className:"codex-copy-id-btn",onClick:(L)=>{L.stopPropagation(),r(c)},"data-testid":`codex-copy-task-id-${c||"unknown"}`},y?"已复制":"复制ID"),A?K("button",{type:"button",className:"codex-copy-id-btn codex-mark-read-btn",disabled:Boolean(_),onClick:(L)=>{L.stopPropagation(),i(c)},"data-testid":`codex-mark-task-read-${c||"unknown"}`},_?"标记中":"标为已读"):null)),K("strong",null,Xc(iQ(u),120)||"空任务"),K("div",{className:"codex-task-meta"},K("span",null,`queue=${m_(u)}`),K("span",null,`provider=${u?.providerId||"main-server"}`),K("span",null,u?.model||"--"),K("span",null,BE(u))),K("div",{className:"codex-task-meta codex-task-update-meta"},K("span",{className:"codex-task-recent-update codex-task-step-count",title:w,"data-testid":`codex-task-step-count-${c||"unknown"}`},`STEP ${Q}`),K("span",{className:"codex-task-recent-update",title:j?`更新时间: ${Nu(j)}`:F,"data-testid":`codex-task-recent-update-${c||"unknown"}`},F),K("span",null,Nu(j||u?.updatedAt))),QQ(u)?K("div",{className:"codex-judge-line","data-testid":`codex-task-prompt-editable-${c||"unknown"}`},"queued prompt 可编辑"):null,$?.decision?K("div",{className:"codex-judge-line"},`judge=${$.decision} ${Math.round(Number($.confidence||0)*100)}%`):null)}function Dc({title:u,tasks:f,selectedId:l,onSelect:r,onCopy:n,onReference:i,onMarkRead:y,copiedTaskId:_,markingReadTaskId:$,emptyText:c}){let A=Array.isArray(f)?f:[];return K("section",{className:"codex-task-section"},K("div",{className:"codex-task-section-head"},K("span",null,u),K("code",null,String(A.length))),A.length===0?K("p",{className:"codex-task-section-empty"},c):K("div",{className:"codex-task-section-list"},A.map((j)=>K(IE,{key:j.id,task:j,selected:l===j.id,onSelect:()=>r(j.id),onCopy:n,onReference:i,onMarkRead:y,copied:_===j.id,markingRead:$===j.id}))))}function gE(){return K("span",{className:"codex-stats-icon","aria-hidden":"true"},K("svg",{viewBox:"0 0 36 24",focusable:"false"},K("path",{className:"grid",d:"M3 20.5H33M3 12.5H33M3 4.5H33"}),K("polyline",{className:"line tasks",points:"3,18 9,14 15,15 21,8 27,10 33,4"}),K("polyline",{className:"line retry",points:"3,20 9,17 15,18 21,13 27,14 33,9"})))}function sE({stats:u,queueName:f,onRaw:l}){let r=PE(u),n=ME(u),i=r.at(-1)||{},y=Hc(r,"executedTasks"),_=Hc(r,"retryAttempts"),$=Hc(r,"avgDurationMs"),c=r.length>0,A=Hf(u?.range)||{},[j,F]=Iu(null),[U,Q]=Iu(null),w=[];if(y>0)w.push(`tasks ${y}`);if(_>0)w.push(`retry ${_}`);if($>0)w.push(`avg ${Rr($)}`);let L=[{key:"executedTasks",className:"tasks",label:"执行任务",max:y,format:(E)=>`${Cf(E)} tasks`},{key:"retryAttempts",className:"retry",label:"重试次数",max:_,format:(E)=>`${Cf(E)} retries`},{key:"avgDurationMs",className:"duration",label:"平均耗时",max:$,format:(E)=>Rr(E)}],J=j||U,N=P3(J),q=String(J?.row?.date||""),W=J?{left:`${Math.max(8,Math.min(92,Number(J.x)/w1*100))}%`,top:`${Math.max(14,Math.min(86,Number(J.y)/gU*100))}%`}:void 0;Gn(()=>{F(null),Q(null)},[f,A.startDate,A.endDate,r.length]);let z=(E)=>{F(E)},Z=(E)=>{let D=P3(E);Q((h)=>P3(h)===D?null:E),F(E)},H=L.flatMap((E)=>r.map((D,h)=>{let B=CE(D,h,r.length,E),X=P3(B),m=N===X,O=String(D?.date||`day-${h}`),p=`${B0(O)} ${E.label}: ${B.valueLabel}`;return K("g",{key:`${E.key}-${O}`,className:`stat-point-group ${E.className} ${m?"active":""}`,role:"button",tabIndex:0,"aria-label":p,"data-testid":`codex-stats-point-${E.className}-${O}`,onMouseEnter:()=>z(B),onFocus:()=>z(B),onClick:()=>Z(B),onKeyDown:(Y)=>{if(Y.key==="Enter"||Y.key===" ")Y.preventDefault(),Z(B)}},K("circle",{className:"stat-hit-point",cx:B.x,cy:B.y,r:13}),K("circle",{className:`stat-point ${E.className} ${m?"active":""}`,cx:B.x,cy:B.y,r:m?5.6:4.2}))}));return K(Mi,{title:"统计曲线",eyebrow:`Daily task stats / ${f}`,className:"codex-stats-panel",summary:K("span",null,`${B0(A.startDate)} -> ${B0(A.endDate)} · ${u?.timezone||"Asia/Shanghai"}`),actions:Hf(u)?K(rQ,{title:"Code Queue Stats",data:u,onOpen:l,testId:"raw-codex-stats"}):null},K("div",{className:"codex-stats-hero","data-testid":"codex-stats-panel"},K(gE),K("div",null,K("strong",null,`${Cf(n.executedTasks)} tasks / ${Cf(n.retryAttempts)} retries`),K("span",null,`平均完成耗时 ${Rr(n.avgDurationMs??void 0)} · 终态 ${Cf(n.completedTasks)} 个`))),c?K("div",{className:"codex-stats-chart","data-testid":"codex-stats-chart",onMouseLeave:()=>F(null)},K("svg",{viewBox:`0 0 ${w1} ${gU}`,preserveAspectRatio:"none",role:"img","aria-label":"Code Queue daily task statistics"},K("line",{className:"axis",x1:zn,x2:w1-zn,y1:p_,y2:p_}),K("line",{className:"grid",x1:zn,x2:w1-zn,y1:Ci+Mc/2,y2:Ci+Mc/2}),K("line",{className:"grid",x1:zn,x2:w1-zn,y1:Ci,y2:Ci}),K("polyline",{className:"stat-line tasks",points:Bc(r,"executedTasks",y)}),K("polyline",{className:"stat-line retry",points:Bc(r,"retryAttempts",_)}),K("polyline",{className:"stat-line duration",points:Bc(r,"avgDurationMs",$)}),J?K("g",{className:"stat-cursor-layer","data-testid":"codex-stats-active-point"},K("line",{className:"stat-cursor",x1:J.x,x2:J.x,y1:Ci,y2:p_}),K("circle",{className:`stat-point-active ${J.className}`,cx:J.x,cy:J.y,r:8})):null,K("g",{className:"stat-point-layer"},H)),J?K("div",{className:"codex-stats-tooltip active",style:W,"data-testid":"codex-stats-tooltip"},K("b",null,B0(J.row?.date)),K("span",null,`${J.label} · ${J.valueLabel}`),K("code",null,`${Cf(J.row?.executedTasks)} exec / ${Cf(J.row?.retryAttempts)} retry / ${Rr(J.row?.avgDurationMs??void 0)}`)):null,K("div",{className:"codex-stats-legend"},K("span",{className:"tasks"},"执行任务"),K("span",{className:"retry"},"重试次数"),K("span",{className:"duration"},"平均耗时")),K("div",{className:"codex-stats-scale"},K("span",null,B0(r[0]?.date)),K("span",null,w.join(" · ")||"暂无峰值"),K("span",null,B0(r.at(-1)?.date))),K("div",{className:`codex-stats-focus ${J?"active":""}`,"data-testid":"codex-stats-focus"},J?K(P_.default.Fragment,null,K("div",null,K("strong",null,B0(J.row?.date)),K("span",null,`${J.label} · ${J.valueLabel}`)),K("div",{className:"codex-stats-focus-metrics"},K("code",null,`${Cf(J.row?.executedTasks)} exec`),K("code",null,`${Cf(J.row?.retryAttempts)} retry`),K("code",null,Rr(J.row?.avgDurationMs??void 0)))):K("span",null,"将鼠标悬停到曲线数据点查看明细,点击数据点可固定。"))):K(G1,{title:"暂无统计",text:"任务开始执行后会生成按天汇总的曲线。"}),K("div",{className:"codex-stats-summary-grid"},K("article",null,K("span",null,"今日执行"),K("strong",null,String(Cf(i.executedTasks))),K("code",null,B0(i.date))),K("article",null,K("span",null,"今日重试"),K("strong",null,String(Cf(i.retryAttempts))),K("code",null,`累计 ${Cf(n.retryAttempts)}`)),K("article",null,K("span",null,"平均耗时"),K("strong",null,Rr(n.avgDurationMs??void 0)),K("code",null,`${Cf(n.durationSamples)} samples`))),K("div",{className:"codex-stats-daily-list","data-testid":"codex-stats-daily-list"},r.slice(-7).map((E)=>K("div",{key:String(E?.date||""),className:`codex-stats-daily-row ${q===String(E?.date||"")?"active":""}`,"data-testid":`codex-stats-day-${String(E?.date||"unknown")}`},K("span",null,B0(E?.date)),K("b",null,`${Cf(E?.executedTasks)} exec`),K("b",null,`${Cf(E?.retryAttempts)} retry`),K("code",null,Rr(E?.avgDurationMs??void 0))))))}function aE({task:u,queueRows:f,busy:l,onMove:r}){let n=String(u?.id||""),i=m_(u),[y,_]=Iu(i);Gn(()=>{_(i)},[n,i]);let $=!n||l||["running","judging","retry_wait"].includes(String(u?.status||""));return K("div",{className:"codex-task-move-control","data-testid":"codex-task-queue-move-control"},K("label",null,"任务 queue",K("select",{value:y,disabled:!n||l,onChange:(c)=>_(String(c.target.value||i)),"data-testid":"codex-task-queue-move-select"},f.map((c)=>K("option",{key:String(c?.id||""),value:String(c?.id||"")},S_(c))))),K("button",{type:"button",className:"ghost-btn",disabled:$||y===i,onClick:()=>r(y),title:$?"运行中 / judging / retry_wait 的任务不能移动;请先打断或等当前 turn 结束":"移动已创建任务到另一个 queue","data-testid":"codex-task-queue-move-button"},"移动"))}function dU(u,f=4){let l=(Array.isArray(u)?u:[]).map((n)=>String(n||"").trim()).filter(Boolean);if(l.length===0)return"--";let r=l.slice(0,f).join(" / ");return l.length>f?`${r} +${l.length-f}`:r}function oE({task:u,loading:f,onLoadPromptPart:l,testId:r="codex-initial-prompt-full",textTestId:n="codex-initial-prompt-full-text",baseTextTestId:i="codex-initial-prompt-base"}){let y=hc(u),_=x3(u),$=C3(u).trimEnd(),c=String(_.full?.text||""),A=wE(u),j=Number(y.promptChars||u?.promptChars||c.length),F=Number(y.basePromptLines||L1($)),U=Number(y.promptLines||L1(c));return K("section",{className:"codex-progressive-card codex-progressive-prompt","data-testid":"codex-progressive-prompt"},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Prompt"),K("strong",null,"Submitted prompt / 原始用户 prompt"),K("code",null,`${F||L1($)} lines / ${$.length} chars`)),K("pre",{className:"codex-prompt-full","data-testid":i},$||"空 prompt"),A?K("details",{className:"codex-reference-injection codex-progressive-full-prompt","data-testid":r,onToggle:(Q)=>{if(Q.currentTarget?.open&&!c)l?.("full")}},K("summary",null,K("span",null,"引用注入已折叠,点击按需拉取最终进入 Code agent 的完整 prompt"),K("code",null,c?`${U||L1(c)} lines / ${c.length} chars`:`${Number.isFinite(j)&&j>0?j:"--"} chars`)),K("pre",{className:"codex-prompt-full codex-prompt-final-full","data-testid":n},c||(f?"正在按需拉取完整 prompt...":"展开后将只请求 full prompt,不拉取完整 transcript。"))):null)}function WQ({task:u,attempt:f,attemptIndex:l,loading:r,onLoadSteps:n,onLoadStep:i,testId:y="codex-execution-summary"}){let _=ZE(FQ(u,l)),$=OE(UE(u,f)),c=f?AE(u,f):_Q(u),A=Pc(u),j=pc(u,l),F=D0(c?.errorCount),U=D0(c?.stepCount??c?.llmStepCount),Q=D0(c?.readCount),w=D0(c?.editCount),L=D0(c?.runCount),J=D0(c?.stepCount??c?.llmStepCount),N=U===null?"--":String(U),q=J===null?"--":String(J),W=Array.isArray($.editedFiles)?$.editedFiles:[],z=Array.isArray($.commands)?$.commands:[],H=bc(f,l)?` · ${String(f?.label||"recovered thread execution")}`:l?` #${l}`:"",E=QE(u,f,l,$),D=`最近更新: ${fQ(E)}`,h=NE(u,f,l);return K("details",{className:`codex-progressive-card codex-execution-summary ${h?"running":""}`,"data-testid":y,"data-attempt-index":b3(l),"data-running":h?"true":"false",onToggle:(B)=>{if(B.currentTarget?.open&&!j)n?.(l)}},K("summary",null,K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Summary"),K("strong",null,`执行过程摘要${H}`),h?K("span",{className:"codex-summary-running-pill","data-testid":`${y}-running`},"执行中"):null,K("code",{title:E?`最近更新: ${Nu(E)}`:D},`${Rr($.durationMs??$.totalElapsedMs)} / ${N} tools / ${D}`)),K("div",{className:"codex-execution-digest"},K("span",{title:"来自 OA Event Flow 统计中心"},`read ${Q===null?"--":Q}`),K("span",{title:"来自 OA Event Flow 统计中心"},`edit ${w===null?"--":w}`),K("span",{title:"来自 OA Event Flow 统计中心"},`run ${L===null?"--":L}`),K("span",{title:"来自 OA Event Flow 统计中心"},`STEP ${q}`),F!==null&&F>0?K("span",{className:"codex-execution-error-pill","data-testid":`${y}-error-count`},`Error ${F}`):null)),K("div",{className:"codex-execution-digest expanded"},K("span",null,`修改文件:${dU(W,6)}`),K("span",null,`执行命令:${dU(z,4)}`)),_.length===0?K("div",{className:"codex-output-empty"},r?"正在按需拉取步骤 summary...":"展开后将只请求执行步骤 summary,不拉取单步骤全量。"):K("div",{className:"codex-trace-step-list"},_.map((B)=>{let X=String(B?.seq??""),m=A[X],O=Array.isArray(B?.summaryLines)?B.summaryLines.slice(0,4):[];return K("details",{key:X||`${B?.title}-${B?.at}`,className:`codex-trace-step ${String(B?.kind||"message")} ${GE(B)?"error":""}`,"data-testid":`codex-trace-step-${X||"unknown"}`,onToggle:(p)=>{if(p.currentTarget?.open&&!m)i?.(B?.seq)}},K("summary",null,K("span",{className:"codex-output-channel"},dE(B?.kind)),K("strong",null,String(B?.title||"Trace step")),B?.status?K("code",null,String(B.status)):null,K("time",null,Nu(B?.at))),K("div",{className:"codex-trace-step-summary"},O.length>0?O.map((p,Y)=>K("pre",{key:`${X}-${Y}`},String(p||""))):K("span",null,"无 summary")),m?.line?K(Y3,{items:[m.line],autoScroll:!1,loading:!1,hasDetail:!0,emptyText:"无步骤详情",testId:`codex-trace-step-detail-${X||"unknown"}`,className:"codex-transcript codex-step-detail-transcript",collapseTools:!1}):K("div",{className:"codex-output-empty"},r?"正在按需拉取这个步骤的全量数据...":"展开后将只请求这个单步骤的全量数据。"))})))}function dE(u){let f=String(u||"");if(f==="ran")return"Ran";if(f==="explored")return"Explored";if(f==="edited")return"Edited";if(f==="error")return"Error";if(f==="system")return"System";return"Message"}function wQ({task:u,attempt:f,attemptIndex:l,testId:r="codex-final-response"}){let n=qE(u,f);if(n.length===0)return null;let i=Number(f?.finalResponseChars||n.length),y=l?` #${l}`:"";return K("section",{className:"codex-progressive-card codex-final-response","data-testid":r,"data-attempt-index":b3(l)},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Final"),K("strong",null,`最终 response${y}`),K("code",null,`${Number.isFinite(i)?i:n.length} chars`)),K(cU,{markdown:n,className:"codex-transcript-body codex-markdown",testId:`${r}-markdown`}))}function LQ({task:u,attempt:f,attemptIndex:l,testId:r="codex-progressive-judge"}){let n=AQ(u,f);if(!n?.decision)return null;let i=l?` #${l}`:"";return K("section",{className:"codex-progressive-card codex-progressive-judge","data-testid":r,"data-attempt-index":b3(l)},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Judge"),K("strong",null,`完成判定${i}`),K("code",null,`${n.decision} ${Math.round(Number(n.confidence||0)*100)}%`)),K("div",{className:"codex-judge-card","data-testid":`${r}-card`},K(K1,{status:n.decision},n.decision),K("strong",null,`${Math.round(Number(n.confidence||0)*100)}% confidence`),K("p",{"data-testid":`${r}-reason`},n.reason||"--"),n.continuePrompt?K("pre",{"data-testid":`${r}-continue-prompt`},String(n.continuePrompt||"")):null))}function eE({task:u,attempt:f,attemptIndex:l,loading:r,onLoadPromptPart:n,testId:i="codex-judge-feedback-prompt"}){let y=WE(u,f,l);if(y===null)return null;let _=jQ(l),c=x3(u)[_],A=String(c?.text||"").trimEnd(),j=String(y.preview||y.text||"").trimEnd(),F=A||String(y.text||"").trimEnd(),U=Number(c?.chars||y.chars||F.length||j.length),Q=Number(c?.lines||y.lines||L1(F||j)),w=c?.forAttempt||y.forAttempt||Number(l||0)+1;return K("details",{className:"codex-progressive-card codex-judge-feedback-prompt","data-testid":i,"data-attempt-index":b3(l),onToggle:(L)=>{if(L.currentTarget?.open&&!A)n?.("feedback",l)}},K("summary",null,K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Prompt"),K("strong",null,`judge feedback prompt #${l} -> #${w}`),K("code",null,`${Q||"--"} lines / ${Number.isFinite(U)?U:j.length} chars`)),K("p",{className:"codex-feedback-preview","data-testid":`${i}-preview`},j||"展开后按需拉取 judge feedback prompt。")),K("pre",{className:"codex-prompt-full codex-feedback-full","data-testid":`${i}-text`},F||(r?"正在按需拉取 judge feedback prompt...":"展开后将只请求这一次 judge feedback prompt。")))}function uZ({task:u,attempt:f,position:l,loading:r,onLoadPromptPart:n,onLoadSteps:i,onLoadStep:y}){let _=HE(f,l),$=l===0,c=bc(f,_),A=c?String(f?.label||"Recovered thread execution"):`Attempt ${_}`;return K("section",{className:"codex-attempt-cycle","data-testid":`codex-attempt-cycle-${_}`},K("div",{className:"codex-attempt-cycle-head"},K("span",{className:"codex-output-channel"},A),K("strong",null,String(f?.mode||(_<=1?"initial":"retry"))),f?.terminalStatus?K(K1,{status:f.terminalStatus},f.terminalStatus):null,K("code",null,`${Nu(f?.startedAt)} -> ${Nu(f?.finishedAt)}`)),K(WQ,{task:u,attempt:f,attemptIndex:_,loading:r,onLoadSteps:i,onLoadStep:y,testId:$?"codex-execution-summary":`codex-execution-summary-attempt-${_}`}),c?null:K(wQ,{task:u,attempt:f,attemptIndex:_,testId:$?"codex-final-response":`codex-final-response-attempt-${_}`}),c?null:K(LQ,{task:u,attempt:f,attemptIndex:_,testId:$?"codex-progressive-judge":`codex-progressive-judge-attempt-${_}`}),c?null:K(eE,{task:u,attempt:f,attemptIndex:_,loading:r,onLoadPromptPart:n,testId:$?"codex-judge-feedback-prompt":`codex-judge-feedback-prompt-attempt-${_}`}))}function fZ({task:u,loading:f,onLoadPromptPart:l,onLoadSteps:r,onLoadStep:n}){if(!u)return K(G1,{title:"未选择任务",text:"从左侧队列选择任务,或提交新 Codex 任务。"});let i=JE(u);return K("div",{className:"codex-transcript codex-progressive-trace","data-testid":"codex-output"},f&&!_r(u)?K("div",{className:"codex-output-empty"},"正在加载 Trace Summary..."):null,K(oE,{task:u,loading:f,onLoadPromptPart:l}),i.length>0?i.map((y,_)=>K(uZ,{key:`${y?.index||_+1}-${y?.startedAt||_}`,task:u,attempt:y,position:_,loading:f,onLoadPromptPart:l,onLoadSteps:r,onLoadStep:n})):[K(WQ,{key:"execution",task:u,loading:f,onLoadSteps:r,onLoadStep:n}),K(wQ,{key:"final",task:u}),K(LQ,{key:"judge",task:u})])}function lZ({task:u}){let f=iE(u);if(!u||f.length===0)return K(G1,{title:"暂无原始消息",text:"原始 Codex app-server 消息会保留在任务 JSON 中。"});return K("details",{className:"codex-raw-output"},K("summary",null,`原始 messages (${f.length})`),K("div",null,f.map((l)=>K("article",{key:`${l.seq}-${l.channel}`,className:`codex-output-line ${l.channel||"system"}`},K("div",{className:"codex-output-meta"},K("span",{className:"codex-output-channel"},XE(String(l.channel||"system"))),K("span",null,Nu(l.at)),l.method?K("code",null,l.method):null),K("pre",null,String(l.text||""))))))}function rZ({task:u}){let f=yE(u).slice().reverse();if(f.length===0)return K(G1,{title:"尚无 attempt",text:"任务开始运行后,这里会记录 Codex 终态、传输中断和 stderr tail。"});return K("div",{className:"table-wrap codex-attempt-table"},K("table",null,K("thead",null,K("tr",null,K("th",null,"#"),K("th",null,"模式"),K("th",null,"终态"),K("th",null,"传输"),K("th",null,"退出"),K("th",null,"完成时间"))),K("tbody",null,f.map((l)=>K("tr",{key:`${l.index}-${l.startedAt}`},K("td",null,l.index),K("td",null,l.mode),K("td",null,K(K1,{status:l.terminalStatus||"unknown"},l.terminalStatus||"unknown")),K("td",null,l.transportClosedBeforeTerminal?K(K1,{status:"failed"},"closed-before-terminal"):K(K1,{status:"succeeded"},"normal")),K("td",null,`code=${l.appServerExitCode??"--"} signal=${l.appServerSignal??"--"}`),K("td",null,Nu(l.finishedAt)))))))}function KQ({microservices:u,onRaw:f,apiBaseUrl:l="/api",initialTasksData:r=null,standalone:n=!1}){let i=u.find((V)=>V.id==="code-queue")||null,y=hE(r),_=String(y?.id||""),$=new Map;if(y!==null&&_.length>0)$.set(_,{task:y,maxSeq:M3(Array.isArray(y.transcript)?y.transcript:[]),complete:Boolean(y._transcriptComplete),completeUpdatedAt:y._transcriptComplete?String(y.updatedAt||""):""});let c=typeof performance>"u"?0:performance.now(),A=Df(_),j=Df(0),F=Df(0),U=Df(0),Q=Df(!1),w=Df(!1),L=Df(!1),J=Df(null),N=Df(new Map),q=Df(new Map),W=Df(new Map),z=Df(new Map),Z=Df(new Set),H=Df(null),E=Df(null),D=Df(!1),h=Df(!1),B=Df(Boolean(r)),X=Df(new Map),m=Df(new Set),O=Df($),p=Df(r),[Y,v]=Iu(null),[T,S]=Iu(r),[k,I]=Iu(_),[b,o]=Iu(y),[s,x]=Iu(!1),[fu,$u]=Iu(""),[tu,ju]=Iu(null),[Gu,qu]=Iu(!1),[P,e]=Iu(!1),[uu,Wu]=Iu(""),[g,Qu]=Iu(""),[Tu,Zu]=Iu("default"),[Xu,ff]=Iu(Tn),[_f,Jf]=Iu(!1),[mf,Yl]=Iu(""),[Al,jl]=Iu("main-server"),[Hr,al]=Iu("gpt-5.5"),[Au,vu]=Iu("/root/unidesk"),[Kl,Su]=Iu(99),[pf,Gl]=Iu(1),[zl,Pf]=Iu(!1),[rf,Ir]=Iu(!1),[Fr,x1]=Iu(""),[gn,b0]=Iu(""),[lu,Ou]=Iu(""),[mu,ou]=Iu(!0),[Af,vf]=Iu(()=>typeof window>"u"?!0:window.matchMedia(kT).matches),[pu,ll]=Iu(!1),[J0,Gf]=Iu(""),[d9,kf]=Iu(""),{addNotification:ol}=Bl(),[Wy,C$]=Iu(""),[wy,R$]=Iu(""),[h1,Ly]=Iu(!1),[Tl,gr]=Iu(r?{phase:"complete",taskId:_,queueMs:0,detailMs:0,totalMs:c,chunks:y?1:0,transcriptRows:Array.isArray(y?.transcript)?y.transcript.length:0,partial:Boolean(r?.selected?.hasMore||X_(y)),completedAt:new Date}:null),[x$,h$]=Iu(r?new Date:null),[Ky,b$]=Iu(!1),sr=s1(tl(T)),Gy=sr.filter(V0),If=T?.queue||Y?.body?.queue||Y?.queue||{},V8=pE(T,If),v$=Kn(T),Br=RU(If,Tu),sn=String(Tu||"default").trim()||"default",an=Br.filter((V)=>String(V?.id||"")!==sn),b1=Ri(Br,Xu),v0=Number((xl(Xu)?If?.total:b1?.total)??v$.total??sr.length),zy=Y_(If),e9=xl(Xu)?zy:[String(Ri(Br,Xu)?.activeTaskId||"")].filter(Boolean),v1=xU(If,Br,Xu,sr),u7=xl(Xu)?Oc(If):Oc(b1||{}),k$=Oc(If),D8=SE(k$),X8=Math.max(mE(k$),zy.length),Y8=Cf((xl(Xu)?If?.unreadTerminal:b1?.unreadTerminal)??Gy.length),U0=T?Gy.length:Y8,k1=xl(Xu)?"All queues":Sc(b1||{id:Xu,name:Xu}),k0=Yc(fu),Sl=k0.length>0,I$=Sl?s1(tl(tu)):[],on=Kn(tu),Jr=Sl?I$:sr,g$=Jr.filter(V0),s$=Jr.filter((V)=>!Cr(V)).sort(hT),qL=Jr.filter((V)=>Cr(V)&&!V0(V)),f7=Sl?on:v$,I1=Sl?Number(on.total??I$.length):v0,l7=f7.hasMore===!0&&String(f7.nextBeforeId||"").length>0,S8=Sl?P:Ky,NL=i?CT(i):{},WL=i?RT(i):{},m8=PU(()=>_E(uu),[uu]),Q0=PU(()=>{let V=bU(pf);return m8.flatMap((C)=>Array.from({length:V},()=>$E(C,g)))},[m8,pf,g]),Ty=Q0.length,r7=Ty>1&&!zl,wL=rf||pu||Ty===0||r7,n7=bE(If,Hr),i7=vE(If,Al),LL=R3(If,Al),p8=b?.id&&b?.activeTurnId&&String(b?.status)==="running",KL=b?.id&&!["succeeded","failed","canceled"].includes(String(b?.status||"")),GL=b?.id&&["succeeded","failed","canceled"].includes(String(b?.status||"")),g1=b?.id&&QQ(b);function Ur(V){let C=typeof V==="function"?V(p.current):V;return p.current=C,S(C),C}function zL(V,C,d=!0){let iu=Array.from(new Set(V.map((Ju)=>String(Ju||"")).filter(Boolean)));for(let Ju of iu)if(X.current.set(Ju,C),d)m.current.add(Ju);return iu}function y7(V){for(let C of V.map((d)=>String(d||"")).filter(Boolean))X.current.delete(C),m.current.delete(C)}function a$(V){let C=String(V?.id||""),d=C?X.current.get(C):void 0;if(!d)return V;if(String(V?.status||"").length>0&&!Cr(V))return X.current.delete(C),m.current.delete(C),V;return{...V,readAt:V?.readAt||d,terminalUnread:!1}}function P8(V){let C=String(V?.id||"");return C.length>0&&m.current.has(C)&&Cr(V)}function s1(V,C=!0){let d=[];for(let iu of Array.isArray(V)?V:[]){let Ju=a$(iu);if(C&&P8(Ju))continue;d.push(Ju)}return d}function TL(V,C=!0){if(!V||!Array.isArray(V?.tasks))return V;let d=s1(tl(V),C),iu=Kn(V);return{...V,tasks:d,pagination:V.pagination?{...iu,returned:d.length}:V.pagination}}function EL(V){let C=String(V||If?.mainProviderId||"main-server").trim()||"main-server";jl(C),vu(R3(If,C))}function o$(V,C,d=null,iu=null){let Ju=new Set(zL(V,C));if(Ju.size===0&&iu===null&&d===null)return;Ur((Ku)=>{if(!Ku)return Ku;let wu=tl(Ku).flatMap((Ru)=>{let hu=String(Ru?.id||"");if(!Ju.has(hu)){let jf=a$(Ru);return P8(jf)?[]:[jf]}let Pu=iu&&String(iu?.id||"")===hu?iu:{},xu={...Ru,...Pu,readAt:C,terminalUnread:!1};return P8(xu)?[]:[xu]});return{...Ku,queue:d||Ku.queue,tasks:Ju.size>0?Pi([wu],v1):wu}});for(let Ku of Ju){let wu=O.current.get(Ku);if(wu?.task){let Ru=iu&&String(iu?.id||"")===Ku?iu:{},hu={...wu.task,...Ru,readAt:C,terminalUnread:!1};if(O.current.set(Ku,{...wu,task:hu}),A.current===Ku)o(hu)}}}Gn(()=>{Pf(!1)},[uu,pf,g]),Gn(()=>{let V=Yc(fu);F.current+=1;let C=F.current;if(!i||V.length===0){ju(null),qu(!1),e(!1),L.current=!1;return}qu(!0),ju(null);let d=window.setTimeout(()=>{(async()=>{try{let iu=await oT(l,Xu,V);if(C!==F.current)return;ju(TL(iu))}catch(iu){if(C===F.current)ju(null),Gf($l(iu,"搜索 Codex tasks 失败"))}finally{if(C===F.current)qu(!1)}})()},240);return()=>window.clearTimeout(d)},[i?.id,l,Xu,fu]),Gn(()=>{b0(b?C3(b):""),Ou(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},[k]);function q0(V,C,d){let iu=O.current.get(V)||{},Ju=iu.task||{},Ku=Array.isArray(Ju.transcript)?Ju.transcript:[],wu=aU(Ju,C),Ru=Object.prototype.hasOwnProperty.call(C,"transcript")?Vc(Ku,Array.isArray(C.transcript)?C.transcript:[]):Ku,hu={...Ju,...wu,transcript:Ru,output:Array.isArray(wu.output)?Cc(Ju,wu,"output"):Array.isArray(Ju.output)?Ju.output:[],events:Array.isArray(wu.events)?Cc(Ju,wu,"events"):Array.isArray(Ju.events)?Ju.events:[]},Pu=a$(hu),xu=String(Pu?.updatedAt||""),jf=Boolean(C._transcriptComplete)&&Cr(Pu),rl=Boolean(iu.complete)&&Cr(Pu)&&String(iu.completeUpdatedAt||"")===xu,du=jf||rl,ef={...iu,task:Pu,maxSeq:M3(Ru),complete:du,completeUpdatedAt:du?xu:""};if(O.current.set(V,ef),d===U.current&&A.current===V)o(Pu);return ef}async function a1(V,C=!1,d,iu){if(!i||!V)return;let Ku=O.current.get(V)?.task;if(!C&&p3(Ku))return;let wu=V,Ru=N.current.get(wu);if(Ru){if(C||!p3(Ku))Ru.refreshAfter=!0;return Ru.promise}let hu=U.current,Pu=performance.now();if(A.current===V)x(!0);let xu={promise:Promise.resolve(),refreshAfter:!1},jf=(async()=>{try{let rl=await eT(l,V);if(hu!==U.current||A.current!==V)return;let du=rl?.summary||{},ef=String(du.updatedAt||"");q0(V,{id:V,status:du.status,updatedAt:ef,startedAt:du.startedAt,finishedAt:du.finishedAt,currentAttempt:du.currentAttempt,maxAttempts:du.maxAttempts,finalResponse:du.finalResponse,lastJudge:du.lastJudge,lastError:du.lastError,attempts:Array.isArray(du.attempts)?du.attempts:[],stepCount:du.stepCount,llmStepCount:du.llmStepCount,traceStats:du.traceStats,statsSource:du.statsSource,timing:du.timing,_traceSummary:du,_traceSummaryLoaded:!0,_traceSummaryUpdatedAt:ef,_detailLoaded:!0},hu),gr({phase:"complete",taskId:V,queueMs:iu??0,detailMs:performance.now()-Pu,totalMs:d===void 0?performance.now()-Pu:performance.now()-d,chunks:1,transcriptRows:Number(du?.execution?.traceLineCount||du?.execution?.stepCount||0),partial:!1,completedAt:new Date})}finally{let rl=Boolean(xu.refreshAfter&&A.current===V&&!p3(O.current.get(V)?.task));if(N.current.delete(wu),hu===U.current&&A.current===V)x(!1);if(rl)window.setTimeout(()=>{a1(V,!0).catch((du)=>Gf($l(du,"自动刷新 Trace Summary 失败")))},0)}})();xu.promise=jf,N.current.set(wu,xu),await jf}async function ZL(V,C=null){let d=A.current;if(!i||!d||!V)return;let iu=O.current.get(d)?.task,Ju=x3(iu),Ku=V==="feedback"||V==="judge-feedback"?jQ(C):V;if(Ju[Ku]?.text)return;let wu=`${d}:${Ku}`,Ru=q.current.get(wu);if(Ru)return Ru;let hu=U.current;if(A.current===d)x(!0);let Pu=(async()=>{try{let xu=await uE(l,d,V,C);if(hu!==U.current||A.current!==d)return;let jf=O.current.get(d)?.task,rl=x3(jf);q0(d,{...V==="full"?{prompt:String(xu?.text||""),promptChars:Number(xu?.chars||0)}:{},_promptDetails:{...rl,[Ku]:xu}},hu)}finally{if(q.current.delete(wu),hu===U.current&&A.current===d)x(!1)}})();q.current.set(wu,Pu),await Pu}async function M8(V=null,C={}){let d=A.current;if(!i||!d)return;let iu=O.current.get(d)?.task,Ju=V===null||V===void 0||String(V).length===0?"":String(V),Ku=pc(iu,Ju||null),wu=Boolean(C.force),Ru=Boolean(C.incremental);if(Ku&&!wu)return;let hu=FQ(iu,Ju||null),Pu=Ru&&hu.length>0?LE(hu):0,xu=`${d}:${Ju||"all"}:${Pu}`,jf=W.current.get(xu);if(jf)return jf;let rl=U.current;if(A.current===d)x(!0);let du=(async()=>{try{let ef=await fE(l,d,Pu,500,Ju||null);if(rl!==U.current||A.current!==d)return;let I0=Array.isArray(ef?.steps)?ef.steps:[],g0=Pu>0?KE(hu,I0):I0;if(Ju){let s0=O.current.get(d)?.task,o1=Hf(s0?._traceStepsByAttempt)||{},nl=Hf(s0?._traceStepsLoadedByAttempt)||{},N0=Hf(s0?._traceStepsNextAfterSeqByAttempt)||{};q0(d,{_traceStepsByAttempt:{...o1,[Ju]:g0},_traceStepsLoadedByAttempt:{...nl,[Ju]:!0},_traceStepsNextAfterSeqByAttempt:{...N0,[Ju]:ef?.nextAfterSeq}},rl)}else q0(d,{_traceSteps:g0,_traceStepsLoaded:!0,_traceStepsHasMore:Boolean(ef?.hasMore),_traceStepsNextAfterSeq:ef?.nextAfterSeq},rl)}finally{if(W.current.delete(xu),rl===U.current&&A.current===d)x(!1)}})();W.current.set(xu,du),await du}async function OL(V){let C=A.current,d=String(V??"");if(!i||!C||d.length===0)return;let iu=O.current.get(C)?.task;if(Pc(iu)[d]?.line)return;let Ku=`${C}:${d}`,wu=z.current.get(Ku);if(wu)return wu;let Ru=U.current;if(A.current===C)x(!0);let hu=(async()=>{try{let Pu=await lE(l,C,V);if(Ru!==U.current||A.current!==C)return;let xu=O.current.get(C)?.task,jf=Pc(xu);q0(C,{_traceStepDetails:{...jf,[d]:Pu}},Ru)}finally{if(z.current.delete(Ku),Ru===U.current&&A.current===C)x(!1)}})();z.current.set(Ku,hu),await hu}function HL(V){if(A.current!==V)return;let C=O.current.get(V)?.task;if(!C)return;if(pc(C,null))M8(null,{force:!0,incremental:!0}).catch((iu)=>Gf($l(iu,"增量刷新 Trace Steps 失败")));let d=Hf(C?._traceStepsLoadedByAttempt)||{};for(let iu of Object.keys(d).filter((Ju)=>d[Ju]))M8(iu,{force:!0,incremental:!0}).catch((Ju)=>Gf($l(Ju,"增量刷新 Attempt Trace Steps 失败")))}async function Vm(V,C,d){if(!i||!V)return;let iu=performance.now(),Ju=U.current,Ku=O.current.get(V);if(Ku?.task){if(o(Ku.task),x(X_(Ku.task)||!Ku.complete),!X_(Ku.task)&&Ku.complete&&Cr(Ku.task)&&String(Ku.completeUpdatedAt||"")===String(Ku.task?.updatedAt||"")){gr({phase:"complete",taskId:V,queueMs:d??0,detailMs:0,totalMs:C===void 0?0:performance.now()-C,chunks:0,transcriptRows:Array.isArray(Ku.task.transcript)?Ku.task.transcript.length:0,completedAt:new Date});return}}else x(!0);let wu=J.current;if(wu?.taskId===V&&wu.token===Ju)return wu.promise;let Ru=(async()=>{try{let hu=await Rf(xf(l,`/api/tasks/${encodeURIComponent(V)}?meta=1`));if(Ju!==U.current||A.current!==V)return;let Pu=O.current.get(V),xu=Array.isArray(Pu?.task?.transcript)?Pu.task.transcript:[],jf=hu?.task||{},rl=Boolean(Pu?.complete)&&String(Pu?.completeUpdatedAt||"")===String(jf?.updatedAt||"");q0(V,{...jf,summaryOnly:!1,_metaLoaded:!0,transcript:xu,_detailLoaded:xu.length>0,_transcriptComplete:rl},Ju);let du=X_(Pu?.task)||Boolean(Pu?.task?._transcriptPreview),ef=du?0:xu.length>0?oU(xu):0,I0=!du&&Pu?.complete&&Cr(jf)&&String(Pu?.completeUpdatedAt||"")===String(jf?.updatedAt||"")?M3(xu):ef,g0=!0,s0=0,o1=xu.length;while(g0){let nl=await Rf(xf(l,`/api/tasks/${encodeURIComponent(V)}/transcript?afterSeq=${encodeURIComponent(String(I0))}&limit=${pT}&fullText=1`));if(Ju!==U.current||A.current!==V)return;let N0=O.current.get(V),d$=Array.isArray(N0?.task?.transcript)?N0.task.transcript:[],gf=Vc(d$,Array.isArray(nl?.transcript)?nl.transcript:[]);s0+=1,o1=gf.length;let e$=Boolean(!nl?.hasMore);if(q0(V,{status:nl?.status||jf.status,updatedAt:nl?.updatedAt||jf.updatedAt,transcript:gf,_detailLoaded:e$||gf.length>0,_transcriptComplete:e$,_transcriptPreview:du&&!e$},Ju),g0=Boolean(nl?.hasMore),I0=Number(nl?.nextAfterSeq??M3(gf)),!g0)break;await new Promise((d1)=>window.setTimeout(d1,0))}gr({phase:"complete",taskId:V,queueMs:d??0,detailMs:performance.now()-iu,totalMs:C===void 0?performance.now()-iu:performance.now()-C,chunks:s0,transcriptRows:o1,completedAt:new Date})}finally{if(J.current?.taskId===V&&J.current?.token===Ju)J.current=null;if(Ju===U.current&&A.current===V)x(!1)}})();J.current={taskId:V,token:Ju,promise:Ru},await Ru}async function ml(V=A.current,C=!0,d=Xu){if(!i)return;if(!C&&h.current)return;let iu=performance.now();if(C)h.current=!0;if(C)gr({phase:"loading",taskId:String(V||A.current||""),startedAt:new Date});let Ju=j.current+1;j.current=Ju;let Ku=String(V||A.current||""),wu=Ku?O.current.get(Ku):null,Ru=Array.isArray(wu?.task?.transcript)?wu.task.transcript:[],hu=oU(Ru),Pu=null;if(Pu=await dT(l,Ku,hu,d),Ju!==j.current){if(C)h.current=!1;return}let xu=performance.now()-iu;v(Y||{});let jf=Pu?.queue||{},rl=String(jf?.activeTaskId||Y_(jf)[0]||""),du=Pu;Ur((el)=>{let Ey=tl(Pu),dn=tl(el),Zy=dn.length>0?Pi([dn,Ey],rl):Pi([Ey],rl),ut=s1(Zy),rK=Kn(Pu),ft=Kn(el),nK=dn.length>Ey.length&&(ft.hasMore===!1||String(ft.nextBeforeId||"").length>0),iK={...rK,...nK?{hasMore:ft.hasMore,nextBeforeId:ft.nextBeforeId}:{},returned:ut.length};return du={...Pu,tasks:ut,pagination:iK},du});let ef=tl(du),I0=RU(jf,Tu),g0=xU(jf,I0,d,ef),s0=aT(I0,d,ef),o1=Ku||A.current,nl=du?.selected||null,N0=nl?.task||null,d$=Array.isArray(nl?.transcript)?nl.transcript:null,gf=o1||g0||s0||ef[0]?.id||"";if(A.current!==gf)U.current+=1;A.current=gf,I(gf);let d1=ef.find((el)=>el.id===gf);if(d1){let el=O.current.get(gf);if(el?.task)O.current.set(gf,{...el,task:{...d1,...el.task,status:d1.status,updatedAt:d1.updatedAt}})}if(N0?.id===gf&&d$!==null){let el=O.current.get(gf),Ey=Array.isArray(el?.task?.transcript)?el.task.transcript:[],dn=Vc(Ey,d$),Zy=Boolean(nl?.preview);if(q0(gf,{...N0,_summaryLoaded:!0,transcript:dn,_detailLoaded:!nl?.hasMore||dn.length>0,_transcriptComplete:!Zy&&!nl?.hasMore&&Cr(N0),_transcriptPreview:Zy},U.current),x(!1),C)gr({phase:"complete",taskId:gf,queueMs:xu,detailMs:Math.max(0,performance.now()-iu-xu),totalMs:performance.now()-iu,chunks:1,transcriptRows:dn.length,partial:Boolean(Zy||nl?.hasMore||X_(N0)),completedAt:new Date});if(h$(new Date),C)h.current=!1;a1(gf,!1,C?iu:void 0,C?xu:void 0).catch((ut)=>Gf($l(ut,"加载 Codex Trace Summary 失败")));return}if(C)gr({phase:"session",taskId:gf,queueMs:xu,totalMs:xu,startedAt:new Date(Date.now()-xu)});if(gf)a1(gf,!0,C?iu:void 0,C?xu:void 0).catch((el)=>Gf($l(el,"加载 Codex Trace Summary 失败")));else if(U.current+=1,o(null),x(!1),C)gr({phase:"complete",taskId:"",queueMs:xu,detailMs:0,totalMs:performance.now()-iu,chunks:0,transcriptRows:0,completedAt:new Date});if(h$(new Date),C)h.current=!1}async function _7(){if(Sl){if(!i||P||L.current)return;let C=String(on.nextBeforeId||"");if(!C)return;L.current=!0,e(!0),Gf("");try{let d=await hU(l,Xu,C,uQ,k0),iu=tl(d),Ju=d?.queue||If||{},Ku=String(Ju?.activeTaskId||Y_(Ju)[0]||v1||"");ju((wu)=>{let Ru=s1(Pi([tl(wu),iu],Ku)),hu=Kn(d);return{...wu||{},queue:Ju,tasks:Ru,pagination:{...hu,returned:Ru.length}}})}catch(d){Gf($l(d,"加载更多搜索结果失败"))}finally{L.current=!1,e(!1)}return}if(!i||Ky||w.current)return;let V=String(Kn(T).nextBeforeId||"");if(!V)return;w.current=!0,b$(!0),Gf("");try{let C=await hU(l,Xu,V),d=tl(C),iu=C?.queue||If||{},Ju=String(iu?.activeTaskId||Y_(iu)[0]||v1||"");Ur((Ku)=>{let wu=s1(Pi([tl(Ku),d],Ju)),Ru=Kn(C);return{...Ku||{},queue:iu,statistics:C?.statistics||Ku?.statistics,tasks:wu,pagination:{...Ru,returned:wu.length}}})}catch(C){Gf($l(C,"加载更早 Codex tasks 失败"))}finally{w.current=!1,b$(!1)}}function BL(V){let C=V.currentTarget;if(!C||S8||!l7)return;if(C.scrollHeight-C.scrollTop-C.clientHeight<120)_7()}async function dl(V,C){ll(!0),Gf("");try{await V()}catch(d){Gf($l(d,C))}finally{ll(!1)}}async function C8(V){if(!V)return;try{let C=!1;try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(V),C=!0}catch{C=!1}if(!C){let iu=document.createElement("textarea");iu.value=V,iu.style.position="fixed",iu.style.opacity="0",document.body.appendChild(iu),iu.select(),C=document.execCommand("copy"),document.body.removeChild(iu)}if(!C)throw Error("browser clipboard rejected the copy request");C$(V);let d=`已复制任务 ID:${V}`;kf(d),ol("success",d),window.setTimeout(()=>C$((iu)=>iu===V?"":iu),1600)}catch(C){Gf(`复制任务 ID 失败:${$l(C)}`)}}function R8(V){if(!V)return;Qu(V);let C=`已引用任务 ID:${V};提交时后端会读取并注入该任务上下文`;kf(C),ol("success",C)}async function x8(V){if(!i||!V)return;let C=new Date().toISOString();j.current+=1,o$([V],C,null,{id:V,readAt:C,terminalUnread:!1}),R$(V);let d=!1;if(await dl(async()=>{let iu=await rE(l,V),Ju=iu?.task||{id:V,readAt:new Date().toISOString(),terminalUnread:!1},Ku=String(Ju?.readAt||new Date().toISOString());o$([V],Ku,iu?.queue||null,Ju),d=!0;let wu=`已将任务 ${V} 标为已读`;kf(wu),ol("success",wu)},"标记 Codex task 已读失败"),!d)y7([V]),ml(A.current,!1).catch((iu)=>Gf($l(iu,"刷新 Codex tasks 失败")));R$((iu)=>iu===V?"":iu)}async function VL(){if(!i||h1)return;Ly(!0);let V=new Date().toISOString(),C=Array.from(new Set([...tl(p.current).filter(V0).map((iu)=>String(iu?.id||"")).filter(Boolean),...Array.from(O.current.entries()).filter(([,iu])=>V0(iu?.task)).map(([iu])=>iu)]));if(j.current+=1,C.length>0)o$(C,V);let d=!1;if(await dl(async()=>{let iu=await nE(l),Ju=String(iu?.readAt||new Date().toISOString()),Ku=tl(p.current).filter(V0).map((xu)=>String(xu?.id||"")).filter(Boolean),wu=Array.from(O.current.entries()).filter(([,xu])=>V0(xu?.task)).map(([xu])=>xu),Ru=Array.from(new Set([...C,...Ku,...wu]));o$(Ru,Ju,iu?.queue||null);let hu=Number(iu?.count||Ru.length);d=!0;let Pu=`已将 ${hu} 个已结束未读任务标为已读`;kf(Pu),ol("success",Pu)},"全部标为已读失败"),!d&&C.length>0)y7(C),ml(A.current,!1).catch((iu)=>Gf($l(iu,"刷新 Codex tasks 失败")));Ly(!1)}function DL(V){let C=V||Tn;if(ff(C),!xl(C))Zu(C);if(Ur(null),!(xl(C)?A.current:""))A.current="",U.current+=1,I(""),o(null),x(!0)}async function XL(){let V=typeof window>"u"?"":window.prompt("输入新的 Codex queue ID(字母/数字/._-,最长 64)","new-lane"),C=String(V||"").trim();if(!C)return;await dl(async()=>{let d=await Rf(xf(l,"/api/queues"),{method:"POST",body:{queueId:C}}),iu=String(d?.queue?.id||C);Zu(iu),ff(iu),Ur(null),A.current="",U.current+=1,I(""),o(null);let Ju=`已创建并切换到 queue:${iu}`;kf(Ju),ol("success",Ju),await ml("",!0,iu)},"创建 Codex queue 失败")}async function YL(){let V=String(Tu||"default").trim()||"default",C=Ri(Br,V)||{id:V,name:V},d=typeof window>"u"?null:window.prompt(`输入 queue 显示名称(ID 不变:${V};留空恢复为 ID)`,nQ(C));if(d===null)return;await dl(async()=>{let iu=await Rf(xf(l,`/api/queues/${encodeURIComponent(V)}`),{method:"PATCH",body:{name:String(d)}}),Ju=iu?.queue||{id:V,name:String(d||V)};if(iu?.summary)Ur((wu)=>wu?{...wu,queue:iu.summary}:wu);let Ku=`已更新 queue 名称:${Sc(Ju)}`;kf(Ku),ol("success",Ku),await ml(A.current,!0,Xu)},"修改 Codex queue 名称失败")}function SL(){if(an.length===0){kf("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let V=an.some((C)=>String(C?.id||"")===mf)?mf:"";Yl(V),Jf(!0)}async function mL(){let V=sn;if(an.length===0){kf("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let d=String(mf||""||"").trim();if(!d){kf("请先选择要合并的源 queue。");return}if(d===V){Gf("源 queue 和目标 queue 不能相同。");return}await dl(async()=>{let iu=await Rf(xf(l,`/api/queues/${encodeURIComponent(V)}/merge`),{method:"POST",body:{sourceQueueId:d}});if(iu?.summary)Ur((wu)=>wu?{...wu,queue:iu.summary}:wu);Zu(V),ff(V),Ur(null);let Ju=Number(iu?.mergedTaskCount||0),Ku=`已将 queue=${d} 合并到 ${V},移动 ${Ju} 个任务;源 queue 已自动删除。`;kf(Ku),ol("success",Ku),Jf(!1),Yl(""),await ml(A.current,!0,V)},"合并 Codex queue 失败")}async function pL(V){if(V.preventDefault(),Q.current){kf("任务正在提交中,请等待当前请求完成,已阻止重复提交。");return}if(Q0.length>1&&!zl){Gf(`检测到将创建 ${Q0.length} 个任务;请先勾选“确认批量入队”,避免误传多个任务。`);return}Q.current=!0,Ir(!0),kf("正在提交 Code Queue 任务,请等待后端确认,输入已临时锁定。"),await dl(async()=>{if(Q0.length===0)throw Error("prompt 不能为空");let C=W1(g),d=Tu.trim()||"default",iu=[...Q0],Ju=(xu)=>({prompt:xu,queueId:d,providerId:Al,model:Hr,cwd:Au,maxAttempts:Number(Kl),...C.length>0?{referenceTaskIds:C}:{}}),Ku=iu.length===1?Ju(iu[0]):{tasks:iu.map(Ju)},wu=await Rf(xf(l,iu.length===1?"/api/tasks":"/api/tasks/batch"),{method:"POST",body:Ku}),Ru=wu?.tasks?.[0]?.id||"",hu=Array.isArray(wu?.tasks)?wu.tasks.map((xu)=>String(xu?.id||"")).filter(Boolean):[],Pu=`已创建 ${hu.length||iu.length} 个任务${hu.length>0?`:${hu.join(" / ")}`:""}`;if(kf(Pu),ol("success",Pu),Wu(""),Qu(""),Pf(!1),A.current=Ru,Xu!==d)Ur(null);Zu(d),await ml(Ru,!0,d)},"Codex 任务入队失败"),Q.current=!1,Ir(!1)}async function PL(V){if(V.preventDefault(),!b?.id)return;await dl(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/steer`),{method:"POST",body:{prompt:Fr}}),x1(""),await ml(b.id)},"追加 prompt 失败")}async function ML(V){V.preventDefault();let C=String(b?.id||"");if(!C||!g1)return;await dl(async()=>{let d=W1(lu),iu=await Rf(xf(l,`/api/tasks/${encodeURIComponent(C)}/edit`),{method:"POST",body:{prompt:gn,referenceTaskIds:d}}),Ju={...iu?.task||b||{},_traceSummary:null,_traceSummaryLoaded:!1,_traceSummaryUpdatedAt:"",_promptDetails:{},_traceSteps:[],_traceStepsLoaded:!1,_traceStepsByAttempt:{},_traceStepsLoadedByAttempt:{},_traceStepsNextAfterSeqByAttempt:{},_traceStepDetails:{}};O.current.set(C,{...O.current.get(C)||{},task:Ju,complete:!1,completeUpdatedAt:""}),A.current=C,o(Ju),I(C),b0(C3(Ju)),Ou(Array.isArray(Ju?.referenceTaskIds)?Ju.referenceTaskIds.join(" "):""),Ur((wu)=>{if(!wu)return wu;let Ru=tl(wu).map((hu)=>String(hu?.id||"")===C?{...hu,...Ju}:hu);return{...wu,queue:iu?.queue||wu.queue,tasks:Pi([Ru],v1)}});let Ku=iu?.changed===!1?`任务 ${C} 的 prompt 未变化`:`已更新 queued 任务 ${C} 的用户 prompt`;kf(Ku),ol("success",Ku),await ml(C,!0,Xu)},"编辑 queued 任务 prompt 失败")}async function CL(){if(!b?.id)return;await dl(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/interrupt`),{method:"POST",body:{}}),await ml(b.id)},"打断 Codex session 失败")}async function RL(){if(!b?.id)return;await dl(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/retry`),{method:"POST",body:{}}),await ml(b.id)},"重新入队失败")}async function xL(V){let C=String(b?.id||""),d=String(V||"").trim();if(!C||!d)return;let iu=m_(b);if(d===iu){kf(`任务 ${C} 已在 queue=${d}`);return}await dl(async()=>{let Ku=(await Rf(xf(l,`/api/tasks/${encodeURIComponent(C)}/move`),{method:"POST",body:{queueId:d}}))?.task||{...b,queueId:d};if(O.current.set(C,{...O.current.get(C)||{},task:Ku}),A.current=C,o(Ku),I(C),Zu(d),!xl(Xu))Ur(null),ff(d);let wu=`已将任务 ${C} 从 ${iu} 移动到 ${d}`;kf(wu),ol("success",wu),await ml(C,!0,xl(Xu)?Tn:d)},"移动任务 queue 失败")}async function hL(){let V=A.current;if(!V)return;let C=performance.now();await dl(async()=>{gr({phase:"session",taskId:V,queueMs:0,totalMs:0,partial:!0,startedAt:new Date}),await a1(V,!0,C,0)},"刷新 Trace Summary 失败")}function bL(V){A.current=V,U.current+=1,I(V);let C=O.current.get(V);if(C?.task)o(C.task),x(!1);else{x(!0);let d=sr.find((iu)=>iu.id===V);if(d)o(d);else o(null)}ml(V).catch((d)=>Gf($l(d,"切换 Codex session 失败")))}function h8(V){if(bL(V),IT())vf(!1)}function $7(V,C,d){if(!V||!Array.isArray(V?.tasks)||C.length===0||Object.keys(d).length===0)return V;let iu=!1,Ju=tl(V).map((Ku)=>{if(String(Ku?.id||"")!==C)return Ku;return iu=!0,a$(aU(Ku,d))});return iu?{...V,tasks:Ju}:V}function vL(V,C){Ur((d)=>$7(d,V,C)),ju((d)=>$7(d,V,C))}function kL(V,C,d){let iu=String(V?.type||"");if(iu==="queue-updated")return!0;if(iu==="trace-stats-updated"||iu==="trace-step-created")return!1;if(C.length===0)return!0;if(!d)return!0;if(V?.queueId&&String(V.queueId)!==m_(d))return!0;if(V?.status&&String(V.status)!==String(d?.status||""))return!0;return String(V?.reason||"")!=="output"}function t7(){if(!i||!Zc())return;if(H.current!==null)window.clearTimeout(H.current);H.current=window.setTimeout(()=>{H.current=null,ml(A.current,!1).catch((V)=>Gf($l(V,"Code Queue 事件刷新失败")))},120)}function IL(V,C){if(!i||!Zc()||A.current!==V)return;if(D.current=D.current||C,E.current!==null)return;E.current=window.setTimeout(()=>{E.current=null;let d=D.current;if(D.current=!1,a1(V,!0).catch((iu)=>Gf($l(iu,"事件刷新 Trace Summary 失败"))),d)HL(V)},250)}function gL(V){let C=Hf(V?.payload)||V,d=Hf(C?.stats),iu=String(V?.type||C?.type||""),Ju=String(C?.subjectKind||d?.subjectKind||""),Ku=String(C?.scopeId||d?.scopeId||""),wu=String(C?.taskId||(Ju==="task"?C?.subjectId:"")||d?.taskId||V?.taskId||""),Ru=C?.attemptIndex??d?.attemptIndex,hu=Ru===null||Ru===void 0||Ru===""?null:D0(Ru),Pu=d||Hf(C?.traceStats),xu=Pu?.stepCount??Pu?.llmStepCount,jf=Pu?.outputMaxSeq;return{...C,type:iu,eventId:V?.eventId||C?.eventId,sequence:V?.sequence??C?.sequence,taskId:wu,subjectKind:Ju,scopeId:Ku,attemptIndex:hu,stepCount:xu,outputMaxSeq:jf,updatedAt:Pu?.updatedAt||C?.updatedAt||V?.createdAt,traceStats:Pu,statsSource:Pu?"oa-event-flow":C?.statsSource}}function sL(V){let C=gL(V),d=String(C?.taskId||""),iu=String(C?.scopeId||C?.traceStats?.scopeId||""),Ju=String(C?.subjectKind||C?.traceStats?.subjectKind||"")==="task-attempt"||Number(C?.attemptIndex)>0||/:attempt:\d+$/u.test(iu),Ku=vU(C?.stepCount),wu={},Ru=d.length>0?tl(p.current).find((hu)=>String(hu?.id||"")===d):null;if(d.length>0){if(C?.status)wu.status=String(C.status);if(C?.updatedAt)wu.updatedAt=String(C.updatedAt);if(C?.queueId)wu.queueId=String(C.queueId);if(!Ju&&Number.isFinite(Number(C?.stepCount)))wu.stepCount=Ku,wu.llmStepCount=Ku;if(!Ju&&Number.isFinite(Number(C?.outputMaxSeq)))wu.outputMaxSeq=vU(C.outputMaxSeq);if(!Ju&&Hf(C?.traceStats))wu.traceStats=C.traceStats,wu.statsSource="oa-event-flow";if(Object.keys(wu).length>0&&(O.current.has(d)||A.current===d))q0(d,wu,U.current);if(Object.keys(wu).length>0)vL(d,wu);if(A.current===d&&(C?.type==="trace-step-created"||C?.type==="task-updated"||C?.type==="trace-stats-updated")){let hu=$Q(Ru),Pu=C?.type==="trace-step-created"||C?.type==="trace-stats-updated"&&!Ju&&Number.isFinite(Number(C?.stepCount))&&(hu===null||Ku>hu);IL(d,Pu)}}if(kL(C,d,Ru))t7()}Gn(()=>{if(B.current){B.current=!1;return}dl(()=>ml(A.current),"Code Queue 加载失败")},[i?.id,Xu]),Gn(()=>{if(!i||typeof EventSource>"u")return;let V=new EventSource(xT(l),{withCredentials:!0}),C=(iu)=>{try{sL(JSON.parse(String(iu.data||"{}")))}catch(Ju){Gf($l(Ju,"解析 Code Queue 事件失败"))}},d=()=>{if(Zc())t7()};return V.addEventListener("trace-step-created",C),V.addEventListener("task-updated",C),V.addEventListener("queue-updated",C),V.addEventListener("trace-stats-updated",C),document.addEventListener("visibilitychange",d),()=>{if(V.close(),document.removeEventListener("visibilitychange",d),H.current!==null)window.clearTimeout(H.current),H.current=null;if(E.current!==null)window.clearTimeout(E.current),E.current=null}},[i?.id,l,Xu]),Gn(()=>{if(!i||!b||s)return;let V=String(b.id||"");if(!V)return;let C=String(b.updatedAt||"");if(p3(b))return;let d=`${V}:${C||"unknown"}:${String(b?._traceSummaryUpdatedAt||"")}`;if(Z.current.has(d))return;Z.current.add(d),a1(V,!0).catch((iu)=>Gf($l(iu,"自动加载 Trace Summary 失败")))},[i?.id,b?.id,b?.updatedAt,b?.traceStats?.statsRevision,b?._traceSummaryUpdatedAt,b?._traceSummaryLoaded,s]);let aL=Jr.length===0?K(G1,{title:Sl?Gu?"搜索中":"没有匹配任务":"队列为空",text:Sl?Gu?`正在搜索包含“${k0}”的 task...`:`未找到包含“${k0}”的 task;可换个关键词或切换 queue。`:"提交一个任务后,Codex 会串行执行并保存输出。"}):[g$.length>0?K(Dc,{key:"unread",title:"已结束未读",tasks:g$,selectedId:k,emptyText:"暂无已结束未读任务。",onSelect:h8,onCopy:C8,onReference:R8,onMarkRead:x8,copiedTaskId:Wy,markingReadTaskId:wy}):null,K(Dc,{key:"active",title:"运行 / 排队",tasks:s$,selectedId:k,emptyText:"当前没有运行或排队任务。",onSelect:h8,onCopy:C8,onReference:R8,onMarkRead:x8,copiedTaskId:Wy,markingReadTaskId:wy}),K(Dc,{key:"history",title:"历史 session",tasks:qL,selectedId:k,emptyText:"最近没有完成、失败或取消的 session。",onSelect:h8,onCopy:C8,onReference:R8,onMarkRead:x8,copiedTaskId:Wy,markingReadTaskId:wy}),K("div",{key:"pagination",className:"codex-task-pagination","data-testid":"codex-task-pagination"},K("span",null,Sl?`搜索“${k0}” · 已显示 ${Jr.length} / ${Number.isFinite(I1)?I1:Jr.length}`:`已加载 ${Jr.length} / ${Number.isFinite(I1)?I1:Jr.length}`),l7?K("button",{type:"button",className:"ghost-btn",disabled:S8,onClick:()=>void _7(),"data-testid":"codex-load-more-tasks-button"},S8?"加载中":Sl?"加载更多结果":"加载更早任务"):K("code",null,Sl?"已到结果末尾":"已到队列末尾"))],c7=(V,C=!1)=>K("label",{className:`code-queue-switcher ${C?"compact":""}`},K("span",null,C?"Queue":"查看 queue"),K("select",{value:Xu,onChange:(d)=>DL(String(d.target.value||Tn)),"data-testid":V},K("option",{value:Tn},`All queues · ${Number.isFinite(v0)?v0:sr.length} tasks · ${zy.length} running`),Br.map((d)=>K("option",{key:String(d?.id||""),value:String(d?.id||"")},S_(d))))),oL=K("div",{className:"codex-task-search","data-testid":"codex-task-search"},K("label",{htmlFor:"codex-task-search-input"},"搜索 task"),K("div",{className:"codex-task-search-row"},K("input",{id:"codex-task-search-input",type:"search",value:fu,placeholder:"关键词 / task ID / prompt",autoComplete:"off",onChange:(V)=>$u(String(V.target.value||"")),"data-testid":"codex-task-search-input"}),fu?K("button",{type:"button",className:"ghost-btn",onClick:()=>$u(""),"data-testid":"codex-task-search-clear"},"清除"):null),K("small",{"data-testid":"codex-task-search-summary"},Sl?Gu?"搜索中...":`匹配 ${Jr.length}/${Number.isFinite(I1)?I1:Jr.length}`:"支持 task ID、prompt、状态、provider、模型和最近输出关键词")),dL=K("div",{className:"codex-trace-status","data-testid":"codex-trace-status-summary"},K("span",{className:"codex-trace-status-chip queued"},K("b",null,"排队"),String(D8)),K("span",{className:"codex-trace-status-chip running"},K("b",null,"运行"),String(X8)),K("span",{className:`codex-trace-status-chip unread ${U0>0?"warn":""}`},K("b",null,"结束未读"),String(U0)),K("span",{className:"codex-trace-status-chip service"},K("b",null,"服务"),`${NL.providerStatus||"unknown"} · ${i?.providerId||"main-server"} · ${WL.public?"公网暴露":"仅 UniDesk frontend 代理访问"}`),K("span",{className:"codex-trace-status-chip"},K("b",null,"执行节点"),i7.map((V)=>V.id).join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"模型"),n7.join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"加载"),Tl?.phase==="complete"?MT(Tl?.totalMs):String(Tl?.phase||"idle")),K("span",{className:"codex-trace-status-chip"},K("b",null,"刷新"),x$?$f(x$):"--")),eL=K(Mi,{title:b?`Trace ${String(b.id).slice(0,22)}`:"Trace 输出",eyebrow:b?`${b.status} / view=${k1} / task queue=${m_(b)} / provider=${b.providerId||"main-server"} / ${b.model} / agent loop trace`:`Agent loop trace / view=${k1}`,summary:dL,loading:s||Ky||Gu||P||Tl?.phase==="loading",actions:K("div",{className:"panel-actions"},c7("code-queue-filter-select"),K("button",{type:"button",className:"ghost-btn codex-mark-all-read-btn",disabled:U0===0||pu||h1,onClick:()=>void VL(),"data-testid":"codex-mark-all-read-button"},h1?"标记中":`全部标已读${U0>0?` (${U0})`:""}`),b?K("button",{type:"button",className:"ghost-btn",disabled:s||pu,onClick:()=>void hL(),"data-testid":"codex-load-full-trace-button"},s?"加载中":_r(b)?"刷新 Summary":"加载 Summary"):null,K("button",{type:"button",className:"codex-session-title-toggle",onClick:()=>vf((V)=>!V),"data-testid":"code-queue-sidebar-toggle"},Af?"收起队列":"展开队列"),K("label",{className:"inline-check"},K("input",{type:"checkbox",checked:mu,onChange:(V)=>ou(Boolean(V.target.checked))}),"自动滚动"),K("button",{type:"button",className:"ghost-btn",disabled:!KL||pu,onClick:()=>void CL(),"data-testid":"codex-interrupt-button"},"打断"),K("button",{type:"button",className:"ghost-btn",disabled:!GL||pu,onClick:()=>void RL()},"重试"),b?K(rQ,{title:"Codex Task",data:b,onOpen:f,testId:"raw-codex-task"}):null),className:"codex-output-panel"},K("div",{className:`codex-session-shell ${Af?"":"queue-collapsed"}`},Af?K("aside",{className:"codex-session-sidebar","data-testid":"codex-session-sidebar"},K("div",{className:"codex-session-sidebar-head"},K("div",null,K("span",null,xl(Xu)?"All queues":"Queue lane"),K("strong",null,`${k1} · ${sr.length}/${Number.isFinite(v0)?v0:sr.length} sessions · 未读 ${U0}`)),K("button",{type:"button",className:"ghost-btn",onClick:()=>vf(!1)},"收起")),c7("code-queue-filter-sidebar",!0),oL,K("div",{className:"codex-task-list codex-task-list-session",onScroll:BL,"data-testid":"codex-task-list-scroll"},aL)):null,K("div",{className:"codex-session-main"},K("div",{className:"codex-output-stack"},K(fZ,{task:b,loading:s,onLoadPromptPart:ZL,onLoadSteps:M8,onLoadStep:OL}),K(lZ,{task:b})))));if(!i)return K(G1,{title:"Code Queue 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=code-queue"});let A7=Number(Tl?.totalMs),j7=Number(Tl?.queueMs),F7=Number(Tl?.detailMs),J7=Number(Tl?.transcriptRows),uK=Tl?.phase==="complete"?"complete":String(Tl?.phase||"idle"),fK=Ri(Br,sn)||{id:sn,name:sn},lK=_f?K(pU,{title:"合并 queue",titleId:"codex-merge-dialog-title",className:"codex-merge-dialog",backdropClassName:"codex-merge-dialog-backdrop",bodyClassName:"codex-merge-dialog-body",actionsClassName:"codex-merge-dialog-actions",testId:"codex-merge-queue-dialog",closeTestId:"codex-merge-queue-close",disableClose:pu,onClose:()=>Jf(!1),actions:[K("button",{key:"cancel",type:"button",className:"ghost-btn",onClick:()=>Jf(!1),disabled:pu,"data-testid":"codex-merge-queue-cancel"},"取消"),K("button",{key:"confirm",type:"button",className:"primary-btn",onClick:()=>void mL(),disabled:pu||rf||!mf,"data-testid":"codex-merge-queue-confirm"},pu?"合并中...":"确认合并")]},K("p",{className:"codex-merge-dialog-target"},"目标 queue:",K("code",null,S_(fK))),K("label",null,"源 queue",K("select",{value:mf,disabled:pu||rf,onChange:(V)=>Yl(String(V.target.value||"")),"data-testid":"codex-merge-source-queue-select"},K("option",{value:""},"选择要合并进来的源 queue"),an.map((V)=>K("option",{key:String(V?.id||""),value:String(V?.id||"")},S_(V))))),K("p",{className:"codex-merge-dialog-note"},"会把源 queue 的任务归属合并到目标 queue,并自动删除源 queue;目标 queue 会按原 queueEnteredAt/createdAt 时间顺序运行。")):null;return K("div",{className:`code-queue-page ${n?"codex-standalone-page":""}`,"data-testid":"code-queue-page","data-load-state":uK,"data-load-total-ms":Number.isFinite(A7)?String(Math.round(A7*10)/10):"","data-load-queue-ms":Number.isFinite(j7)?String(Math.round(j7*10)/10):"","data-load-detail-ms":Number.isFinite(F7)?String(Math.round(F7*10)/10):"","data-load-transcript-rows":Number.isFinite(J7)?String(J7):"","data-load-task-id":String(Tl?.taskId||k||""),"data-load-partial":Tl?.partial?"true":"false"},K(yf,{error:J0,wide:!0}),lK,K("div",{className:"codex-session-stage codex-session-stage-top"},eL),K("div",{className:"code-queue-layout"},K("div",{className:"codex-left-rail"},K(Mi,{title:"提交任务",eyebrow:rf?"Submitting...":Q0.length>1?`${Q0.length} tasks`:"Single or Batch",className:"codex-compose-panel",loading:rf},K("form",{className:`codex-task-form ${rf?"is-submitting":""}`,onSubmit:pL,"data-testid":"code-queue-task-form","aria-busy":rf?"true":"false"},K("label",null,"Prompt / 多任务用单独一行 --- 分隔",K("textarea",{value:uu,rows:8,disabled:rf,onChange:(V)=>Wu(V.target.value),placeholder:"写入 Codex 任务;多个任务之间用 --- 分隔。"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选)",K("input",{value:g,disabled:rf,onChange:(V)=>Qu(V.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-reference-task-id"}),W1(g).length>0?K("code",null,`后端将解析并注入:${W1(g).join(" / ")}`):null),K("div",{className:"codex-form-grid"},K("label",{className:"codex-submit-queue-field"},"Queue",K("div",{className:"codex-submit-queue-row"},K("select",{className:"codex-submit-queue-select",value:Tu,disabled:rf,onChange:(V)=>Zu(String(V.target.value||"default")),"data-testid":"code-queue-id-select"},Br.map((V)=>K("option",{key:String(V?.id||""),value:String(V?.id||"")},S_(V)))),K("button",{type:"button",className:"ghost-btn codex-rename-queue-btn",onClick:()=>void YL(),disabled:pu||rf||!Tu,title:"修改当前 queue 的显示名称,ID 不变","data-testid":"codex-rename-queue-button"},"改名"),K("button",{type:"button",className:"ghost-btn codex-merge-queue-btn",onClick:()=>SL(),disabled:pu||rf||an.length===0,title:"打开独立窗口选择源 queue 并合并到当前 queue;合并后自动删除源 queue","data-testid":"codex-merge-queue-button"},"合并 queue"),K("button",{type:"button",className:"ghost-btn codex-create-queue-btn",onClick:()=>void XL(),disabled:pu||rf,"data-testid":"codex-create-queue-button"},"创建 queue"))),K("label",null,"模型",K("select",{value:Hr,disabled:rf,onChange:(V)=>al(V.target.value),"data-testid":"codex-model-select"},n7.map((V)=>K("option",{key:V,value:V},V)))),K("label",null,"执行 Provider",K("select",{value:Al,disabled:rf,onChange:(V)=>EL(String(V.target.value||"main-server")),"data-testid":"codex-provider-select"},i7.map((V)=>K("option",{key:V.id,value:V.id},`${V.label||V.id} · ${V.defaultWorkdir||R3(If,V.id)}`)))),K("label",null,"工作目录",K("input",{value:Au,disabled:rf,onChange:(V)=>vu(V.target.value),placeholder:LL||If?.defaultWorkdir||"/root/unidesk","data-testid":"codex-cwd-input"})),K("label",null,"最大尝试",K("input",{type:"number",min:1,max:99,value:Kl,disabled:rf,onChange:(V)=>Su(Number(V.target.value)),"data-testid":"codex-max-attempts-input"})),K("label",null,"入队份数",K("input",{type:"number",min:1,max:50,value:pf,disabled:rf,onChange:(V)=>Gl(Number(V.target.value)),"data-testid":"codex-repeat-count-input"}))),Ty>1?K("label",{className:`codex-batch-confirm ${zl?"confirmed":""}`,"data-testid":"codex-batch-confirm-row"},K("input",{type:"checkbox",checked:zl,disabled:rf,onChange:(V)=>Pf(Boolean(V.target.checked)),"data-testid":"codex-batch-confirm-checkbox"}),K("span",null,`确认批量入队 ${Ty} 个任务(prompt 分段 ${m8.length} × 入队份数 ${bU(pf)})`)):null,rf?K("div",{className:"codex-submit-wait","data-testid":"codex-submit-wait"},"正在提交到后端,已锁定输入以防重复提交..."):null,K("div",{className:"codex-form-actions"},K("button",{type:"button",className:"ghost-btn",disabled:pu||rf||uu.length===0&&g.length===0,onClick:()=>{Wu(""),Qu(""),Pf(!1);let V="已清空任务输入栏";kf(V),ol("success",V)},"data-testid":"codex-clear-input-button"},"清空输入"),K("button",{type:"submit",className:"primary-btn",disabled:wL,"data-testid":"codex-enqueue-button"},rf?"提交中,请等待...":r7?`请确认批量入队 ${Ty} 个任务`:Q0.length>1?`批量入队 ${Q0.length} 个任务`:"入队并运行"))))),K("div",{className:"codex-main-stage"},K("div",{className:"codex-detail-grid"},K(Mi,{title:"运行控制",eyebrow:g1?"Queued prompt editable":p8?"Active turn steer":"Steer when running",loading:pu},K("div",{className:"codex-run-control-stack"},K(aE,{task:b,queueRows:Br,busy:pu,onMove:xL}),b?.id?K("form",{className:"codex-steer-form codex-edit-prompt-form",onSubmit:ML,"data-testid":"codex-edit-prompt-form"},K("label",null,"编辑 queued 用户 prompt",K("textarea",{value:gn,rows:5,onChange:(V)=>b0(V.target.value),placeholder:"仅 QUEUED 且尚未开始运行的任务可在这里修改原始用户 prompt。",disabled:!g1||pu,"data-testid":"codex-edit-prompt-textarea"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选,留空会清除引用)",K("input",{value:lu,disabled:!g1||pu,onChange:(V)=>Ou(V.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-edit-reference-task-id"}),W1(lu).length>0?K("code",null,`将保留/注入:${W1(lu).join(" / ")}`):null),K("div",{className:"codex-form-actions"},K("button",{type:"button",className:"ghost-btn",disabled:!b?.id||pu,onClick:()=>{b0(b?C3(b):""),Ou(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},"data-testid":"codex-edit-prompt-reset"},"恢复当前值"),K("button",{type:"submit",className:"primary-btn",disabled:!g1||pu||gn.trim().length===0,title:g1?"保存后会重写尚未运行任务的用户 prompt":"只有 QUEUED 且尚未开始的任务可编辑 prompt","data-testid":"codex-edit-prompt-submit"},"保存 queued prompt"))):null,K("form",{className:"codex-steer-form",onSubmit:PL},K("label",null,"追加 prompt",K("textarea",{value:Fr,rows:4,onChange:(V)=>x1(V.target.value),placeholder:"给正在运行的 Codex session 推入新的指令或纠偏。",disabled:!p8})),K("button",{type:"submit",className:"primary-btn",disabled:!p8||pu||Fr.trim().length===0,"data-testid":"codex-steer-button"},"推入运行中 session")))),K(Mi,{title:"完成判定",eyebrow:b?.lastJudge?b.lastJudge.source:"judge",loading:s},b?.lastJudge?K("div",{className:"codex-judge-card","data-testid":"codex-task-judge-card"},K(K1,{status:b.lastJudge.decision},b.lastJudge.decision),K("strong",null,`${Math.round(Number(b.lastJudge.confidence||0)*100)}% confidence`),K("p",{"data-testid":"codex-task-judge-reason"},Xc(b.lastJudge.reason||"--",180)),b.lastJudge.continuePrompt?K("code",{"data-testid":"codex-task-judge-continue-prompt"},Xc(b.lastJudge.continuePrompt,160)):null):K(G1,{title:"尚未判定",text:"Codex turn 结束后会由 MiniMax M2.7 或 fallback judge 判定 complete/retry/fail;retry 会在已有 thread 追加继续执行 prompt。"}))),K(sE,{stats:V8,queueName:k1,onRaw:f}),K(Mi,{title:"Attempts",eyebrow:"terminal vs interruption",loading:s},K(rZ,{task:b})))))}var M_=Mu(Qf(),1);var Bu=M_.default.createElement,{useEffect:kc}=M_.default,Ic=M_.default.useState,nZ=M_.default.useRef,sc=` +本次任务:`,r=f.indexOf(l);if(r===-1)return u;return f.slice(r+l.length).trimStart()}function W1(u){return u.length>0?u.split(/\r\n|\r|\n/u).length:0}function tQ(u){let f=String(u?.displayPrompt||"");if(f.length>0)return f;let l=String(u?.prompt||"");return NE(qE(l).userPrompt)}function cr(u){return u?._traceSummary&&typeof u._traceSummary==="object"&&!Array.isArray(u._traceSummary)?u._traceSummary:null}function xt(u){return u?._promptDetails&&typeof u._promptDetails==="object"&&!Array.isArray(u._promptDetails)?u._promptDetails:{}}function b5(u){let f=cr(u)?.prompt;return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function AQ(u){let f=cr(u)?.execution;return f&&typeof f==="object"&&!Array.isArray(f)?f:{}}function sU(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):0}function D0(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):null}function cQ(u){let f=Lf(u?.traceStats);if(f&&(u?.statsSource==="oa-event-flow"||f.source==="oa-event-flow"))return f;let l=cr(u),r=Lf(l?.traceStats);if(r&&(l?.statsSource==="oa-event-flow"||r.source==="oa-event-flow"))return r;return null}function WE(u,f){let l=Lf(f?.traceStats)||Lf(f?.execution?.traceStats),r=String(f?.statsSource||f?.execution?.statsSource||"");if(l&&(r==="oa-event-flow"||l.source==="oa-event-flow"))return l;return null}function LE(u,f){return D0(cQ(u)?.[f])}function jQ(u){let f=LE(u,"stepCount");if(f!==null)return f;let l=cr(u);if(l!==null)return wE(l);return null}function wE(u){let f=Lf(u?.traceStats);if(!f||u?.statsSource!=="oa-event-flow"&&f.source!=="oa-event-flow")return null;return D0(f.stepCount)}function Pt(u){if(!u||u?._traceSummaryLoaded!==!0)return!1;let f=cr(u),l=String(u?._traceSummaryUpdatedAt||f?.updatedAt||""),r=String(u?.updatedAt||"");if(r.length>0){let n=X0(l),i=X0(r);if(n!==null&&i!==null){if(n+10?l:tQ(u)}function FQ(u){let f=cr(u);return String(f?.finalResponse||u?.finalResponse||"").trimEnd()}function JQ(u){let l=cr(u)?.lastJudge||u?.lastJudge;return l&&typeof l==="object"&&!Array.isArray(l)?l:null}function Lf(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function KE(u){let f=Lf(u?.raw),l=Lf(u?.failureDetails)||Lf(f?.minimaxFailure);if(l===null)return"";let r=l.repairAttempt===void 0?"":`${l.repairAttempt}/${l.maxRepairAttempts??"?"}`;return[["provider",l.provider||"minimax"],["stage",l.stage],["model",l.model],["timedOut",l.timedOut],["durationMs",l.durationMs],["timeoutMs",l.timeoutMs],["promptChars",l.promptChars],["promptLines",l.promptLines],["payloadBytes",l.payloadBytes],["responseStatus",l.responseStatus],["repairAttempt",r],["errorName",l.errorName],["error",l.errorMessage],["responseContentPreview",l.responseContentPreview],["responseTextPreview",l.responseTextPreview]].filter(([,i])=>i!==void 0&&i!==null&&String(i).length>0).map(([i,y])=>`${i}: ${String(y)}`).join(` +`)}function UQ({judge:u,testId:f="codex-judge-failure-details"}){let l=KE(u);if(l.length===0)return null;return K("details",{className:"codex-judge-failure-details","data-testid":f},K("summary",null,"MiniMax failure details"),K("pre",null,l))}function GE(u){let f=cr(u)?.attempts;if(Array.isArray(f)&&f.length>0)return f;let l=AQ(u),r=FQ(u),n=JQ(u);if(Object.keys(l).length===0&&r.length===0&&n===null)return[];return[{index:Number(u?.currentAttempt||1),mode:u?.currentMode||"initial",startedAt:u?.startedAt,finishedAt:u?.finishedAt,terminalStatus:u?.status,execution:l,finalResponse:r,finalResponseChars:r.length,judge:n}]}function zE(u,f){return Lf(f?.execution)||AQ(u)}function TE(u,f,l,r){let n=cr(u),i=Number(n?.currentAttempt||u?.currentAttempt||0),y=Number(l),_=Number.isFinite(y)&&y>0&&y===i,$=yQ(u?.updatedAt,n?.updatedAt);if(_&&!f?.finishedAt&&$.length>0)return $;return String(f?.updatedAt||f?.finishedAt||r.effectiveEndAt||(_?$:"")||$||u?.finishedAt||u?.startedAt||"")}function EE(u,f){let l=String(f?.finalResponse||f?.finalResponsePreview||"");if(Object.prototype.hasOwnProperty.call(f||{},"finalResponse")||Object.prototype.hasOwnProperty.call(f||{},"finalResponsePreview"))return l.trimEnd();return l.length>0?l.trimEnd():FQ(u)}function QQ(u,f){if(Object.prototype.hasOwnProperty.call(f||{},"judge"))return Lf(f?.judge);return JQ(u)}function ZE(u,f,l){if(!hE(u))return!1;if(v5(f,l))return!1;if(f?.finishedAt)return!1;if(["succeeded","failed","canceled"].includes(String(f?.terminalStatus||"")))return!1;let r=cr(u),n=Number(r?.currentAttempt||u?.currentAttempt||0),i=Number(l);if(Number.isFinite(i)&&i>0&&Number.isFinite(n)&&n>0)return i===n;return!0}function qQ(u){return`feedback:${String(u||"latest")}`}function OE(u,f,l){let r=String(f?.feedbackPrompt||"").trimEnd(),n=String(f?.feedbackPromptPreview||r||"").trimEnd(),i=Number(f?.feedbackPromptChars||r.length||n.length||0),y=Number(f?.feedbackPromptLines||W1(r||n));if(r.length>0||n.length>0||i>0)return{text:r,preview:n,chars:i,lines:y,source:f?.feedbackPromptSource||"judge-feedback",forAttempt:f?.feedbackPromptForAttempt||Number(l||0)+1,truncated:Boolean(f?.feedbackPromptTruncated)};let _=QQ(u,f),$=String(_?.continuePrompt||"").trimEnd();if(_?.decision==="retry"&&$.length>0)return{text:"",preview:$,chars:$.length,lines:W1($),source:"judge-continue-prompt",forAttempt:Number(l||0)+1,truncated:!1};return null}function HE(u){let f=b5(u);return Boolean(f.hasReferenceInjection||Number(f.referencePromptChars||0)>0||u?.referenceInjection||u?.referenceInjectionSummary)}function NQ(u,f=null){if(f!==null&&f!==void 0){let r=(Lf(u?._traceStepsByAttempt)||{})[String(f)];return Array.isArray(r)?r:[]}return Array.isArray(u?._traceSteps)?u._traceSteps:[]}function m5(u){let l=[u?.seq,...Array.isArray(u?.rawSeqs)?u.rawSeqs:[]].map((r)=>Number(r)).filter((r)=>Number.isFinite(r));return l.length>0?Math.max(...l):0}function BE(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,m5(l)),0)}function VE(u,f){let l=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(f)?f:[]]){let n=String(r?.seq??`${r?.title||"step"}:${r?.at||""}`);l.set(n,{...l.get(n)||{},...r})}return Array.from(l.values()).sort((r,n)=>m5(r)-m5(n))}function xi(u){return(Array.isArray(u?.summaryLines)?u.summaryLines:[]).map((f)=>String(f||""))}function DE(u){let f=String(u?.kind||"").trim().toLowerCase(),l=String(u?.status||"").trim().toLowerCase();return f==="error"||l==="error"}function ht(u){let f=String(u?.status||"").trim();if(f.length>0)return f;let l=xi(u).join(` +`);return/^(item\/[A-Za-z]+(?:\/[A-Za-z]+)?):/u.exec(l)?.[1]||""}function aU(u){return/^item\/(?:started|completed): file changes status=/u.test(String(u||"").trim())}function XE(u){let f=xi(u);for(let r=f.length-1;r>=0;r-=1){let n=/file changes status=([A-Za-z0-9_-]+)/u.exec(f[r]||"")?.[1];if(n)return n}let l=ht(u);if(l==="item/fileChange/outputDelta")return"updated";if(l==="item/started")return"started";if(l==="item/completed")return"completed";return l.replace(/^item\//u,"")||String(u?.status||"changed")}function YE(u){if(String(u?.kind||"")!=="edited")return!1;let f=String(u?.title||""),l=String(u?.status||""),r=xi(u).join(` +`);if(f==="Edited files")return!0;if(/^item\/fileChange\//u.test(l))return!0;if((l==="item/started"||l==="item/completed")&&/file changes status=/u.test(r))return!0;if(/^Success\. Updated the following files:/mu.test(r))return!0;if(/^diff --git /mu.test(r))return!0;return/^([AMDRCU?]{1,2})\s+\S+/mu.test(r)}function SE(u){if(u.length<=1)return u[0];let f=u.find((i)=>ht(i)==="item/fileChange/outputDelta")||u.find((i)=>xi(i).some((y)=>!aU(y)))||u.at(-1)||u[0],l=u.flatMap((i)=>Array.isArray(i?.rawSeqs)?i.rawSeqs:[i?.seq]).filter((i)=>i!==void 0),r=u.flatMap(xi).filter((i)=>i.trim().length>0&&!aU(i)),n=u[u.length-1]||f;return{...f,at:f?.at||n?.at,title:String(f?.title||"Edited files"),status:XE(n),summaryLines:r.length>0?r:xi(f),rawSeqs:l}}function pE(u){let f=Array.isArray(u)?u:[],l=[],r=[],n=()=>{if(r.length>0)l.push(SE(r));r=[]};for(let i of f){if(YE(i)){if(ht(i)==="item/started"&&r.length>0)n();if(r.push(i),ht(i)==="item/completed")n();continue}n(),l.push(i)}return n(),l}function mE(u){return{...u}}function P5(u,f=null){if(f!==null&&f!==void 0){let l=Lf(u?._traceStepsLoadedByAttempt)||{};return Boolean(l[String(f)])}return Boolean(u?._traceStepsLoaded)}function M5(u){return u?._traceStepDetails&&typeof u._traceStepDetails==="object"&&!Array.isArray(u._traceStepDetails)?u._traceStepDetails:{}}function PE(u,f){let l=Number(u?.index);return Number.isFinite(l)?l:f+1}function v5(u,f){return Boolean(u?.synthetic)||Number(f)<=0}function bt(u){let f=Number(u);return Number.isFinite(f)?String(f):void 0}function ME(u){let f=u?.timing&&typeof u.timing==="object"?u.timing:{},l=String(u?.status||"");if(["queued"].includes(l))return`等待 ${hr(f.queueWaitMs??f.totalElapsedMs)}`;if(["running","judging","retry_wait"].includes(l))return`耗时 ${hr(f.durationMs??f.totalElapsedMs)}`;return`耗时 ${hr(f.durationMs??f.totalElapsedMs)}`}function p_(u){return String(u?.queueId||"default")}function WQ(u){return Lf(u?.queuedReason)}function LQ(u){let f=String(u?.queuedReasonLabel||"").trim();if(f.length>0)return f.toUpperCase();let l=WQ(u),r=String(l?.label||"").trim();return r.length>0?r.toUpperCase():""}function CE(u){let f=String(u?.status||"unknown");if(f!=="queued")return f;let l=LQ(u);return l.length>0?`QUEUED(${l})`:"QUEUED"}function RE(u){if(String(u?.status||"")!=="queued")return;let f=WQ(u),l=String(f?.message||"").trim(),r=LQ(u);if(l.length>0&&r.length>0)return`${r}: ${l}`;if(l.length>0)return l;return r.length>0?r:void 0}function xE(u){return{system:"SYS",user:"YOU",assistant:"GPT",reasoning:"THINK",command:"CMD",diff:"DIFF",tool:"TOOL",error:"ERR"}[u]||u.toUpperCase()}function oU(u){return["running","judging","retry_wait"].includes(String(u?.status||""))}function hE(u){return String(u?.status||"")==="running"}function xr(u){return["succeeded","failed","canceled"].includes(String(u?.status||""))}function wQ(u){if(u?.promptEditable===!0)return!0;if(u?.promptEditable===!1)return!1;return String(u?.status||"")==="queued"&&!u?.startedAt&&Number(u?.currentAttempt||0)===0&&!u?.codexThreadId&&!u?.nextMode}function V0(u){if(!xr(u))return!1;if(u?.terminalUnread===!0)return!0;if(u?.terminalUnread===!1)return!1;return!u?.readAt}function Cf(u){let f=Number(u||0);return Number.isFinite(f)?f:0}function bE(u){return Cf(u.queued)+Cf(u.retry_wait)}function vE(u){return Cf(u.running)+Cf(u.judging)}function kE(u,f){return Lf(u?.statistics)||Lf(f?.statistics)||{}}function IE(u){return Array.isArray(u?.daily)?u.daily:[]}function gE(u){return Lf(u?.totals)||{}}function k5(u,f){let l=Number(u?.[f]??0);return Number.isFinite(l)&&l>0?l:0}function H5(u,f){return u.reduce((l,r)=>Math.max(l,k5(r,f)),0)}var N1=700,dU=220,Kn=30,Ci=24,m_=184,C5=m_-Ci;function KQ(u,f){if(f<=1)return N1/2;return Kn+u*(N1-Kn*2)/(f-1)}function GQ(u,f){let l=f>0?f:1;return m_-Math.min(1,u/l)*C5}function B5(u,f,l){let r=u.length>0?u:[{[f]:0}],n=r.length>1?r:[r[0],r[0]];return n.map((i,y)=>`${KQ(y,n.length).toFixed(2)},${GQ(k5(i,f),l).toFixed(2)}`).join(" ")}function B0(u){let f=String(u||"");return/^\d{4}-\d{2}-\d{2}$/u.test(f)?f.slice(5):f||"--"}function Mt(u){if(!u)return"";return`${String(u.seriesKey||"")}:${String(u.row?.date||u.index||"")}`}function sE(u,f,l,r){let n=k5(u,r.key);return{...r,row:u,index:f,value:n,valueLabel:r.format(n),x:KQ(f,l),y:GQ(n,r.max),seriesKey:r.key}}function eU(u){if(V0(u))return 0;return{running:1,judging:2,retry_wait:3,queued:4,succeeded:8,failed:8,canceled:8}[String(u?.status||"")]??9}function X_(u){if(!u)return!1;if(u?._traceSummaryLoaded===!0)return!1;return u?.summaryOnly===!0||u?._metaLoaded!==!0}function aE(u){return Boolean(u?._metaLoaded)||u?.summaryOnly===!1}function oE(u,f,l){let r=String(u?.[l]||""),n=String(f?.[l]||"");return r.length>n.length?r:n}function R5(u,f,l){let r=Array.isArray(u?.[l])?u[l]:[],n=Array.isArray(f?.[l])?f[l]:[];if(n.length===0&&r.length>0)return r;return r.length>n.length?r:n}function uQ(u,f){let l=f?.summaryOnly===!0&&aE(u),r={...u,...f};if(!l)return r;for(let n of["prompt","basePrompt","displayPrompt","finalResponse"])r[n]=oE(u,f,n);for(let n of["promptHistory","attempts","output","events"])r[n]=R5(u,f,n);if(u?.referenceInjection?.items&&!f?.referenceInjection?.items)r.referenceInjection=u.referenceInjection;if(u?.referenceInjectionSummary&&!f?.referenceInjectionSummary)r.referenceInjectionSummary=u.referenceInjectionSummary;r.summaryOnly=u?.summaryOnly===!1?!1:f.summaryOnly,r._metaLoaded=u?._metaLoaded,r._detailLoaded=u?._detailLoaded,r._transcriptComplete=u?._transcriptComplete,r._transcriptPreview=Object.prototype.hasOwnProperty.call(f,"_transcriptPreview")?f._transcriptPreview:u?._transcriptPreview;for(let n of["_traceSummary","_traceSummaryLoaded","_traceSteps","_traceStepsLoaded","_traceStepsByAttempt","_traceStepsLoadedByAttempt","_traceStepsNextAfterSeqByAttempt","_traceStepDetails","_promptDetails"])if(!Object.prototype.hasOwnProperty.call(f,n)&&Object.prototype.hasOwnProperty.call(u||{},n))r[n]=u[n];return r}function dE(u){let f=u?.selected,l=f?.task&&typeof f.task==="object"?f.task:null;if(l!==null){let n=Boolean(f?.preview);return{...l,transcript:Array.isArray(f?.transcript)?f.transcript:[],_detailLoaded:Array.isArray(f?.transcript)&&f.transcript.length>0,_transcriptComplete:Boolean(!n&&!f?.hasMore&&xr(l)),_transcriptPreview:n,_summaryLoaded:!0}}let r=jl(u)[0];return r?{...r,_summaryLoaded:!0}:null}function V5(u,f){let l=new Map;for(let r of[...Array.isArray(u)?u:[],...Array.isArray(f)?f:[]]){let n=`${Number(r?.seq??0)}:${String(r?.kind||"message")}`,i=l.get(n);if(!i){l.set(n,r);continue}let y={...i,...r};for(let[_,$]of[["bodyPreview","bodyOmittedLines"],["commandPreview","commandOmittedLines"]]){let A=String(i?.[_]||""),c=String(r?.[_]||"");if(A.length>c.length)y[_]=i[_],y[$]=i[$]}l.set(n,y)}return Array.from(l.values()).sort((r,n)=>Number(r?.seq??0)-Number(n?.seq??0))}function Ct(u){return(Array.isArray(u)?u:[]).reduce((f,l)=>Math.max(f,Number(l?.seq??0)),0)}function fQ(u,f=8){let l=Array.from(new Set((Array.isArray(u)?u:[]).map((n)=>Number(n?.seq??0)).filter((n)=>Number.isFinite(n)&&n>0))).sort((n,i)=>n-i);if(l.length===0)return 0;let r=l[Math.max(0,l.length-f)]??0;return Math.max(0,r-0.001)}function eE(u,f){let l=Array.isArray(u?.codeModels)?u.codeModels:Array.isArray(u?.codexModels)?u.codexModels:[],r=["gpt-5.5","gpt-5.4-mini","gpt-5.4","minimax-m2.7"];return Array.from(new Set([...l,...r,f].map((n)=>String(n||"").trim()).filter(Boolean)))}function uZ(u,f){let r=(Array.isArray(u?.executionProviders)?u.executionProviders:[]).map((y)=>({id:String(y?.id||"").trim(),label:String(y?.label||y?.id||"").trim(),defaultWorkdir:String(y?.defaultWorkdir||"").trim(),supportsWindowsNativeCodex:y?.supportsWindowsNativeCodex===!0,windowsNativeDefaultWorkdir:String(y?.windowsNativeDefaultWorkdir||"").trim(),kind:String(y?.kind||"").trim()})).filter((y)=>y.id.length>0),n=String(u?.mainProviderId||u?.defaultProviderId||"main-server").trim()||"main-server",i=new Map;for(let y of[...r,{id:n,label:`${n} (master)`,defaultWorkdir:String(u?.defaultWorkdir||"/root/unidesk"),supportsWindowsNativeCodex:!1,windowsNativeDefaultWorkdir:"",kind:"local"},f?{id:f,label:f,defaultWorkdir:I5(u,f),supportsWindowsNativeCodex:f!==n,windowsNativeDefaultWorkdir:String(u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart"),kind:""}:null].filter(Boolean))if(!i.has(y.id))i.set(y.id,y);return Array.from(i.values())}function fZ(u,f){let r=(Array.isArray(u?.executionModes)?u.executionModes:[]).map((y)=>({id:String(y?.id||y?.kind||"").trim(),label:String(y?.label||y?.id||y?.kind||"").trim(),description:String(y?.description||"").trim(),defaultWorkdir:String(y?.defaultWorkdir||"").trim(),requiresProvider:y?.requiresProvider===!0,requiresWindowsCwd:y?.requiresWindowsCwd===!0})).filter((y)=>y.id.length>0),n=[{id:"default",label:"默认容器/本机",description:"主 server 用本机 Codex;远程 Provider 用执行容器 Codex。",defaultWorkdir:"",requiresProvider:!1,requiresWindowsCwd:!1},{id:"windows-native",label:"Windows 原生 Codex",description:"启动执行容器,但容器只做 stdio relay,Codex 运行在 Provider 的 Windows 宿主。",defaultWorkdir:String(u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart"),requiresProvider:!0,requiresWindowsCwd:!0}],i=new Map;for(let y of[...r,...n,f?{id:f,label:f,description:"",defaultWorkdir:"",requiresProvider:f==="windows-native",requiresWindowsCwd:f==="windows-native"}:null].filter(Boolean))if(!i.has(y.id))i.set(y.id,y);return Array.from(i.values())}function D5(u,f,l){if(f!=="windows-native")return I5(u,l);let r=Array.isArray(u?.executionModes)?u.executionModes.find((i)=>String(i?.id||i?.kind||"")==="windows-native"):null,n=Array.isArray(u?.executionProviders)?u.executionProviders.find((i)=>String(i?.id||"")===l):null;return String(n?.windowsNativeDefaultWorkdir||r?.defaultWorkdir||u?.windowsNativeCodexDefaultWorkdir||"/mnt/f/Work/ConStart")}function I5(u,f){let l=String(f||"").trim(),r=u?.defaultWorkdirByProvider&&typeof u.defaultWorkdirByProvider==="object"?u.defaultWorkdirByProvider:{};if(typeof r[l]==="string"&&String(r[l]).trim().length>0)return String(r[l]).trim();let n=Array.isArray(u?.executionProviders)?u.executionProviders.find((y)=>String(y?.id||"")===l):null;if(typeof n?.defaultWorkdir==="string"&&n.defaultWorkdir.trim().length>0)return n.defaultWorkdir.trim();let i=String(u?.mainProviderId||u?.defaultProviderId||"main-server");return l===i?String(u?.defaultWorkdir||"/root/unidesk"):String(u?.remoteDefaultWorkdir||"/home/ubuntu")}function lZ(u){return jQ(u)}function rZ({task:u,selected:f,onSelect:l,onCopy:r,onReference:n,onMarkRead:i,copied:y,markingRead:_}){let $=u?.lastJudge||{},A=String(u?.id||""),c=V0(u),j=yQ(u?.updatedAt,cr(u)?.updatedAt),F=`最近更新: ${iQ(j)}`,U=lZ(u),Q=U===null?"--":String(U),L=U===null?"STEP 统计中心同步中":"STEP 来自 OA Event Flow 统计中心";return K("article",{role:"button",tabIndex:0,className:`codex-task-card ${f?"selected":""} ${c?"unread-terminal":""}`,onClick:l,onKeyDown:(w)=>{if(w.key==="Enter"||w.key===" ")w.preventDefault(),l()},"data-unread-terminal":c?"true":"false","data-testid":`codex-task-${u?.id||"unknown"}`},c?K("span",{className:"codex-unread-badge",title:"待读","aria-label":"待读","data-testid":`codex-unread-task-${A||"unknown"}`}):null,K("div",{className:"codex-task-card-head"},K("div",{className:"codex-task-status-line"},K(L1,{status:u?.status,title:RE(u)},CE(u))),K("span",{className:"mono-text"},`${u?.currentAttempt||0}/${u?.maxAttempts||0}`)),K("div",{className:"codex-task-id-row"},K("code",{title:A},A||"unknown"),K("div",{className:"codex-task-id-actions"},K("button",{type:"button",className:"codex-copy-id-btn",onClick:(w)=>{w.stopPropagation(),n(A)},"data-testid":`codex-reference-task-${A||"unknown"}`},"引用"),K("button",{type:"button",className:"codex-copy-id-btn",onClick:(w)=>{w.stopPropagation(),r(A)},"data-testid":`codex-copy-task-id-${A||"unknown"}`},y?"已复制":"复制ID"),c?K("button",{type:"button",className:"codex-copy-id-btn codex-mark-read-btn",disabled:Boolean(_),onClick:(w)=>{w.stopPropagation(),i(A)},"data-testid":`codex-mark-task-read-${A||"unknown"}`},_?"标记中":"标为已读"):null)),K("strong",null,Y5(tQ(u),120)||"空任务"),K("div",{className:"codex-task-meta"},K("span",null,`queue=${p_(u)}`),K("span",null,`provider=${u?.providerId||"main-server"}`),K("span",null,`mode=${u?.executionMode||"default"}`),K("span",null,u?.model||"--"),K("span",null,ME(u))),K("div",{className:"codex-task-meta codex-task-update-meta"},K("span",{className:"codex-task-recent-update codex-task-step-count",title:L,"data-testid":`codex-task-step-count-${A||"unknown"}`},`STEP ${Q}`),K("span",{className:"codex-task-recent-update",title:j?`更新时间: ${Nu(j)}`:F,"data-testid":`codex-task-recent-update-${A||"unknown"}`},F),K("span",null,Nu(j||u?.updatedAt))),wQ(u)?K("div",{className:"codex-judge-line","data-testid":`codex-task-prompt-editable-${A||"unknown"}`},"queued prompt 可编辑"):null,$?.decision?K("div",{className:"codex-judge-line"},`judge=${$.decision} ${Math.round(Number($.confidence||0)*100)}%`):null)}function X5({title:u,tasks:f,selectedId:l,onSelect:r,onCopy:n,onReference:i,onMarkRead:y,copiedTaskId:_,markingReadTaskId:$,emptyText:A}){let c=Array.isArray(f)?f:[];return K("section",{className:"codex-task-section"},K("div",{className:"codex-task-section-head"},K("span",null,u),K("code",null,String(c.length))),c.length===0?K("p",{className:"codex-task-section-empty"},A):K("div",{className:"codex-task-section-list"},c.map((j)=>K(rZ,{key:j.id,task:j,selected:l===j.id,onSelect:()=>r(j.id),onCopy:n,onReference:i,onMarkRead:y,copied:_===j.id,markingRead:$===j.id}))))}function nZ(){return K("span",{className:"codex-stats-icon","aria-hidden":"true"},K("svg",{viewBox:"0 0 36 24",focusable:"false"},K("path",{className:"grid",d:"M3 20.5H33M3 12.5H33M3 4.5H33"}),K("polyline",{className:"line tasks",points:"3,18 9,14 15,15 21,8 27,10 33,4"}),K("polyline",{className:"line retry",points:"3,20 9,17 15,18 21,13 27,14 33,9"})))}function iZ({stats:u,queueName:f,onRaw:l}){let r=IE(u),n=gE(u),i=r.at(-1)||{},y=H5(r,"executedTasks"),_=H5(r,"retryAttempts"),$=H5(r,"avgDurationMs"),A=r.length>0,c=Lf(u?.range)||{},[j,F]=bu(null),[U,Q]=bu(null),L=[];if(y>0)L.push(`tasks ${y}`);if(_>0)L.push(`retry ${_}`);if($>0)L.push(`avg ${hr($)}`);let w=[{key:"executedTasks",className:"tasks",label:"执行任务",max:y,format:(E)=>`${Cf(E)} tasks`},{key:"retryAttempts",className:"retry",label:"重试次数",max:_,format:(E)=>`${Cf(E)} retries`},{key:"avgDurationMs",className:"duration",label:"平均耗时",max:$,format:(E)=>hr(E)}],J=j||U,N=Mt(J),q=String(J?.row?.date||""),W=J?{left:`${Math.max(8,Math.min(92,Number(J.x)/N1*100))}%`,top:`${Math.max(14,Math.min(86,Number(J.y)/dU*100))}%`}:void 0;wn(()=>{F(null),Q(null)},[f,c.startDate,c.endDate,r.length]);let z=(E)=>{F(E)},Z=(E)=>{let D=Mt(E);Q((h)=>Mt(h)===D?null:E),F(E)},H=w.flatMap((E)=>r.map((D,h)=>{let V=sE(D,h,r.length,E),Y=Mt(V),p=N===Y,O=String(D?.date||`day-${h}`),m=`${B0(O)} ${E.label}: ${V.valueLabel}`;return K("g",{key:`${E.key}-${O}`,className:`stat-point-group ${E.className} ${p?"active":""}`,role:"button",tabIndex:0,"aria-label":m,"data-testid":`codex-stats-point-${E.className}-${O}`,onMouseEnter:()=>z(V),onFocus:()=>z(V),onClick:()=>Z(V),onKeyDown:(X)=>{if(X.key==="Enter"||X.key===" ")X.preventDefault(),Z(V)}},K("circle",{className:"stat-hit-point",cx:V.x,cy:V.y,r:13}),K("circle",{className:`stat-point ${E.className} ${p?"active":""}`,cx:V.x,cy:V.y,r:p?5.6:4.2}))}));return K(Mi,{title:"统计曲线",eyebrow:`Daily task stats / ${f}`,className:"codex-stats-panel",summary:K("span",null,`${B0(c.startDate)} -> ${B0(c.endDate)} · ${u?.timezone||"Asia/Shanghai"}`),actions:Lf(u)?K(_Q,{title:"Code Queue Stats",data:u,onOpen:l,testId:"raw-codex-stats"}):null},K("div",{className:"codex-stats-hero","data-testid":"codex-stats-panel"},K(nZ),K("div",null,K("strong",null,`${Cf(n.executedTasks)} tasks / ${Cf(n.retryAttempts)} retries`),K("span",null,`平均完成耗时 ${hr(n.avgDurationMs??void 0)} · 终态 ${Cf(n.completedTasks)} 个`))),A?K("div",{className:"codex-stats-chart","data-testid":"codex-stats-chart",onMouseLeave:()=>F(null)},K("svg",{viewBox:`0 0 ${N1} ${dU}`,preserveAspectRatio:"none",role:"img","aria-label":"Code Queue daily task statistics"},K("line",{className:"axis",x1:Kn,x2:N1-Kn,y1:m_,y2:m_}),K("line",{className:"grid",x1:Kn,x2:N1-Kn,y1:Ci+C5/2,y2:Ci+C5/2}),K("line",{className:"grid",x1:Kn,x2:N1-Kn,y1:Ci,y2:Ci}),K("polyline",{className:"stat-line tasks",points:B5(r,"executedTasks",y)}),K("polyline",{className:"stat-line retry",points:B5(r,"retryAttempts",_)}),K("polyline",{className:"stat-line duration",points:B5(r,"avgDurationMs",$)}),J?K("g",{className:"stat-cursor-layer","data-testid":"codex-stats-active-point"},K("line",{className:"stat-cursor",x1:J.x,x2:J.x,y1:Ci,y2:m_}),K("circle",{className:`stat-point-active ${J.className}`,cx:J.x,cy:J.y,r:8})):null,K("g",{className:"stat-point-layer"},H)),J?K("div",{className:"codex-stats-tooltip active",style:W,"data-testid":"codex-stats-tooltip"},K("b",null,B0(J.row?.date)),K("span",null,`${J.label} · ${J.valueLabel}`),K("code",null,`${Cf(J.row?.executedTasks)} exec / ${Cf(J.row?.retryAttempts)} retry / ${hr(J.row?.avgDurationMs??void 0)}`)):null,K("div",{className:"codex-stats-legend"},K("span",{className:"tasks"},"执行任务"),K("span",{className:"retry"},"重试次数"),K("span",{className:"duration"},"平均耗时")),K("div",{className:"codex-stats-scale"},K("span",null,B0(r[0]?.date)),K("span",null,L.join(" · ")||"暂无峰值"),K("span",null,B0(r.at(-1)?.date))),K("div",{className:`codex-stats-focus ${J?"active":""}`,"data-testid":"codex-stats-focus"},J?K(P_.default.Fragment,null,K("div",null,K("strong",null,B0(J.row?.date)),K("span",null,`${J.label} · ${J.valueLabel}`)),K("div",{className:"codex-stats-focus-metrics"},K("code",null,`${Cf(J.row?.executedTasks)} exec`),K("code",null,`${Cf(J.row?.retryAttempts)} retry`),K("code",null,hr(J.row?.avgDurationMs??void 0)))):K("span",null,"将鼠标悬停到曲线数据点查看明细,点击数据点可固定。"))):K(w1,{title:"暂无统计",text:"任务开始执行后会生成按天汇总的曲线。"}),K("div",{className:"codex-stats-summary-grid"},K("article",null,K("span",null,"今日执行"),K("strong",null,String(Cf(i.executedTasks))),K("code",null,B0(i.date))),K("article",null,K("span",null,"今日重试"),K("strong",null,String(Cf(i.retryAttempts))),K("code",null,`累计 ${Cf(n.retryAttempts)}`)),K("article",null,K("span",null,"平均耗时"),K("strong",null,hr(n.avgDurationMs??void 0)),K("code",null,`${Cf(n.durationSamples)} samples`))),K("div",{className:"codex-stats-daily-list","data-testid":"codex-stats-daily-list"},r.slice(-7).map((E)=>K("div",{key:String(E?.date||""),className:`codex-stats-daily-row ${q===String(E?.date||"")?"active":""}`,"data-testid":`codex-stats-day-${String(E?.date||"unknown")}`},K("span",null,B0(E?.date)),K("b",null,`${Cf(E?.executedTasks)} exec`),K("b",null,`${Cf(E?.retryAttempts)} retry`),K("code",null,hr(E?.avgDurationMs??void 0))))))}function yZ({task:u,queueRows:f,busy:l,onMove:r}){let n=String(u?.id||""),i=p_(u),[y,_]=bu(i);wn(()=>{_(i)},[n,i]);let $=!n||l||["running","judging","retry_wait"].includes(String(u?.status||""));return K("div",{className:"codex-task-move-control","data-testid":"codex-task-queue-move-control"},K("label",null,"任务 queue",K("select",{value:y,disabled:!n||l,onChange:(A)=>_(String(A.target.value||i)),"data-testid":"codex-task-queue-move-select"},f.map((A)=>K("option",{key:String(A?.id||""),value:String(A?.id||"")},S_(A))))),K("button",{type:"button",className:"ghost-btn",disabled:$||y===i,onClick:()=>r(y),title:$?"运行中 / judging / retry_wait 的任务不能移动;请先打断或等当前 turn 结束":"移动已创建任务到另一个 queue","data-testid":"codex-task-queue-move-button"},"移动"))}function lQ(u,f=4){let l=(Array.isArray(u)?u:[]).map((n)=>String(n||"").trim()).filter(Boolean);if(l.length===0)return"--";let r=l.slice(0,f).join(" / ");return l.length>f?`${r} +${l.length-f}`:r}function _Z({task:u,loading:f,onLoadPromptPart:l,testId:r="codex-initial-prompt-full",textTestId:n="codex-initial-prompt-full-text",baseTextTestId:i="codex-initial-prompt-base"}){let y=b5(u),_=xt(u),$=Rt(u).trimEnd(),A=String(_.full?.text||""),c=HE(u),j=Number(y.promptChars||u?.promptChars||A.length),F=Number(y.basePromptLines||W1($)),U=Number(y.promptLines||W1(A));return K("section",{className:"codex-progressive-card codex-progressive-prompt","data-testid":"codex-progressive-prompt"},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Prompt"),K("strong",null,"Submitted prompt / 原始用户 prompt"),K("code",null,`${F||W1($)} lines / ${$.length} chars`)),K("pre",{className:"codex-prompt-full","data-testid":i},$||"空 prompt"),c?K("details",{className:"codex-reference-injection codex-progressive-full-prompt","data-testid":r,onToggle:(Q)=>{if(Q.currentTarget?.open&&!A)l?.("full")}},K("summary",null,K("span",null,"引用注入已折叠,点击按需拉取最终进入 Code agent 的完整 prompt"),K("code",null,A?`${U||W1(A)} lines / ${A.length} chars`:`${Number.isFinite(j)&&j>0?j:"--"} chars`)),K("pre",{className:"codex-prompt-full codex-prompt-final-full","data-testid":n},A||(f?"正在按需拉取完整 prompt...":"展开后将只请求 full prompt,不拉取完整 transcript。"))):null)}function zQ({task:u,attempt:f,attemptIndex:l,loading:r,onLoadSteps:n,onLoadStep:i,testId:y="codex-execution-summary"}){let _=pE(NQ(u,l)),$=mE(zE(u,f)),A=f?WE(u,f):cQ(u),c=M5(u),j=P5(u,l),F=D0(A?.errorCount),U=D0(A?.stepCount??A?.llmStepCount),Q=D0(A?.readCount),L=D0(A?.editCount),w=D0(A?.runCount),J=D0(A?.stepCount??A?.llmStepCount),N=U===null?"--":String(U),q=J===null?"--":String(J),W=Array.isArray($.editedFiles)?$.editedFiles:[],z=Array.isArray($.commands)?$.commands:[],H=v5(f,l)?` · ${String(f?.label||"recovered thread execution")}`:l?` #${l}`:"",E=TE(u,f,l,$),D=`最近更新: ${iQ(E)}`,h=ZE(u,f,l);return K("details",{className:`codex-progressive-card codex-execution-summary ${h?"running":""}`,"data-testid":y,"data-attempt-index":bt(l),"data-running":h?"true":"false",onToggle:(V)=>{if(V.currentTarget?.open&&!j)n?.(l)}},K("summary",null,K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Summary"),K("strong",null,`执行过程摘要${H}`),h?K("span",{className:"codex-summary-running-pill","data-testid":`${y}-running`},"执行中"):null,K("code",{title:E?`最近更新: ${Nu(E)}`:D},`${hr($.durationMs??$.totalElapsedMs)} / ${N} tools / ${D}`)),K("div",{className:"codex-execution-digest"},K("span",{title:"来自 OA Event Flow 统计中心"},`read ${Q===null?"--":Q}`),K("span",{title:"来自 OA Event Flow 统计中心"},`edit ${L===null?"--":L}`),K("span",{title:"来自 OA Event Flow 统计中心"},`run ${w===null?"--":w}`),K("span",{title:"来自 OA Event Flow 统计中心"},`STEP ${q}`),F!==null&&F>0?K("span",{className:"codex-execution-error-pill","data-testid":`${y}-error-count`},`Error ${F}`):null)),K("div",{className:"codex-execution-digest expanded"},K("span",null,`修改文件:${lQ(W,6)}`),K("span",null,`执行命令:${lQ(z,4)}`)),_.length===0?K("div",{className:"codex-output-empty"},r?"正在按需拉取步骤 summary...":"展开后将只请求执行步骤 summary,不拉取单步骤全量。"):K("div",{className:"codex-trace-step-list"},_.map((V)=>{let Y=String(V?.seq??""),p=c[Y],O=Array.isArray(V?.summaryLines)?V.summaryLines.slice(0,4):[],m=O.find((X)=>String(X||"").trim().length>0);return K("details",{key:Y||`${V?.title}-${V?.at}`,className:`codex-trace-step ${String(V?.kind||"message")} ${DE(V)?"error":""}`,"data-testid":`codex-trace-step-${Y||"unknown"}`,onToggle:(X)=>{if(X.currentTarget?.open&&!p)i?.(V?.seq)}},K("summary",null,K("span",{className:"codex-output-channel"},$Z(V?.kind)),K("strong",null,String(V?.title||"Trace step")),V?.status?K("code",null,String(V.status)):null,m?K("span",{className:"codex-trace-step-inline-summary",title:String(m)},String(m)):null,K("time",null,Nu(V?.at))),K("div",{className:"codex-trace-step-summary"},O.length>0?O.map((X,v)=>K("pre",{key:`${Y}-${v}`},String(X||""))):K("span",null,"无 summary")),p?.line?K(St,{items:[p.line],autoScroll:!1,loading:!1,hasDetail:!0,emptyText:"无步骤详情",testId:`codex-trace-step-detail-${Y||"unknown"}`,className:"codex-transcript codex-step-detail-transcript",collapseTools:!1}):K("div",{className:"codex-output-empty"},r?"正在按需拉取这个步骤的全量数据...":"展开后将只请求这个单步骤的全量数据。"))})))}function $Z(u){let f=String(u||"");if(f==="ran")return"Ran";if(f==="explored")return"Explored";if(f==="edited")return"Edited";if(f==="error")return"Error";if(f==="system")return"System";return"Message"}function TQ({task:u,attempt:f,attemptIndex:l,testId:r="codex-final-response"}){let n=EE(u,f);if(n.length===0)return null;let i=Number(f?.finalResponseChars||n.length),y=l?` #${l}`:"";return K("section",{className:"codex-progressive-card codex-final-response","data-testid":r,"data-attempt-index":bt(l)},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Final"),K("strong",null,`最终 response${y}`),K("code",null,`${Number.isFinite(i)?i:n.length} chars`)),K(FU,{markdown:n,className:"codex-transcript-body codex-markdown",testId:`${r}-markdown`}))}function EQ({task:u,attempt:f,attemptIndex:l,testId:r="codex-progressive-judge"}){let n=QQ(u,f);if(!n?.decision)return null;let i=l?` #${l}`:"";return K("section",{className:"codex-progressive-card codex-progressive-judge","data-testid":r,"data-attempt-index":bt(l)},K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Judge"),K("strong",null,`完成判定${i}`),K("code",null,`${n.decision} ${Math.round(Number(n.confidence||0)*100)}%`)),K("div",{className:"codex-judge-card","data-testid":`${r}-card`},K(L1,{status:n.decision},n.decision),K("strong",null,`${Math.round(Number(n.confidence||0)*100)}% confidence`),K("p",{"data-testid":`${r}-reason`},n.reason||"--"),K(UQ,{judge:n,testId:`${r}-failure-details`}),n.continuePrompt?K("pre",{"data-testid":`${r}-continue-prompt`},String(n.continuePrompt||"")):null))}function tZ({task:u,attempt:f,attemptIndex:l,loading:r,onLoadPromptPart:n,testId:i="codex-judge-feedback-prompt"}){let y=OE(u,f,l);if(y===null)return null;let _=qQ(l),A=xt(u)[_],c=String(A?.text||"").trimEnd(),j=String(y.preview||y.text||"").trimEnd(),F=c||String(y.text||"").trimEnd(),U=Number(A?.chars||y.chars||F.length||j.length),Q=Number(A?.lines||y.lines||W1(F||j)),L=A?.forAttempt||y.forAttempt||Number(l||0)+1;return K("details",{className:"codex-progressive-card codex-judge-feedback-prompt","data-testid":i,"data-attempt-index":bt(l),onToggle:(w)=>{if(w.currentTarget?.open&&!c)n?.("feedback",l)}},K("summary",null,K("div",{className:"codex-progressive-card-head"},K("span",{className:"codex-output-channel"},"Prompt"),K("strong",null,`judge feedback prompt #${l} -> #${L}`),K("code",null,`${Q||"--"} lines / ${Number.isFinite(U)?U:j.length} chars`)),K("p",{className:"codex-feedback-preview","data-testid":`${i}-preview`},j||"展开后按需拉取 judge feedback prompt。")),K("pre",{className:"codex-prompt-full codex-feedback-full","data-testid":`${i}-text`},F||(r?"正在按需拉取 judge feedback prompt...":"展开后将只请求这一次 judge feedback prompt。")))}function AZ({task:u,attempt:f,position:l,loading:r,onLoadPromptPart:n,onLoadSteps:i,onLoadStep:y}){let _=PE(f,l),$=l===0,A=v5(f,_),c=A?String(f?.label||"Recovered thread execution"):`Attempt ${_}`;return K("section",{className:"codex-attempt-cycle","data-testid":`codex-attempt-cycle-${_}`},K("div",{className:"codex-attempt-cycle-head"},K("span",{className:"codex-output-channel"},c),K("strong",null,String(f?.mode||(_<=1?"initial":"retry"))),f?.terminalStatus?K(L1,{status:f.terminalStatus},f.terminalStatus):null,K("code",null,`${Nu(f?.startedAt)} -> ${Nu(f?.finishedAt)}`)),K(zQ,{task:u,attempt:f,attemptIndex:_,loading:r,onLoadSteps:i,onLoadStep:y,testId:$?"codex-execution-summary":`codex-execution-summary-attempt-${_}`}),A?null:K(TQ,{task:u,attempt:f,attemptIndex:_,testId:$?"codex-final-response":`codex-final-response-attempt-${_}`}),A?null:K(EQ,{task:u,attempt:f,attemptIndex:_,testId:$?"codex-progressive-judge":`codex-progressive-judge-attempt-${_}`}),A?null:K(tZ,{task:u,attempt:f,attemptIndex:_,loading:r,onLoadPromptPart:n,testId:$?"codex-judge-feedback-prompt":`codex-judge-feedback-prompt-attempt-${_}`}))}function cZ({task:u,loading:f,onLoadPromptPart:l,onLoadSteps:r,onLoadStep:n}){if(!u)return K(w1,{title:"未选择任务",text:"从左侧队列选择任务,或提交新 Codex 任务。"});let i=GE(u);return K("div",{className:"codex-transcript codex-progressive-trace","data-testid":"codex-output"},f&&!cr(u)?K("div",{className:"codex-output-empty"},"正在加载 Trace Summary..."):null,K(_Z,{task:u,loading:f,onLoadPromptPart:l}),i.length>0?i.map((y,_)=>K(AZ,{key:`${y?.index||_+1}-${y?.startedAt||_}`,task:u,attempt:y,position:_,loading:f,onLoadPromptPart:l,onLoadSteps:r,onLoadStep:n})):[K(zQ,{key:"execution",task:u,loading:f,onLoadSteps:r,onLoadStep:n}),K(TQ,{key:"final",task:u}),K(EQ,{key:"judge",task:u})])}function jZ({task:u}){let f=FE(u);if(!u||f.length===0)return K(w1,{title:"暂无原始消息",text:"原始 Codex app-server 消息会保留在任务 JSON 中。"});return K("details",{className:"codex-raw-output"},K("summary",null,`原始 messages (${f.length})`),K("div",null,f.map((l)=>K("article",{key:`${l.seq}-${l.channel}`,className:`codex-output-line ${l.channel||"system"}`},K("div",{className:"codex-output-meta"},K("span",{className:"codex-output-channel"},xE(String(l.channel||"system"))),K("span",null,Nu(l.at)),l.method?K("code",null,l.method):null),K("pre",null,String(l.text||""))))))}function FZ({task:u}){let f=JE(u).slice().reverse();if(f.length===0)return K(w1,{title:"尚无 attempt",text:"任务开始运行后,这里会记录 Codex 终态、传输中断和 stderr tail。"});return K("div",{className:"table-wrap codex-attempt-table"},K("table",null,K("thead",null,K("tr",null,K("th",null,"#"),K("th",null,"模式"),K("th",null,"终态"),K("th",null,"传输"),K("th",null,"退出"),K("th",null,"完成时间"))),K("tbody",null,f.map((l)=>K("tr",{key:`${l.index}-${l.startedAt}`},K("td",null,l.index),K("td",null,l.mode),K("td",null,K(L1,{status:l.terminalStatus||"unknown"},l.terminalStatus||"unknown")),K("td",null,l.transportClosedBeforeTerminal?K(L1,{status:"failed"},"closed-before-terminal"):K(L1,{status:"succeeded"},"normal")),K("td",null,`code=${l.appServerExitCode??"--"} signal=${l.appServerSignal??"--"}`),K("td",null,Nu(l.finishedAt)))))))}function ZQ({microservices:u,onRaw:f,apiBaseUrl:l="/api",initialTasksData:r=null,standalone:n=!1}){let i=u.find((B)=>B.id==="code-queue")||null,y=dE(r),_=String(y?.id||""),$=new Map;if(y!==null&&_.length>0)$.set(_,{task:y,maxSeq:Ct(Array.isArray(y.transcript)?y.transcript:[]),complete:Boolean(y._transcriptComplete),completeUpdatedAt:y._transcriptComplete?String(y.updatedAt||""):""});let A=typeof performance>"u"?0:performance.now(),c=Xf(_),j=Xf(0),F=Xf(0),U=Xf(0),Q=Xf(!1),L=Xf(!1),w=Xf(!1),J=Xf(null),N=Xf(new Map),q=Xf(new Map),W=Xf(new Map),z=Xf(new Map),Z=Xf(new Set),H=Xf(null),E=Xf(null),D=Xf(!1),h=Xf(!1),V=Xf(Boolean(r)),Y=Xf(new Map),p=Xf(new Set),O=Xf($),m=Xf(r),[X,v]=bu(null),[T,S]=bu(r),[k,I]=bu(_),[b,o]=bu(y),[s,x]=bu(!1),[fu,$u]=bu(""),[tu,ju]=bu(null),[Gu,qu]=bu(!1),[P,e]=bu(!1),[uu,Wu]=bu(""),[g,Qu]=bu(""),[Tu,Zu]=bu("default"),[Xu,uf]=bu(Gn),[_f,Jf]=bu(!1),[Pf,Sl]=bu(""),[vf,ll]=bu("main-server"),[dl,el]=bu("default"),[cu,ku]=bu("gpt-5.5"),[Tl,pu]=bu("/root/unidesk"),[rl,El]=bu(99),[Jl,nl]=bu(1),[pl,qr]=bu(!1),[rf,C1]=bu(!1),[kn,R1]=bu(""),[lu,Ou]=bu(""),[Yu,Iu]=bu(""),[Qf,il]=bu(!0),[ff,df]=bu(()=>typeof window>"u"?!0:window.matchMedia(uE).matches),[$f,C$]=bu(!1),[V8,Tf]=bu(""),[u7,kf]=bu(""),{addNotification:ur}=Vl(),[Wy,R$]=bu(""),[x1,Ly]=bu(""),[h1,x$]=bu(!1),[ml,sr]=bu(r?{phase:"complete",taskId:_,queueMs:0,detailMs:0,totalMs:A,chunks:y?1:0,transcriptRows:Array.isArray(y?.transcript)?y.transcript.length:0,partial:Boolean(r?.selected?.hasMore||X_(y)),completedAt:new Date}:null),[h$,b$]=bu(r?new Date:null),[wy,Ky]=bu(!1),ar=s1(jl(T)),v$=ar.filter(V0),pf=T?.queue||X?.body?.queue||X?.queue||{},D8=kE(T,pf),k$=Ln(T),Dr=vU(pf,Tu),In=String(Tu||"default").trim()||"default",b0=Dr.filter((B)=>String(B?.id||"")!==In),b1=Ri(Dr,Xu),gn=Number((bl(Xu)?pf?.total:b1?.total)??k$.total??ar.length),Gy=Y_(pf),f7=bl(Xu)?Gy:[String(Ri(Dr,Xu)?.activeTaskId||"")].filter(Boolean),v1=kU(pf,Dr,Xu,ar),l7=bl(Xu)?O5(pf):O5(b1||{}),I$=O5(pf),X8=bE(I$),g$=Math.max(vE(I$),Gy.length),Y8=Cf((bl(Xu)?pf?.unreadTerminal:b1?.unreadTerminal)??v$.length),U0=T?v$.length:Y8,k1=bl(Xu)?"All queues":p5(b1||{id:Xu,name:Xu}),sn=S5(fu),Ul=sn.length>0,s$=Ul?s1(jl(tu)):[],zy=Ln(tu),fr=Ul?s$:ar,r7=fr.filter(V0),Kw=fr.filter((B)=>!xr(B)).sort(oT),Gw=fr.filter((B)=>xr(B)&&!V0(B)),n7=Ul?zy:k$,I1=Ul?Number(zy.total??s$.length):gn,i7=n7.hasMore===!0&&String(n7.nextBeforeId||"").length>0,S8=Ul?P:wy,zw=i?gT(i):{},Tw=i?sT(i):{},p8=xU(()=>UE(uu),[uu]),Q0=xU(()=>{let B=gU(Jl);return p8.flatMap((M)=>Array.from({length:B},()=>QE(M,g)))},[p8,Jl,g]),Ty=Q0.length,y7=Ty>1&&!pl,Ew=rf||$f||Ty===0||y7,_7=eE(pf,cu),a$=uZ(pf,vf),$7=fZ(pf,dl),Zw=D5(pf,dl,vf),m8=b?.id&&b?.activeTurnId&&String(b?.status)==="running",Ow=b?.id&&!["succeeded","failed","canceled"].includes(String(b?.status||"")),Hw=b?.id&&["succeeded","failed","canceled"].includes(String(b?.status||"")),g1=b?.id&&wQ(b);function Nr(B){let M=typeof B==="function"?B(m.current):B;return m.current=M,S(M),M}function Bw(B,M,d=!0){let nu=Array.from(new Set(B.map((Fu)=>String(Fu||"")).filter(Boolean)));for(let Fu of nu)if(Y.current.set(Fu,M),d)p.current.add(Fu);return nu}function t7(B){for(let M of B.map((d)=>String(d||"")).filter(Boolean))Y.current.delete(M),p.current.delete(M)}function o$(B){let M=String(B?.id||""),d=M?Y.current.get(M):void 0;if(!d)return B;if(String(B?.status||"").length>0&&!xr(B))return Y.current.delete(M),p.current.delete(M),B;return{...B,readAt:B?.readAt||d,terminalUnread:!1}}function P8(B){let M=String(B?.id||"");return M.length>0&&p.current.has(M)&&xr(B)}function s1(B,M=!0){let d=[];for(let nu of Array.isArray(B)?B:[]){let Fu=o$(nu);if(M&&P8(Fu))continue;d.push(Fu)}return d}function Vw(B,M=!0){if(!B||!Array.isArray(B?.tasks))return B;let d=s1(jl(B),M),nu=Ln(B);return{...B,tasks:d,pagination:B.pagination?{...nu,returned:d.length}:B.pagination}}function Dw(B){let M=String(B||pf?.mainProviderId||"main-server").trim()||"main-server";ll(M),pu(D5(pf,dl,M))}function Xw(B){let M=String(B||"default").trim()||"default",d=vf;if(M==="windows-native"){if(!a$.find((Fu)=>Fu.id===vf)?.supportsWindowsNativeCodex)d=String(a$.find((Fu)=>Fu.supportsWindowsNativeCodex)?.id||vf||"D601"),ll(d)}el(M),pu(D5(pf,M,d))}function d$(B,M,d=null,nu=null){let Fu=new Set(Bw(B,M));if(Fu.size===0&&nu===null&&d===null)return;Nr((Ku)=>{if(!Ku)return Ku;let Lu=jl(Ku).flatMap((Cu)=>{let xu=String(Cu?.id||"");if(!Fu.has(xu)){let jf=o$(Cu);return P8(jf)?[]:[jf]}let mu=nu&&String(nu?.id||"")===xu?nu:{},Ru={...Cu,...mu,readAt:M,terminalUnread:!1};return P8(Ru)?[]:[Ru]});return{...Ku,queue:d||Ku.queue,tasks:Fu.size>0?Pi([Lu],v1):Lu}});for(let Ku of Fu){let Lu=O.current.get(Ku);if(Lu?.task){let Cu=nu&&String(nu?.id||"")===Ku?nu:{},xu={...Lu.task,...Cu,readAt:M,terminalUnread:!1};if(O.current.set(Ku,{...Lu,task:xu}),c.current===Ku)o(xu)}}}wn(()=>{qr(!1)},[uu,Jl,g]),wn(()=>{let B=S5(fu);F.current+=1;let M=F.current;if(!i||B.length===0){ju(null),qu(!1),e(!1),w.current=!1;return}qu(!0),ju(null);let d=window.setTimeout(()=>{(async()=>{try{let nu=await iE(l,Xu,B);if(M!==F.current)return;ju(Vw(nu))}catch(nu){if(M===F.current)ju(null),Tf(cl(nu,"搜索 Codex tasks 失败"))}finally{if(M===F.current)qu(!1)}})()},240);return()=>window.clearTimeout(d)},[i?.id,l,Xu,fu]),wn(()=>{Ou(b?Rt(b):""),Iu(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},[k]);function q0(B,M,d){let nu=O.current.get(B)||{},Fu=nu.task||{},Ku=Array.isArray(Fu.transcript)?Fu.transcript:[],Lu=uQ(Fu,M),Cu=Object.prototype.hasOwnProperty.call(M,"transcript")?V5(Ku,Array.isArray(M.transcript)?M.transcript:[]):Ku,xu={...Fu,...Lu,transcript:Cu,output:Array.isArray(Lu.output)?R5(Fu,Lu,"output"):Array.isArray(Fu.output)?Fu.output:[],events:Array.isArray(Lu.events)?R5(Fu,Lu,"events"):Array.isArray(Fu.events)?Fu.events:[]},mu=o$(xu),Ru=String(mu?.updatedAt||""),jf=Boolean(M._transcriptComplete)&&xr(mu),yl=Boolean(nu.complete)&&xr(mu)&&String(nu.completeUpdatedAt||"")===Ru,ou=jf||yl,ef={...nu,task:mu,maxSeq:Ct(Cu),complete:ou,completeUpdatedAt:ou?Ru:""};if(O.current.set(B,ef),d===U.current&&c.current===B)o(mu);return ef}async function a1(B,M=!1,d,nu){if(!i||!B)return;let Ku=O.current.get(B)?.task;if(!M&&Pt(Ku))return;let Lu=B,Cu=N.current.get(Lu);if(Cu){if(M||!Pt(Ku))Cu.refreshAfter=!0;return Cu.promise}let xu=U.current,mu=performance.now();if(c.current===B)x(!0);let Ru={promise:Promise.resolve(),refreshAfter:!1},jf=(async()=>{try{let yl=await _E(l,B);if(xu!==U.current||c.current!==B)return;let ou=yl?.summary||{},ef=String(ou.updatedAt||"");q0(B,{id:B,status:ou.status,updatedAt:ef,startedAt:ou.startedAt,finishedAt:ou.finishedAt,currentAttempt:ou.currentAttempt,maxAttempts:ou.maxAttempts,finalResponse:ou.finalResponse,lastJudge:ou.lastJudge,lastError:ou.lastError,attempts:Array.isArray(ou.attempts)?ou.attempts:[],stepCount:ou.stepCount,llmStepCount:ou.llmStepCount,traceStats:ou.traceStats,statsSource:ou.statsSource,timing:ou.timing,_traceSummary:ou,_traceSummaryLoaded:!0,_traceSummaryUpdatedAt:ef,_detailLoaded:!0},xu),sr({phase:"complete",taskId:B,queueMs:nu??0,detailMs:performance.now()-mu,totalMs:d===void 0?performance.now()-mu:performance.now()-d,chunks:1,transcriptRows:Number(ou?.execution?.traceLineCount||ou?.execution?.stepCount||0),partial:!1,completedAt:new Date})}finally{let yl=Boolean(Ru.refreshAfter&&c.current===B&&!Pt(O.current.get(B)?.task));if(N.current.delete(Lu),xu===U.current&&c.current===B)x(!1);if(yl)window.setTimeout(()=>{a1(B,!0).catch((ou)=>Tf(cl(ou,"自动刷新 Trace Summary 失败")))},0)}})();Ru.promise=jf,N.current.set(Lu,Ru),await jf}async function Yw(B,M=null){let d=c.current;if(!i||!d||!B)return;let nu=O.current.get(d)?.task,Fu=xt(nu),Ku=B==="feedback"||B==="judge-feedback"?qQ(M):B;if(Fu[Ku]?.text)return;let Lu=`${d}:${Ku}`,Cu=q.current.get(Lu);if(Cu)return Cu;let xu=U.current;if(c.current===d)x(!0);let mu=(async()=>{try{let Ru=await $E(l,d,B,M);if(xu!==U.current||c.current!==d)return;let jf=O.current.get(d)?.task,yl=xt(jf);q0(d,{...B==="full"?{prompt:String(Ru?.text||""),promptChars:Number(Ru?.chars||0)}:{},_promptDetails:{...yl,[Ku]:Ru}},xu)}finally{if(q.current.delete(Lu),xu===U.current&&c.current===d)x(!1)}})();q.current.set(Lu,mu),await mu}async function M8(B=null,M={}){let d=c.current;if(!i||!d)return;let nu=O.current.get(d)?.task,Fu=B===null||B===void 0||String(B).length===0?"":String(B),Ku=P5(nu,Fu||null),Lu=Boolean(M.force),Cu=Boolean(M.incremental);if(Ku&&!Lu)return;let xu=NQ(nu,Fu||null),mu=Cu&&xu.length>0?BE(xu):0,Ru=`${d}:${Fu||"all"}:${mu}`,jf=W.current.get(Ru);if(jf)return jf;let yl=U.current;if(c.current===d)x(!0);let ou=(async()=>{try{let ef=await tE(l,d,mu,500,Fu||null);if(yl!==U.current||c.current!==d)return;let v0=Array.isArray(ef?.steps)?ef.steps:[],k0=mu>0?VE(xu,v0):v0;if(Fu){let I0=O.current.get(d)?.task,o1=Lf(I0?._traceStepsByAttempt)||{},_l=Lf(I0?._traceStepsLoadedByAttempt)||{},N0=Lf(I0?._traceStepsNextAfterSeqByAttempt)||{};q0(d,{_traceStepsByAttempt:{...o1,[Fu]:k0},_traceStepsLoadedByAttempt:{..._l,[Fu]:!0},_traceStepsNextAfterSeqByAttempt:{...N0,[Fu]:ef?.nextAfterSeq}},yl)}else q0(d,{_traceSteps:k0,_traceStepsLoaded:!0,_traceStepsHasMore:Boolean(ef?.hasMore),_traceStepsNextAfterSeq:ef?.nextAfterSeq},yl)}finally{if(W.current.delete(Ru),yl===U.current&&c.current===d)x(!1)}})();W.current.set(Ru,ou),await ou}async function Sw(B){let M=c.current,d=String(B??"");if(!i||!M||d.length===0)return;let nu=O.current.get(M)?.task;if(M5(nu)[d]?.line)return;let Ku=`${M}:${d}`,Lu=z.current.get(Ku);if(Lu)return Lu;let Cu=U.current;if(c.current===M)x(!0);let xu=(async()=>{try{let mu=await AE(l,M,B);if(Cu!==U.current||c.current!==M)return;let Ru=O.current.get(M)?.task,jf=M5(Ru);q0(M,{_traceStepDetails:{...jf,[d]:mu}},Cu)}finally{if(z.current.delete(Ku),Cu===U.current&&c.current===M)x(!1)}})();z.current.set(Ku,xu),await xu}function pw(B){if(c.current!==B)return;let M=O.current.get(B)?.task;if(!M)return;if(P5(M,null))M8(null,{force:!0,incremental:!0}).catch((nu)=>Tf(cl(nu,"增量刷新 Trace Steps 失败")));let d=Lf(M?._traceStepsLoadedByAttempt)||{};for(let nu of Object.keys(d).filter((Fu)=>d[Fu]))M8(nu,{force:!0,incremental:!0}).catch((Fu)=>Tf(cl(Fu,"增量刷新 Attempt Trace Steps 失败")))}async function Rp(B,M,d){if(!i||!B)return;let nu=performance.now(),Fu=U.current,Ku=O.current.get(B);if(Ku?.task){if(o(Ku.task),x(X_(Ku.task)||!Ku.complete),!X_(Ku.task)&&Ku.complete&&xr(Ku.task)&&String(Ku.completeUpdatedAt||"")===String(Ku.task?.updatedAt||"")){sr({phase:"complete",taskId:B,queueMs:d??0,detailMs:0,totalMs:M===void 0?0:performance.now()-M,chunks:0,transcriptRows:Array.isArray(Ku.task.transcript)?Ku.task.transcript.length:0,completedAt:new Date});return}}else x(!0);let Lu=J.current;if(Lu?.taskId===B&&Lu.token===Fu)return Lu.promise;let Cu=(async()=>{try{let xu=await Rf(xf(l,`/api/tasks/${encodeURIComponent(B)}?meta=1`));if(Fu!==U.current||c.current!==B)return;let mu=O.current.get(B),Ru=Array.isArray(mu?.task?.transcript)?mu.task.transcript:[],jf=xu?.task||{},yl=Boolean(mu?.complete)&&String(mu?.completeUpdatedAt||"")===String(jf?.updatedAt||"");q0(B,{...jf,summaryOnly:!1,_metaLoaded:!0,transcript:Ru,_detailLoaded:Ru.length>0,_transcriptComplete:yl},Fu);let ou=X_(mu?.task)||Boolean(mu?.task?._transcriptPreview),ef=ou?0:Ru.length>0?fQ(Ru):0,v0=!ou&&mu?.complete&&xr(jf)&&String(mu?.completeUpdatedAt||"")===String(jf?.updatedAt||"")?Ct(Ru):ef,k0=!0,I0=0,o1=Ru.length;while(k0){let _l=await Rf(xf(l,`/api/tasks/${encodeURIComponent(B)}/transcript?afterSeq=${encodeURIComponent(String(v0))}&limit=${vT}&fullText=1`));if(Fu!==U.current||c.current!==B)return;let N0=O.current.get(B),e$=Array.isArray(N0?.task?.transcript)?N0.task.transcript:[],If=V5(e$,Array.isArray(_l?.transcript)?_l.transcript:[]);I0+=1,o1=If.length;let u3=Boolean(!_l?.hasMore);if(q0(B,{status:_l?.status||jf.status,updatedAt:_l?.updatedAt||jf.updatedAt,transcript:If,_detailLoaded:u3||If.length>0,_transcriptComplete:u3,_transcriptPreview:ou&&!u3},Fu),k0=Boolean(_l?.hasMore),v0=Number(_l?.nextAfterSeq??Ct(If)),!k0)break;await new Promise((d1)=>window.setTimeout(d1,0))}sr({phase:"complete",taskId:B,queueMs:d??0,detailMs:performance.now()-nu,totalMs:M===void 0?performance.now()-nu:performance.now()-M,chunks:I0,transcriptRows:o1,completedAt:new Date})}finally{if(J.current?.taskId===B&&J.current?.token===Fu)J.current=null;if(Fu===U.current&&c.current===B)x(!1)}})();J.current={taskId:B,token:Fu,promise:Cu},await Cu}async function Pl(B=c.current,M=!0,d=Xu){if(!i)return;if(!M&&h.current)return;let nu=performance.now();if(M)h.current=!0;if(M)sr({phase:"loading",taskId:String(B||c.current||""),startedAt:new Date});let Fu=j.current+1;j.current=Fu;let Ku=String(B||c.current||""),Lu=Ku?O.current.get(Ku):null,Cu=Array.isArray(Lu?.task?.transcript)?Lu.task.transcript:[],xu=fQ(Cu),mu=null;if(mu=await yE(l,Ku,xu,d),Fu!==j.current){if(M)h.current=!1;return}let Ru=performance.now()-nu;v(X||{});let jf=mu?.queue||{},yl=String(jf?.activeTaskId||Y_(jf)[0]||""),ou=mu;Nr((rr)=>{let Ey=jl(mu),an=jl(rr),Zy=an.length>0?Pi([an,Ey],yl):Pi([Ey],yl),f3=s1(Zy),AK=Ln(mu),l3=Ln(rr),cK=an.length>Ey.length&&(l3.hasMore===!1||String(l3.nextBeforeId||"").length>0),jK={...AK,...cK?{hasMore:l3.hasMore,nextBeforeId:l3.nextBeforeId}:{},returned:f3.length};return ou={...mu,tasks:f3,pagination:jK},ou});let ef=jl(ou),v0=vU(jf,Tu),k0=kU(jf,v0,d,ef),I0=nE(v0,d,ef),o1=Ku||c.current,_l=ou?.selected||null,N0=_l?.task||null,e$=Array.isArray(_l?.transcript)?_l.transcript:null,If=o1||k0||I0||ef[0]?.id||"";if(c.current!==If)U.current+=1;c.current=If,I(If);let d1=ef.find((rr)=>rr.id===If);if(d1){let rr=O.current.get(If);if(rr?.task)O.current.set(If,{...rr,task:{...d1,...rr.task,status:d1.status,updatedAt:d1.updatedAt}})}if(N0?.id===If&&e$!==null){let rr=O.current.get(If),Ey=Array.isArray(rr?.task?.transcript)?rr.task.transcript:[],an=V5(Ey,e$),Zy=Boolean(_l?.preview);if(q0(If,{...N0,_summaryLoaded:!0,transcript:an,_detailLoaded:!_l?.hasMore||an.length>0,_transcriptComplete:!Zy&&!_l?.hasMore&&xr(N0),_transcriptPreview:Zy},U.current),x(!1),M)sr({phase:"complete",taskId:If,queueMs:Ru,detailMs:Math.max(0,performance.now()-nu-Ru),totalMs:performance.now()-nu,chunks:1,transcriptRows:an.length,partial:Boolean(Zy||_l?.hasMore||X_(N0)),completedAt:new Date});if(b$(new Date),M)h.current=!1;a1(If,!1,M?nu:void 0,M?Ru:void 0).catch((f3)=>Tf(cl(f3,"加载 Codex Trace Summary 失败")));return}if(M)sr({phase:"session",taskId:If,queueMs:Ru,totalMs:Ru,startedAt:new Date(Date.now()-Ru)});if(If)a1(If,!0,M?nu:void 0,M?Ru:void 0).catch((rr)=>Tf(cl(rr,"加载 Codex Trace Summary 失败")));else if(U.current+=1,o(null),x(!1),M)sr({phase:"complete",taskId:"",queueMs:Ru,detailMs:0,totalMs:performance.now()-nu,chunks:0,transcriptRows:0,completedAt:new Date});if(b$(new Date),M)h.current=!1}async function A7(){if(Ul){if(!i||P||w.current)return;let M=String(zy.nextBeforeId||"");if(!M)return;w.current=!0,e(!0),Tf("");try{let d=await IU(l,Xu,M,nQ,sn),nu=jl(d),Fu=d?.queue||pf||{},Ku=String(Fu?.activeTaskId||Y_(Fu)[0]||v1||"");ju((Lu)=>{let Cu=s1(Pi([jl(Lu),nu],Ku)),xu=Ln(d);return{...Lu||{},queue:Fu,tasks:Cu,pagination:{...xu,returned:Cu.length}}})}catch(d){Tf(cl(d,"加载更多搜索结果失败"))}finally{w.current=!1,e(!1)}return}if(!i||wy||L.current)return;let B=String(Ln(T).nextBeforeId||"");if(!B)return;L.current=!0,Ky(!0),Tf("");try{let M=await IU(l,Xu,B),d=jl(M),nu=M?.queue||pf||{},Fu=String(nu?.activeTaskId||Y_(nu)[0]||v1||"");Nr((Ku)=>{let Lu=s1(Pi([jl(Ku),d],Fu)),Cu=Ln(M);return{...Ku||{},queue:nu,statistics:M?.statistics||Ku?.statistics,tasks:Lu,pagination:{...Cu,returned:Lu.length}}})}catch(M){Tf(cl(M,"加载更早 Codex tasks 失败"))}finally{L.current=!1,Ky(!1)}}function mw(B){let M=B.currentTarget;if(!M||S8||!i7)return;if(M.scrollHeight-M.scrollTop-M.clientHeight<120)A7()}async function lr(B,M){C$(!0),Tf("");try{await B()}catch(d){Tf(cl(d,M))}finally{C$(!1)}}async function C8(B){if(!B)return;try{let M=!1;try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(B),M=!0}catch{M=!1}if(!M){let nu=document.createElement("textarea");nu.value=B,nu.style.position="fixed",nu.style.opacity="0",document.body.appendChild(nu),nu.select(),M=document.execCommand("copy"),document.body.removeChild(nu)}if(!M)throw Error("browser clipboard rejected the copy request");R$(B);let d=`已复制任务 ID:${B}`;kf(d),ur("success",d),window.setTimeout(()=>R$((nu)=>nu===B?"":nu),1600)}catch(M){Tf(`复制任务 ID 失败:${cl(M)}`)}}function R8(B){if(!B)return;Qu(B);let M=`已引用任务 ID:${B};提交时后端会读取并注入该任务上下文`;kf(M),ur("success",M)}async function x8(B){if(!i||!B)return;let M=new Date().toISOString();j.current+=1,d$([B],M,null,{id:B,readAt:M,terminalUnread:!1}),Ly(B);let d=!1;if(await lr(async()=>{let nu=await cE(l,B),Fu=nu?.task||{id:B,readAt:new Date().toISOString(),terminalUnread:!1},Ku=String(Fu?.readAt||new Date().toISOString());d$([B],Ku,nu?.queue||null,Fu),d=!0;let Lu=`已将任务 ${B} 标为已读`;kf(Lu),ur("success",Lu)},"标记 Codex task 已读失败"),!d)t7([B]),Pl(c.current,!1).catch((nu)=>Tf(cl(nu,"刷新 Codex tasks 失败")));Ly((nu)=>nu===B?"":nu)}async function Pw(){if(!i||h1)return;x$(!0);let B=new Date().toISOString(),M=Array.from(new Set([...jl(m.current).filter(V0).map((nu)=>String(nu?.id||"")).filter(Boolean),...Array.from(O.current.entries()).filter(([,nu])=>V0(nu?.task)).map(([nu])=>nu)]));if(j.current+=1,M.length>0)d$(M,B);let d=!1;if(await lr(async()=>{let nu=await jE(l),Fu=String(nu?.readAt||new Date().toISOString()),Ku=jl(m.current).filter(V0).map((Ru)=>String(Ru?.id||"")).filter(Boolean),Lu=Array.from(O.current.entries()).filter(([,Ru])=>V0(Ru?.task)).map(([Ru])=>Ru),Cu=Array.from(new Set([...M,...Ku,...Lu]));d$(Cu,Fu,nu?.queue||null);let xu=Number(nu?.count||Cu.length);d=!0;let mu=`已将 ${xu} 个已结束未读任务标为已读`;kf(mu),ur("success",mu)},"全部标为已读失败"),!d&&M.length>0)t7(M),Pl(c.current,!1).catch((nu)=>Tf(cl(nu,"刷新 Codex tasks 失败")));x$(!1)}function Mw(B){let M=B||Gn;if(uf(M),!bl(M))Zu(M);if(Nr(null),!(bl(M)?c.current:""))c.current="",U.current+=1,I(""),o(null),x(!0)}async function Cw(){let B=typeof window>"u"?"":window.prompt("输入新的 Codex queue ID(字母/数字/._-,最长 64)","new-lane"),M=String(B||"").trim();if(!M)return;await lr(async()=>{let d=await Rf(xf(l,"/api/queues"),{method:"POST",body:{queueId:M}}),nu=String(d?.queue?.id||M);Zu(nu),uf(nu),Nr(null),c.current="",U.current+=1,I(""),o(null);let Fu=`已创建并切换到 queue:${nu}`;kf(Fu),ur("success",Fu),await Pl("",!0,nu)},"创建 Codex queue 失败")}async function Rw(){let B=String(Tu||"default").trim()||"default",M=Ri(Dr,B)||{id:B,name:B},d=typeof window>"u"?null:window.prompt(`输入 queue 显示名称(ID 不变:${B};留空恢复为 ID)`,$Q(M));if(d===null)return;await lr(async()=>{let nu=await Rf(xf(l,`/api/queues/${encodeURIComponent(B)}`),{method:"PATCH",body:{name:String(d)}}),Fu=nu?.queue||{id:B,name:String(d||B)};if(nu?.summary)Nr((Lu)=>Lu?{...Lu,queue:nu.summary}:Lu);let Ku=`已更新 queue 名称:${p5(Fu)}`;kf(Ku),ur("success",Ku),await Pl(c.current,!0,Xu)},"修改 Codex queue 名称失败")}function xw(){if(b0.length===0){kf("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let B=b0.some((M)=>String(M?.id||"")===Pf)?Pf:"";Sl(B),Jf(!0)}async function hw(){let B=In;if(b0.length===0){kf("没有可合并的其他 queue;请先创建或选择另一个 queue。");return}let d=String(Pf||""||"").trim();if(!d){kf("请先选择要合并的源 queue。");return}if(d===B){Tf("源 queue 和目标 queue 不能相同。");return}await lr(async()=>{let nu=await Rf(xf(l,`/api/queues/${encodeURIComponent(B)}/merge`),{method:"POST",body:{sourceQueueId:d}});if(nu?.summary)Nr((Lu)=>Lu?{...Lu,queue:nu.summary}:Lu);Zu(B),uf(B),Nr(null);let Fu=Number(nu?.mergedTaskCount||0),Ku=`已将 queue=${d} 合并到 ${B},移动 ${Fu} 个任务;源 queue 已自动删除。`;kf(Ku),ur("success",Ku),Jf(!1),Sl(""),await Pl(c.current,!0,B)},"合并 Codex queue 失败")}async function bw(B){if(B.preventDefault(),Q.current){kf("任务正在提交中,请等待当前请求完成,已阻止重复提交。");return}if(Q0.length>1&&!pl){Tf(`检测到将创建 ${Q0.length} 个任务;请先勾选“确认批量入队”,避免误传多个任务。`);return}Q.current=!0,C1(!0),kf("正在提交 Code Queue 任务,请等待后端确认,输入已临时锁定。"),await lr(async()=>{if(Q0.length===0)throw Error("prompt 不能为空");let M=q1(g),d=Tu.trim()||"default",nu=[...Q0],Fu=(Ru)=>({prompt:Ru,queueId:d,providerId:vf,executionMode:dl,model:cu,cwd:Tl,maxAttempts:Number(rl),...M.length>0?{referenceTaskIds:M}:{}}),Ku=nu.length===1?Fu(nu[0]):{tasks:nu.map(Fu)},Lu=await Rf(xf(l,nu.length===1?"/api/tasks":"/api/tasks/batch"),{method:"POST",body:Ku}),Cu=Lu?.tasks?.[0]?.id||"",xu=Array.isArray(Lu?.tasks)?Lu.tasks.map((Ru)=>String(Ru?.id||"")).filter(Boolean):[],mu=`已创建 ${xu.length||nu.length} 个任务${xu.length>0?`:${xu.join(" / ")}`:""}`;if(kf(mu),ur("success",mu),Wu(""),Qu(""),qr(!1),c.current=Cu,Xu!==d)Nr(null);Zu(d),await Pl(Cu,!0,d)},"Codex 任务入队失败"),Q.current=!1,C1(!1)}async function vw(B){if(B.preventDefault(),!b?.id)return;await lr(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/steer`),{method:"POST",body:{prompt:kn}}),R1(""),await Pl(b.id)},"追加 prompt 失败")}async function kw(B){B.preventDefault();let M=String(b?.id||"");if(!M||!g1)return;await lr(async()=>{let d=q1(Yu),nu=await Rf(xf(l,`/api/tasks/${encodeURIComponent(M)}/edit`),{method:"POST",body:{prompt:lu,referenceTaskIds:d}}),Fu={...nu?.task||b||{},_traceSummary:null,_traceSummaryLoaded:!1,_traceSummaryUpdatedAt:"",_promptDetails:{},_traceSteps:[],_traceStepsLoaded:!1,_traceStepsByAttempt:{},_traceStepsLoadedByAttempt:{},_traceStepsNextAfterSeqByAttempt:{},_traceStepDetails:{}};O.current.set(M,{...O.current.get(M)||{},task:Fu,complete:!1,completeUpdatedAt:""}),c.current=M,o(Fu),I(M),Ou(Rt(Fu)),Iu(Array.isArray(Fu?.referenceTaskIds)?Fu.referenceTaskIds.join(" "):""),Nr((Lu)=>{if(!Lu)return Lu;let Cu=jl(Lu).map((xu)=>String(xu?.id||"")===M?{...xu,...Fu}:xu);return{...Lu,queue:nu?.queue||Lu.queue,tasks:Pi([Cu],v1)}});let Ku=nu?.changed===!1?`任务 ${M} 的 prompt 未变化`:`已更新 queued 任务 ${M} 的用户 prompt`;kf(Ku),ur("success",Ku),await Pl(M,!0,Xu)},"编辑 queued 任务 prompt 失败")}async function Iw(){if(!b?.id)return;await lr(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/interrupt`),{method:"POST",body:{}}),await Pl(b.id)},"打断 Codex session 失败")}async function gw(){if(!b?.id)return;await lr(async()=>{await Rf(xf(l,`/api/tasks/${encodeURIComponent(b.id)}/retry`),{method:"POST",body:{}}),await Pl(b.id)},"重新入队失败")}async function sw(B){let M=String(b?.id||""),d=String(B||"").trim();if(!M||!d)return;let nu=p_(b);if(d===nu){kf(`任务 ${M} 已在 queue=${d}`);return}await lr(async()=>{let Ku=(await Rf(xf(l,`/api/tasks/${encodeURIComponent(M)}/move`),{method:"POST",body:{queueId:d}}))?.task||{...b,queueId:d};if(O.current.set(M,{...O.current.get(M)||{},task:Ku}),c.current=M,o(Ku),I(M),Zu(d),!bl(Xu))Nr(null),uf(d);let Lu=`已将任务 ${M} 从 ${nu} 移动到 ${d}`;kf(Lu),ur("success",Lu),await Pl(M,!0,bl(Xu)?Gn:d)},"移动任务 queue 失败")}async function aw(){let B=c.current;if(!B)return;let M=performance.now();await lr(async()=>{sr({phase:"session",taskId:B,queueMs:0,totalMs:0,partial:!0,startedAt:new Date}),await a1(B,!0,M,0)},"刷新 Trace Summary 失败")}function ow(B){c.current=B,U.current+=1,I(B);let M=O.current.get(B);if(M?.task)o(M.task),x(!1);else{x(!0);let d=ar.find((nu)=>nu.id===B);if(d)o(d);else o(null)}Pl(B).catch((d)=>Tf(cl(d,"切换 Codex session 失败")))}function h8(B){if(ow(B),fE())df(!1)}function c7(B,M,d){if(!B||!Array.isArray(B?.tasks)||M.length===0||Object.keys(d).length===0)return B;let nu=!1,Fu=jl(B).map((Ku)=>{if(String(Ku?.id||"")!==M)return Ku;return nu=!0,o$(uQ(Ku,d))});return nu?{...B,tasks:Fu}:B}function dw(B,M){Nr((d)=>c7(d,B,M)),ju((d)=>c7(d,B,M))}function ew(B,M,d){let nu=String(B?.type||"");if(nu==="queue-updated")return!0;if(nu==="trace-stats-updated"||nu==="trace-step-created")return!1;if(M.length===0)return!0;if(!d)return!0;if(B?.queueId&&String(B.queueId)!==p_(d))return!0;if(B?.status&&String(B.status)!==String(d?.status||""))return!0;return String(B?.reason||"")!=="output"}function j7(){if(!i||!Z5())return;if(H.current!==null)window.clearTimeout(H.current);H.current=window.setTimeout(()=>{H.current=null,Pl(c.current,!1).catch((B)=>Tf(cl(B,"Code Queue 事件刷新失败")))},120)}function uK(B,M){if(!i||!Z5()||c.current!==B)return;if(D.current=D.current||M,E.current!==null)return;E.current=window.setTimeout(()=>{E.current=null;let d=D.current;if(D.current=!1,a1(B,!0).catch((nu)=>Tf(cl(nu,"事件刷新 Trace Summary 失败"))),d)pw(B)},250)}function fK(B){let M=Lf(B?.payload)||B,d=Lf(M?.stats),nu=String(B?.type||M?.type||""),Fu=String(M?.subjectKind||d?.subjectKind||""),Ku=String(M?.scopeId||d?.scopeId||""),Lu=String(M?.taskId||(Fu==="task"?M?.subjectId:"")||d?.taskId||B?.taskId||""),Cu=M?.attemptIndex??d?.attemptIndex,xu=Cu===null||Cu===void 0||Cu===""?null:D0(Cu),mu=d||Lf(M?.traceStats),Ru=mu?.stepCount??mu?.llmStepCount,jf=mu?.outputMaxSeq;return{...M,type:nu,eventId:B?.eventId||M?.eventId,sequence:B?.sequence??M?.sequence,taskId:Lu,subjectKind:Fu,scopeId:Ku,attemptIndex:xu,stepCount:Ru,outputMaxSeq:jf,updatedAt:mu?.updatedAt||M?.updatedAt||B?.createdAt,traceStats:mu,statsSource:mu?"oa-event-flow":M?.statsSource}}function lK(B){let M=fK(B),d=String(M?.taskId||""),nu=String(M?.scopeId||M?.traceStats?.scopeId||""),Fu=String(M?.subjectKind||M?.traceStats?.subjectKind||"")==="task-attempt"||Number(M?.attemptIndex)>0||/:attempt:\d+$/u.test(nu),Ku=sU(M?.stepCount),Lu={},Cu=d.length>0?jl(m.current).find((xu)=>String(xu?.id||"")===d):null;if(d.length>0){if(M?.status)Lu.status=String(M.status);if(M?.updatedAt)Lu.updatedAt=String(M.updatedAt);if(M?.queueId)Lu.queueId=String(M.queueId);if(!Fu&&Number.isFinite(Number(M?.stepCount)))Lu.stepCount=Ku,Lu.llmStepCount=Ku;if(!Fu&&Number.isFinite(Number(M?.outputMaxSeq)))Lu.outputMaxSeq=sU(M.outputMaxSeq);if(!Fu&&Lf(M?.traceStats))Lu.traceStats=M.traceStats,Lu.statsSource="oa-event-flow";if(Object.keys(Lu).length>0&&(O.current.has(d)||c.current===d))q0(d,Lu,U.current);if(Object.keys(Lu).length>0)dw(d,Lu);if(c.current===d&&(M?.type==="trace-step-created"||M?.type==="task-updated"||M?.type==="trace-stats-updated")){let xu=jQ(Cu),mu=M?.type==="trace-step-created"||M?.type==="trace-stats-updated"&&!Fu&&Number.isFinite(Number(M?.stepCount))&&(xu===null||Ku>xu);uK(d,mu)}}if(ew(M,d,Cu))j7()}wn(()=>{if(V.current){V.current=!1;return}lr(()=>Pl(c.current),"Code Queue 加载失败")},[i?.id,Xu]),wn(()=>{if(!i||typeof EventSource>"u")return;let B=new EventSource(aT(l),{withCredentials:!0}),M=(nu)=>{try{lK(JSON.parse(String(nu.data||"{}")))}catch(Fu){Tf(cl(Fu,"解析 Code Queue 事件失败"))}},d=()=>{if(Z5())j7()};return B.addEventListener("trace-step-created",M),B.addEventListener("task-updated",M),B.addEventListener("queue-updated",M),B.addEventListener("trace-stats-updated",M),document.addEventListener("visibilitychange",d),()=>{if(B.close(),document.removeEventListener("visibilitychange",d),H.current!==null)window.clearTimeout(H.current),H.current=null;if(E.current!==null)window.clearTimeout(E.current),E.current=null}},[i?.id,l,Xu]),wn(()=>{if(!i||!b||s)return;let B=String(b.id||"");if(!B)return;let M=String(b.updatedAt||"");if(Pt(b))return;let d=`${B}:${M||"unknown"}:${String(b?._traceSummaryUpdatedAt||"")}`;if(Z.current.has(d))return;Z.current.add(d),a1(B,!0).catch((nu)=>Tf(cl(nu,"自动加载 Trace Summary 失败")))},[i?.id,b?.id,b?.updatedAt,b?.traceStats?.statsRevision,b?._traceSummaryUpdatedAt,b?._traceSummaryLoaded,s]);let rK=fr.length===0?K(w1,{title:Ul?Gu?"搜索中":"没有匹配任务":"队列为空",text:Ul?Gu?`正在搜索包含“${sn}”的 task...`:`未找到包含“${sn}”的 task;可换个关键词或切换 queue。`:"提交一个任务后,Codex 会串行执行并保存输出。"}):[r7.length>0?K(X5,{key:"unread",title:"已结束未读",tasks:r7,selectedId:k,emptyText:"暂无已结束未读任务。",onSelect:h8,onCopy:C8,onReference:R8,onMarkRead:x8,copiedTaskId:Wy,markingReadTaskId:x1}):null,K(X5,{key:"active",title:"运行 / 排队",tasks:Kw,selectedId:k,emptyText:"当前没有运行或排队任务。",onSelect:h8,onCopy:C8,onReference:R8,onMarkRead:x8,copiedTaskId:Wy,markingReadTaskId:x1}),K(X5,{key:"history",title:"历史 session",tasks:Gw,selectedId:k,emptyText:"最近没有完成、失败或取消的 session。",onSelect:h8,onCopy:C8,onReference:R8,onMarkRead:x8,copiedTaskId:Wy,markingReadTaskId:x1}),K("div",{key:"pagination",className:"codex-task-pagination","data-testid":"codex-task-pagination"},K("span",null,Ul?`搜索“${sn}” · 已显示 ${fr.length} / ${Number.isFinite(I1)?I1:fr.length}`:`已加载 ${fr.length} / ${Number.isFinite(I1)?I1:fr.length}`),i7?K("button",{type:"button",className:"ghost-btn",disabled:S8,onClick:()=>void A7(),"data-testid":"codex-load-more-tasks-button"},S8?"加载中":Ul?"加载更多结果":"加载更早任务"):K("code",null,Ul?"已到结果末尾":"已到队列末尾"))],F7=(B,M=!1)=>K("label",{className:`code-queue-switcher ${M?"compact":""}`},K("span",null,M?"Queue":"查看 queue"),K("select",{value:Xu,onChange:(d)=>Mw(String(d.target.value||Gn)),"data-testid":B},K("option",{value:Gn},`All queues · ${Number.isFinite(gn)?gn:ar.length} tasks · ${Gy.length} running`),Dr.map((d)=>K("option",{key:String(d?.id||""),value:String(d?.id||"")},S_(d))))),nK=K("div",{className:"codex-task-search","data-testid":"codex-task-search"},K("label",{htmlFor:"codex-task-search-input"},"搜索 task"),K("div",{className:"codex-task-search-row"},K("input",{id:"codex-task-search-input",type:"search",value:fu,placeholder:"关键词 / task ID / prompt",autoComplete:"off",onChange:(B)=>$u(String(B.target.value||"")),"data-testid":"codex-task-search-input"}),fu?K("button",{type:"button",className:"ghost-btn",onClick:()=>$u(""),"data-testid":"codex-task-search-clear"},"清除"):null),K("small",{"data-testid":"codex-task-search-summary"},Ul?Gu?"搜索中...":`匹配 ${fr.length}/${Number.isFinite(I1)?I1:fr.length}`:"支持 task ID、prompt、状态、provider、模型和最近输出关键词")),iK=K("div",{className:"codex-trace-status","data-testid":"codex-trace-status-summary"},K("span",{className:"codex-trace-status-chip queued"},K("b",null,"排队"),String(X8)),K("span",{className:"codex-trace-status-chip running"},K("b",null,"运行"),String(g$)),K("span",{className:`codex-trace-status-chip unread ${U0>0?"warn":""}`},K("b",null,"结束未读"),String(U0)),K("span",{className:"codex-trace-status-chip service"},K("b",null,"服务"),`${zw.providerStatus||"unknown"} · ${i?.providerId||"main-server"} · ${Tw.public?"公网暴露":"仅 UniDesk frontend 代理访问"}`),K("span",{className:"codex-trace-status-chip"},K("b",null,"执行节点"),a$.map((B)=>B.id).join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"执行模式"),$7.map((B)=>B.id).join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"模型"),_7.join(" / ")),K("span",{className:"codex-trace-status-chip"},K("b",null,"加载"),ml?.phase==="complete"?IT(ml?.totalMs):String(ml?.phase||"idle")),K("span",{className:"codex-trace-status-chip"},K("b",null,"刷新"),h$?tf(h$):"--")),yK=K(Mi,{title:b?`Trace ${String(b.id).slice(0,22)}`:"Trace 输出",eyebrow:b?`${b.status} / view=${k1} / task queue=${p_(b)} / provider=${b.providerId||"main-server"} / mode=${b.executionMode||"default"} / ${b.model} / agent loop trace`:`Agent loop trace / view=${k1}`,summary:iK,loading:s||wy||Gu||P||ml?.phase==="loading",actions:K("div",{className:"panel-actions"},F7("code-queue-filter-select"),K("button",{type:"button",className:"ghost-btn codex-mark-all-read-btn",disabled:U0===0||$f||h1,onClick:()=>void Pw(),"data-testid":"codex-mark-all-read-button"},h1?"标记中":`全部标已读${U0>0?` (${U0})`:""}`),b?K("button",{type:"button",className:"ghost-btn",disabled:s||$f,onClick:()=>void aw(),"data-testid":"codex-load-full-trace-button"},s?"加载中":cr(b)?"刷新 Summary":"加载 Summary"):null,K("button",{type:"button",className:"codex-session-title-toggle",onClick:()=>df((B)=>!B),"data-testid":"code-queue-sidebar-toggle"},ff?"收起队列":"展开队列"),K("label",{className:"inline-check"},K("input",{type:"checkbox",checked:Qf,onChange:(B)=>il(Boolean(B.target.checked))}),"自动滚动"),K("button",{type:"button",className:"ghost-btn",disabled:!Ow||$f,onClick:()=>void Iw(),"data-testid":"codex-interrupt-button"},"打断"),K("button",{type:"button",className:"ghost-btn",disabled:!Hw||$f,onClick:()=>void gw()},"重试"),b?K(_Q,{title:"Codex Task",data:b,onOpen:f,testId:"raw-codex-task"}):null),className:"codex-output-panel"},K("div",{className:`codex-session-shell ${ff?"":"queue-collapsed"}`},ff?K("aside",{className:"codex-session-sidebar","data-testid":"codex-session-sidebar"},K("div",{className:"codex-session-sidebar-head"},K("div",null,K("span",null,bl(Xu)?"All queues":"Queue lane"),K("strong",null,`${k1} · ${ar.length}/${Number.isFinite(gn)?gn:ar.length} sessions · 未读 ${U0}`)),K("button",{type:"button",className:"ghost-btn",onClick:()=>df(!1)},"收起")),F7("code-queue-filter-sidebar",!0),nK,K("div",{className:"codex-task-list codex-task-list-session",onScroll:mw,"data-testid":"codex-task-list-scroll"},rK)):null,K("div",{className:"codex-session-main"},K("div",{className:"codex-output-stack"},K(cZ,{task:b,loading:s,onLoadPromptPart:Yw,onLoadSteps:M8,onLoadStep:Sw}),K(jZ,{task:b})))));if(!i)return K(w1,{title:"Code Queue 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=code-queue"});let J7=Number(ml?.totalMs),U7=Number(ml?.queueMs),Q7=Number(ml?.detailMs),q7=Number(ml?.transcriptRows),_K=ml?.phase==="complete"?"complete":String(ml?.phase||"idle"),$K=Ri(Dr,In)||{id:In,name:In},tK=_f?K(RU,{title:"合并 queue",titleId:"codex-merge-dialog-title",className:"codex-merge-dialog",backdropClassName:"codex-merge-dialog-backdrop",bodyClassName:"codex-merge-dialog-body",actionsClassName:"codex-merge-dialog-actions",testId:"codex-merge-queue-dialog",closeTestId:"codex-merge-queue-close",disableClose:$f,onClose:()=>Jf(!1),actions:[K("button",{key:"cancel",type:"button",className:"ghost-btn",onClick:()=>Jf(!1),disabled:$f,"data-testid":"codex-merge-queue-cancel"},"取消"),K("button",{key:"confirm",type:"button",className:"primary-btn",onClick:()=>void hw(),disabled:$f||rf||!Pf,"data-testid":"codex-merge-queue-confirm"},$f?"合并中...":"确认合并")]},K("p",{className:"codex-merge-dialog-target"},"目标 queue:",K("code",null,S_($K))),K("label",null,"源 queue",K("select",{value:Pf,disabled:$f||rf,onChange:(B)=>Sl(String(B.target.value||"")),"data-testid":"codex-merge-source-queue-select"},K("option",{value:""},"选择要合并进来的源 queue"),b0.map((B)=>K("option",{key:String(B?.id||""),value:String(B?.id||"")},S_(B))))),K("p",{className:"codex-merge-dialog-note"},"会把源 queue 的任务归属合并到目标 queue,并自动删除源 queue;目标 queue 会按原 queueEnteredAt/createdAt 时间顺序运行。")):null;return K("div",{className:`code-queue-page ${n?"codex-standalone-page":""}`,"data-testid":"code-queue-page","data-load-state":_K,"data-load-total-ms":Number.isFinite(J7)?String(Math.round(J7*10)/10):"","data-load-queue-ms":Number.isFinite(U7)?String(Math.round(U7*10)/10):"","data-load-detail-ms":Number.isFinite(Q7)?String(Math.round(Q7*10)/10):"","data-load-transcript-rows":Number.isFinite(q7)?String(q7):"","data-load-task-id":String(ml?.taskId||k||""),"data-load-partial":ml?.partial?"true":"false"},K(yf,{error:V8,wide:!0}),tK,K("div",{className:"codex-session-stage codex-session-stage-top"},yK),K("div",{className:"code-queue-layout"},K("div",{className:"codex-left-rail"},K(Mi,{title:"提交任务",eyebrow:rf?"Submitting...":Q0.length>1?`${Q0.length} tasks`:"Single or Batch",className:"codex-compose-panel",loading:rf},K("form",{className:`codex-task-form ${rf?"is-submitting":""}`,onSubmit:bw,"data-testid":"code-queue-task-form","aria-busy":rf?"true":"false"},K("label",null,"Prompt / 多任务用单独一行 --- 分隔",K("textarea",{value:uu,rows:8,disabled:rf,onChange:(B)=>Wu(B.target.value),placeholder:"写入 Codex 任务;多个任务之间用 --- 分隔。"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选)",K("input",{value:g,disabled:rf,onChange:(B)=>Qu(B.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-reference-task-id"}),q1(g).length>0?K("code",null,`后端将解析并注入:${q1(g).join(" / ")}`):null),K("div",{className:"codex-form-grid"},K("label",{className:"codex-submit-queue-field"},"Queue",K("div",{className:"codex-submit-queue-row"},K("select",{className:"codex-submit-queue-select",value:Tu,disabled:rf,onChange:(B)=>Zu(String(B.target.value||"default")),"data-testid":"code-queue-id-select"},Dr.map((B)=>K("option",{key:String(B?.id||""),value:String(B?.id||"")},S_(B)))),K("button",{type:"button",className:"ghost-btn codex-rename-queue-btn",onClick:()=>void Rw(),disabled:$f||rf||!Tu,title:"修改当前 queue 的显示名称,ID 不变","data-testid":"codex-rename-queue-button"},"改名"),K("button",{type:"button",className:"ghost-btn codex-merge-queue-btn",onClick:()=>xw(),disabled:$f||rf||b0.length===0,title:"打开独立窗口选择源 queue 并合并到当前 queue;合并后自动删除源 queue","data-testid":"codex-merge-queue-button"},"合并 queue"),K("button",{type:"button",className:"ghost-btn codex-create-queue-btn",onClick:()=>void Cw(),disabled:$f||rf,"data-testid":"codex-create-queue-button"},"创建 queue"))),K("label",null,"模型",K("select",{value:cu,disabled:rf,onChange:(B)=>ku(B.target.value),"data-testid":"codex-model-select"},_7.map((B)=>K("option",{key:B,value:B},B)))),K("label",null,"执行 Provider",K("select",{value:vf,disabled:rf,onChange:(B)=>Dw(String(B.target.value||"main-server")),"data-testid":"codex-provider-select"},a$.map((B)=>K("option",{key:B.id,value:B.id},`${B.label||B.id} · ${B.defaultWorkdir||I5(pf,B.id)}${B.supportsWindowsNativeCodex?" · Windows native":""}`)))),K("label",null,"执行模式",K("select",{value:dl,disabled:rf,onChange:(B)=>Xw(String(B.target.value||"default")),"data-testid":"codex-execution-mode-select"},$7.map((B)=>K("option",{key:B.id,value:B.id},`${B.label||B.id}${B.id==="windows-native"?" · 宿主 Codex":""}`)))),K("label",null,"工作目录",K("input",{value:Tl,disabled:rf,onChange:(B)=>pu(B.target.value),placeholder:Zw||pf?.defaultWorkdir||"/root/unidesk","data-testid":"codex-cwd-input"})),K("label",null,"最大尝试",K("input",{type:"number",min:1,max:99,value:rl,disabled:rf,onChange:(B)=>El(Number(B.target.value)),"data-testid":"codex-max-attempts-input"})),K("label",null,"入队份数",K("input",{type:"number",min:1,max:50,value:Jl,disabled:rf,onChange:(B)=>nl(Number(B.target.value)),"data-testid":"codex-repeat-count-input"}))),Ty>1?K("label",{className:`codex-batch-confirm ${pl?"confirmed":""}`,"data-testid":"codex-batch-confirm-row"},K("input",{type:"checkbox",checked:pl,disabled:rf,onChange:(B)=>qr(Boolean(B.target.checked)),"data-testid":"codex-batch-confirm-checkbox"}),K("span",null,`确认批量入队 ${Ty} 个任务(prompt 分段 ${p8.length} × 入队份数 ${gU(Jl)})`)):null,rf?K("div",{className:"codex-submit-wait","data-testid":"codex-submit-wait"},"正在提交到后端,已锁定输入以防重复提交..."):null,K("div",{className:"codex-form-actions"},K("button",{type:"button",className:"ghost-btn",disabled:$f||rf||uu.length===0&&g.length===0,onClick:()=>{Wu(""),Qu(""),qr(!1);let B="已清空任务输入栏";kf(B),ur("success",B)},"data-testid":"codex-clear-input-button"},"清空输入"),K("button",{type:"submit",className:"primary-btn",disabled:Ew,"data-testid":"codex-enqueue-button"},rf?"提交中,请等待...":y7?`请确认批量入队 ${Ty} 个任务`:Q0.length>1?`批量入队 ${Q0.length} 个任务`:"入队并运行"))))),K("div",{className:"codex-main-stage"},K("div",{className:"codex-detail-grid"},K(Mi,{title:"运行控制",eyebrow:g1?"Queued prompt editable":m8?"Active turn steer":"Steer when running",loading:$f},K("div",{className:"codex-run-control-stack"},K(yZ,{task:b,queueRows:Dr,busy:$f,onMove:sw}),b?.id?K("form",{className:"codex-steer-form codex-edit-prompt-form",onSubmit:kw,"data-testid":"codex-edit-prompt-form"},K("label",null,"编辑 queued 用户 prompt",K("textarea",{value:lu,rows:5,onChange:(B)=>Ou(B.target.value),placeholder:"仅 QUEUED 且尚未开始运行的任务可在这里修改原始用户 prompt。",disabled:!g1||$f,"data-testid":"codex-edit-prompt-textarea"})),K("label",{className:"codex-reference-field"},"引用任务 ID(可选,留空会清除引用)",K("input",{value:Yu,disabled:!g1||$f,onChange:(B)=>Iu(B.target.value),placeholder:"codex_...;支持空格/逗号分隔多个 ID","data-testid":"codex-edit-reference-task-id"}),q1(Yu).length>0?K("code",null,`将保留/注入:${q1(Yu).join(" / ")}`):null),K("div",{className:"codex-form-actions"},K("button",{type:"button",className:"ghost-btn",disabled:!b?.id||$f,onClick:()=>{Ou(b?Rt(b):""),Iu(Array.isArray(b?.referenceTaskIds)?b.referenceTaskIds.join(" "):"")},"data-testid":"codex-edit-prompt-reset"},"恢复当前值"),K("button",{type:"submit",className:"primary-btn",disabled:!g1||$f||lu.trim().length===0,title:g1?"保存后会重写尚未运行任务的用户 prompt":"只有 QUEUED 且尚未开始的任务可编辑 prompt","data-testid":"codex-edit-prompt-submit"},"保存 queued prompt"))):null,K("form",{className:"codex-steer-form",onSubmit:vw},K("label",null,"追加 prompt",K("textarea",{value:kn,rows:4,onChange:(B)=>R1(B.target.value),placeholder:"给正在运行的 Codex session 推入新的指令或纠偏。",disabled:!m8})),K("button",{type:"submit",className:"primary-btn",disabled:!m8||$f||kn.trim().length===0,"data-testid":"codex-steer-button"},"推入运行中 session")))),K(Mi,{title:"完成判定",eyebrow:b?.lastJudge?b.lastJudge.source:"judge",loading:s},b?.lastJudge?K("div",{className:"codex-judge-card","data-testid":"codex-task-judge-card"},K(L1,{status:b.lastJudge.decision},b.lastJudge.decision),K("strong",null,`${Math.round(Number(b.lastJudge.confidence||0)*100)}% confidence`),K("p",{"data-testid":"codex-task-judge-reason"},Y5(b.lastJudge.reason||"--",180)),K(UQ,{judge:b.lastJudge,testId:"codex-task-judge-failure-details"}),b.lastJudge.continuePrompt?K("code",{"data-testid":"codex-task-judge-continue-prompt"},Y5(b.lastJudge.continuePrompt,160)):null):K(w1,{title:"尚未判定",text:"Codex turn 结束后会由 MiniMax M2.7 或 fallback judge 判定 complete/retry/fail;retry 会在已有 thread 追加继续执行 prompt。"}))),K(iZ,{stats:D8,queueName:k1,onRaw:f}),K(Mi,{title:"Attempts",eyebrow:"terminal vs interruption",loading:s},K(FZ,{task:b})))))}var M_=Pu(qf(),1);var Bu=M_.default.createElement,{useEffect:g5}=M_.default,s5=M_.default.useState,JZ=M_.default.useRef,o5=` :root { --surfacePrimary: #ffffff; --surfaceSecondary: #f8fafc; @@ -224,64 +226,64 @@ nav .material-icons::before { display: none !important; } } -`;function gc({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Bu("section",{className:`panel ${n||""}`},Bu("div",{className:"panel-head"},Bu("div",null,f?Bu("p",{className:"panel-eyebrow"},f):null,Bu(nf,{title:u,loading:i})),l?Bu("div",{className:"panel-actions"},l):null),Bu("div",{className:"panel-body"},r))}function iZ({title:u,data:f,onOpen:l,testId:r}){return Bu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function yZ({title:u,text:f}){return Bu("div",{className:"empty-state"},Bu("strong",null,u),Bu("span",null,f))}function GQ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function zQ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function TQ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function _Z(u){return u.filter((l)=>l?.id==="filebrowser"||String(l?.id||"").startsWith("filebrowser-")).sort((l,r)=>{let n=(i)=>i.providerId==="D518"?0:i.providerId==="D601"?1:i.id==="filebrowser"?2:3;return n(l)-n(r)||String(l.id).localeCompare(String(r.id))})}function $Z(u){if(u?.providerId==="D518")return"D518";return u?.providerId||u?.name||u?.id||"Unknown"}function tZ(u,f,l="/"){let r=l.startsWith("/")?l:`/${l}`;return`${u}/microservices/${encodeURIComponent(f)}/proxy${r}`}function cZ(u,f){return`${u}/microservices/${encodeURIComponent(f)}/health`}async function AZ(u,f=16000){let l=new AbortController,r=setTimeout(()=>l.abort(),f);try{return await Eu(u,{signal:l.signal,failureFields:[!1]})}finally{clearTimeout(r)}}function EQ(u){if(u?.providerId==="main-server")return"host / -> /srv";if(u?.providerId==="D601"||u?.providerId==="D518")return"WSL / + /mnt/c -> /srv";return"provider / -> /srv"}function v3(u){return u?.status==="OK"||u?.ok===!0}function jZ({service:u,active:f,health:l,onSelect:r,onRaw:n}){let i=GQ(u),y=zQ(u),_=TQ(u),$=i.container||{},c=v3(l?.body);return Bu("button",{type:"button",className:`filebrowser-target-card ${f?"active":""}`,"data-testid":`filebrowser-target-card-${u.id}`,onClick:r},Bu("span",{className:`status-badge ${c?"ok":i.providerStatus==="online"?"running":"warn"}`},c?"Health OK":i.providerStatus||"unknown"),Bu("strong",null,u.name||u.id),Bu("span",null,EQ(u)),Bu("code",null,`${y.nodeBindHost||"--"}:${y.nodePort||"--"}`),Bu("small",null,$.name?`${$.name} / ${$.state||"--"}`:`${_.composeService||"--"}`),Bu("span",{className:"filebrowser-card-raw",onClick:(A)=>{A.stopPropagation(),n(`${u.name} service`,u)}},"JSON"))}function ZQ(u){try{return u?.contentDocument||u?.contentWindow?.document||null}catch{return null}}function ac(u){let f=ZQ(u);if(f===null||f.head===null)return!1;let l=f.getElementById("unidesk-filebrowser-compact-style");if(l===null)l=f.createElement("style"),l.id="unidesk-filebrowser-compact-style",f.head.appendChild(l);if(l.textContent!==sc)l.textContent=sc;return!0}function FZ(u,f){let l=URL.createObjectURL(u),r=document.createElement("a");r.href=l,r.download=f,document.body.appendChild(r),r.click(),r.remove(),setTimeout(()=>URL.revokeObjectURL(l),2000)}function JZ(u,f){let l=ZQ(u);if(l===null||l.documentElement===null)throw Error("无法访问 File Browser iframe 文档");ac(u);let r=Math.max(640,Math.ceil(u.clientWidth||l.documentElement.clientWidth||1280)),n=Math.max(480,Math.ceil(u.clientHeight||l.documentElement.clientHeight||720)),i=l.documentElement.cloneNode(!0);i.querySelectorAll("script, style, link[rel='stylesheet'], link[rel='preload'], link[rel='icon']").forEach((A)=>A.remove()),i.querySelectorAll("img").forEach((A)=>{A.removeAttribute("src"),A.removeAttribute("srcset")});let y=i.querySelector("head");if(y===null)y=l.createElement("head"),i.insertBefore(y,i.firstChild);let _=l.createElement("style");_.textContent=`${sc} -html,body{width:${r}px!important;min-height:${n}px!important;overflow:hidden!important;}`,y.appendChild(_);let $=new XMLSerializer().serializeToString(i),c=`${$}`;FZ(new Blob([c],{type:"image/svg+xml;charset=utf-8"}),f.replace(/\.png$/i,".svg"))}function OQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=_Z(Array.isArray(u)?u:[]),n=new URLSearchParams(window.location.search).get("target")||"",i=n==="filebrowser-d518"?"filebrowser":n,y=r.some((Z)=>Z.id===i)?i:r[0]?.id||"",[_,$]=Ic(y),[c,A]=Ic({loading:!1,refreshedAt:null,health:{},error:""}),[j,F]=Ic({exporting:!1,message:"",error:""}),U=nZ(null),Q=r.find((Z)=>Z.id===_)||r[0]||null,w=GQ(Q),L=zQ(Q),J=TQ(Q),N=Q?c.health[Q.id]:null,q=Q?tZ(l,Q.id,"/"):"about:blank";kc(()=>{if(r.length===0)return;if(!_||!r.some((Z)=>Z.id===_))$(r[0].id)},[r.map((Z)=>Z.id).join(",")]),kc(()=>{let Z=0,H=setInterval(()=>{if(Z+=1,ac(U.current)||Z>=24)clearInterval(H)},500);return()=>clearInterval(H)},[q]),kc(()=>{if(r.length===0)return;let Z=!1;async function H(){A((h)=>({...h,loading:!0,error:""}));let D=await Promise.all(r.map(async(h)=>{try{let B=await AZ(cZ(l,h.id));return[h.id,{ok:!0,body:B}]}catch(B){return[h.id,{ok:!1,error:Hu(B,"File Browser health failed")}]}}));if(Z)return;A({loading:!1,refreshedAt:new Date().toISOString(),health:Object.fromEntries(D),error:""})}H();let E=setInterval(H,30000);return()=>{Z=!0,clearInterval(E)}},[r.map((Z)=>`${Z.id}:${Z.runtime?.providerStatus||""}`).join(","),l]);function W(Z){$(Z);let H=new URL(window.location.href);H.searchParams.set("target",Z),window.history.replaceState({},"",`${H.pathname}${H.search}`)}async function z(){if(j.exporting)return;F({exporting:!0,message:"",error:""});try{let Z=new Date().toISOString().replace(/[-:.TZ]/g,"").slice(0,14);await JZ(U.current,`unidesk-filebrowser-${Q?.id||"target"}-${Z}.png`),F({exporting:!1,message:"截图已导出",error:""})}catch(Z){F({exporting:!1,message:"",error:Hu(Z,"截图导出失败")})}}if(r.length===0)return Bu(yZ,{title:"File Browser 未登记",text:"请在 config.json 的 microservices 中登记 id=filebrowser 或 filebrowser-* 用户服务"});return Bu("div",{className:"filebrowser-page","data-testid":"filebrowser-page"},c.error?Bu(yf,{error:c.error,wide:!0}):null,Bu(gc,{title:"文件管理器",eyebrow:"File Browser / Host Files",loading:c.loading,actions:Bu("div",{className:"panel-actions"},Q?Bu("button",{type:"button",className:"ghost-btn",onClick:z,disabled:j.exporting,"data-testid":"filebrowser-export-screenshot"},j.exporting?"导出中...":"导出截图"):null,Q?Bu("a",{className:"ghost-btn",href:q,target:"_blank",rel:"noreferrer"},"新窗口打开"):null,Q?Bu(iZ,{title:"File Browser 当前目标",data:{service:Q,health:N},onOpen:f,testId:"raw-filebrowser-active"}):null)},Bu("div",{className:"filebrowser-hero"},Bu("div",null,Bu("span",{className:`status-badge ${v3(N?.body)?"ok":"warn"}`},v3(N?.body)?"Health OK":"Health Pending"),Bu("h3",null,Q?.name||"File Browser"),Bu("p",{className:"muted paragraph"},Q?.description||"通过 UniDesk 登录态代理访问,不开放 File Browser 公网端口。"),j.error?Bu("p",{className:"filebrowser-shot-error"},j.error):null,j.message?Bu("p",{className:"filebrowser-shot-ok"},j.message):null),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Provider"),Bu("strong",null,Q?.providerId||"--"),Bu("code",null,w.providerName||Q?.providerId||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Private Backend"),Bu("strong",null,`${L.nodeBindHost||"--"}:${L.nodePort||"--"}`),Bu("code",null,L.nodeBaseUrl||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Image"),Bu("strong",null,J.dockerfile||"filebrowser/filebrowser:v2.63.3"),Bu("code",null,J.commitId||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Mount"),Bu("strong",null,EQ(Q)),Bu("code",null,Q?.providerId==="main-server"?"/root, /var, /home":"/home, /mnt/c, /mnt/d")))),Bu(gc,{title:"浏览目标",eyebrow:`${r.length} host targets`,loading:c.loading},Bu("div",{className:"filebrowser-target-grid"},r.map((Z)=>Bu(jZ,{key:Z.id,service:Z,active:Z.id===Q?.id,health:c.health[Z.id],onSelect:()=>W(Z.id),onRaw:f})))),Bu(gc,{title:`${$Z(Q)} 文件视图`,eyebrow:N?.body?`Health ${v3(N.body)?"OK":"UNKNOWN"} / ${c.refreshedAt?$f(c.refreshedAt):"--"}`:"Embedded WebUI",className:"filebrowser-frame-panel"},Bu("div",{className:"filebrowser-frame-shell"},Bu("div",{className:"filebrowser-frame-toolbar"},Bu("span",null,"BaseURL"),Bu("code",null,`/api/microservices/${Q?.id||"filebrowser"}/proxy`),Bu("span",null,"Root"),Bu("code",null,"/srv"),Bu("span",{className:"filebrowser-compact-note"},"Compact layout injected")),Bu("iframe",{ref:U,key:q,title:`${Q?.name||"File Browser"} WebUI`,src:q,className:"filebrowser-frame","data-testid":"filebrowser-frame",onLoad:(Z)=>ac(Z.currentTarget),sandbox:"allow-downloads allow-forms allow-modals allow-same-origin allow-scripts"}))))}var s3=Mu(Qf(),1);var Fu=s3.default.createElement,{useEffect:UZ}=s3.default,QZ=s3.default.useState;function k3({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return Fu("span",{className:`status-badge ${l}`},f||u||"unknown")}function En({label:u,value:f,hint:l,tone:r}){return Fu("article",{className:`metric-card ${r||""}`},Fu("div",{className:"metric-label"},u),Fu("div",{className:"metric-value"},f),Fu("div",{className:"metric-hint"},l))}function I3({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Fu("section",{className:`panel ${n||""}`},Fu("div",{className:"panel-head"},Fu("div",null,f?Fu("p",{className:"panel-eyebrow"},f):null,Fu(nf,{title:u,loading:i})),l?Fu("div",{className:"panel-actions"},l):null),Fu("div",{className:"panel-body"},r))}function g3({title:u,data:f,onOpen:l,testId:r}){return Fu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function oc({title:u,text:f}){return Fu("div",{className:"empty-state"},Fu("strong",null,u),Fu("span",null,f))}function qZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function NZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function WZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function z1(u,f){let l=u&&typeof u==="object"?u[f]:void 0;return Number.isFinite(Number(l))?String(l):"--"}function wZ(u){return(Array.isArray(u?.jobs)?u.jobs:[]).slice(0,40)}function LZ(u){return(Array.isArray(u?.drafts)?u.drafts:[]).slice(0,12)}function HQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((Q)=>Q.id==="findjob")||null,[n,i]=QZ({loading:!1,error:"",health:null,summary:null,jobs:null,drafts:null,refreshedAt:null});async function y(){if(!r)return;i((Q)=>({...Q,loading:!0,error:""}));try{let[Q,w,L,J]=await Promise.all([Eu(`${l}/microservices/findjob/health`),Eu(`${l}/microservices/findjob/proxy/api/summary`),Eu(`${l}/microservices/findjob/proxy/api/jobs?__unideskArrayLimit=jobs:40`),Eu(`${l}/microservices/findjob/proxy/api/drafts`)]);i({loading:!1,error:"",health:Q,summary:w,jobs:L,drafts:J,refreshedAt:new Date})}catch(Q){i((w)=>({...w,loading:!1,error:Hu(Q,"FindJob 加载失败")}))}}if(UZ(()=>{y()},[r?.id,r?.runtime?.providerStatus]),!r)return Fu(oc,{title:"FindJob 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=findjob"});let _=qZ(r),$=WZ(r),c=NZ(r),A=n.summary||{},j=wZ(n.jobs),F=LZ(n.drafts),U=n.jobs?._unidesk?.arrayLimits?.jobs;return Fu("div",{className:"findjob-page","data-testid":"findjob-page"},Fu(I3,{title:"FindJob 工作台",eyebrow:"D601 用户服务",loading:n.loading,actions:Fu("div",{className:"panel-actions"},Fu("button",{type:"button",className:"ghost-btn",onClick:y,disabled:n.loading,"data-testid":"findjob-refresh-button"},n.loading?"刷新中":"刷新"),Fu(g3,{title:"FindJob 用户服务",data:r,onOpen:f,testId:"raw-findjob-service"}))},Fu("div",{className:"findjob-hero"},Fu("div",null,Fu("div",{className:"node-version-line"},Fu(k3,{status:_.providerStatus==="online"?"online":"warn"},_.providerStatus||"unknown"),Fu("span",null,r.providerId),Fu("span",null,c.public?"公网暴露":"仅 UniDesk frontend 代理访问")),Fu("p",{className:"muted paragraph"},r.description)),Fu("div",{className:"microservice-ref-card"},Fu("span",null,"Repo"),Fu("strong",null,$.url||"--"),Fu("code",null,$.commitId||"--")),Fu("div",{className:"microservice-ref-card"},Fu("span",null,"D601 Docker"),Fu("strong",null,`${c.nodeBindHost||"--"}:${c.nodePort||"--"}`),Fu("code",null,`${$.composeFile||"--"} / ${$.composeService||"--"}`))),Fu(yf,{error:n.error,wide:!0})),Fu("div",{className:"findjob-grid"},Fu(I3,{title:"岗位指标",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Summary",loading:n.loading},Fu("div",{className:"metric-grid"},Fu(En,{label:"岗位总量",value:z1(A,"totalJobs"),hint:"tracked jobs",tone:"ok"}),Fu(En,{label:"原始岗位",value:z1(A,"rawJobs"),hint:"raw queue"}),Fu(En,{label:"已验证",value:z1(A,"verifiedJobs"),hint:"verified set"}),Fu(En,{label:"优先处理",value:z1(A,"prioritizedJobs"),hint:"prioritized"}),Fu(En,{label:"过期",value:z1(A,"staleJobs"),hint:"stale jobs",tone:"warn"}),Fu(En,{label:"无效",value:z1(A,"invalidJobs"),hint:"invalid jobs",tone:"warn"}),Fu(En,{label:"上海",value:z1(A,"shanghaiJobs"),hint:"city filter"}),Fu(En,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /api/health"})),Fu("div",{className:"panel-actions inline-actions"},Fu(g3,{title:"FindJob Summary",data:A,onOpen:f,testId:"raw-findjob-summary"}))),Fu(I3,{title:"近期岗位",eyebrow:U?`${U.returnedLength}/${U.originalLength} Preview`:`${j.length} Preview`,loading:n.loading},j.length===0?Fu(oc,{title:"暂无岗位预览",text:"等待 D601 findjob backend 返回 /api/jobs"}):Fu("div",{className:"table-wrap findjob-job-table"},Fu("table",null,Fu("thead",null,Fu("tr",null,Fu("th",null,"优先级"),Fu("th",null,"状态"),Fu("th",null,"单位"),Fu("th",null,"职位"),Fu("th",null,"城市"),Fu("th",null,"阶段"),Fu("th",null,"截止"),Fu("th",null,"证据"))),Fu("tbody",null,j.map((Q)=>Fu("tr",{key:Q.id},Fu("td",null,Fu(k3,{status:String(Q.priority||"").toLowerCase()||"unknown"},Q.priority||"--")),Fu("td",null,Fu(k3,{status:String(Q.status||"").toLowerCase()||"unknown"},Q.status||"--")),Fu("td",null,Q.organization_name||"--",Fu("code",null,Q.id||"--")),Fu("td",null,Q.display_title||Q.title||"--"),Fu("td",null,Q.display_city||Q.city||"--"),Fu("td",null,Q.workflow_stage||"--"),Fu("td",null,Q.deadline||"--"),Fu("td",null,Q.evidence_url?Fu("a",{href:Q.evidence_url,target:"_blank",rel:"noreferrer"},"打开"):Fu("span",{className:"muted"},"无"))))))),Fu("div",{className:"panel-actions inline-actions"},Fu(g3,{title:"FindJob Jobs Preview",data:n.jobs,onOpen:f,testId:"raw-findjob-jobs"}))),Fu(I3,{title:"草稿与报告",eyebrow:`${F.length} Drafts`,loading:n.loading},F.length===0?Fu(oc,{title:"暂无草稿",text:"D601 findjob backend 未返回 drafts"}):Fu("div",{className:"draft-list"},F.map((Q)=>Fu("article",{key:Q.id,className:"draft-card"},Fu("div",{className:"node-card-head"},Fu("strong",null,Q.id),Fu(k3,{status:Q.status},Q.status||"--")),Fu("div",{className:"docker-meta compact"},Fu("span",null,Q.workflow_stage||"--"),Fu("span",null,`jobs ${Q.counts?.jobs??0}`),Fu("span",null,`reports ${Q.counts?.reports??0}`)),Fu("span",null,Q.latestReportPath||"暂无报告"),Fu("code",null,Nu(Q.updated_at||Q.updatedAt))))),Fu("div",{className:"panel-actions inline-actions"},Fu(g3,{title:"FindJob Drafts",data:n.drafts,onOpen:f,testId:"raw-findjob-drafts"})))))}var h_=Mu(Qf(),1);var M=h_.default.createElement,{useEffect:KZ}=h_.default,dc=h_.default.useState;function C_(u){let f=Number(u);return Number.isFinite(f)?`${Math.max(0,Math.min(100,f)).toFixed(1)}%`:"--"}function u5(u){if(u===null||u===void 0||u==="")return"--";let f=Number(u);if(!Number.isFinite(f))return"--";if(f<60)return`${Math.max(0,Math.round(f))}s`;if(f<3600)return`${Math.floor(f/60)}m ${Math.round(f%60)}s`;return`${Math.floor(f/3600)}h ${Math.floor(f%3600/60)}m`}function f5(u,f=2){let l=Number(u);if(!Number.isFinite(l))return u===!1?"false":u===!0?"true":"--";let r=Math.abs(l);if(Number.isInteger(l)||r>=1000)return l.toLocaleString("zh-CN",{maximumFractionDigits:0});if(r>=1)return l.toLocaleString("zh-CN",{maximumFractionDigits:f});return l.toLocaleString("zh-CN",{maximumFractionDigits:Math.max(f,6)})}function x_(u){if(u===null||u===void 0||u==="")return"--";if(typeof u==="boolean")return u?"true":"false";if(typeof u==="number")return f5(u,4);if(Array.isArray(u))return u.map((f)=>x_(f)).join(" x ");if(typeof u==="object")return"已上报";return String(u)}function a3(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=f>=100?0:f>=10?1:2;return`${f.toLocaleString("zh-CN",{maximumFractionDigits:l})} epoch/h`}function o3(u){return u.replace(/[^a-zA-Z0-9_-]/g,"-")}function hl(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function R_({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return M("span",{className:`status-badge ${l}`},f||u||"unknown")}function Zn({label:u,value:f,hint:l,tone:r}){return M("article",{className:`metric-card ${r||""}`},M("div",{className:"metric-label"},u),M("div",{className:"metric-value"},f),M("div",{className:"metric-hint"},l))}function ec({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return M("section",{className:`panel ${n||""}`},M("div",{className:"panel-head"},M("div",null,f?M("p",{className:"panel-eyebrow"},f):null,M(nf,{title:u,loading:i})),l?M("div",{className:"panel-actions"},l):null),M("div",{className:"panel-body"},r))}function hi({title:u,data:f,onOpen:l,testId:r}){return M("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function Y0({title:u,text:f}){return M("div",{className:"empty-state"},M("strong",null,u),M("span",null,f))}function GZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function zZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function TZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function EZ(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function ZZ(u){return Array.isArray(u?.jobs)?u.jobs.slice(0,240):[]}function OZ(u){return Array.isArray(u?.projects)?u.projects.slice(0,1000):[]}function d3(u){return Array.isArray(u?.projects)?u.projects:[]}function HZ(u,f){if(Array.isArray(f?.gpu))return f.gpu;if(Array.isArray(u?.gpu))return u.gpu;return[]}function $r(u,f){return`${u}/microservices/met-nonlinear/proxy${f}`}function BQ(u){return u.startedAt&&u.finishedAt?u5((Date.parse(u.finishedAt)-Date.parse(u.startedAt))/1000):"--"}function BZ(u){let f=u.progress||{};if(f.etaSeconds!==null&&f.etaSeconds!==void 0&&f.etaSeconds!==""){let y=Number(f.etaSeconds);if(Number.isFinite(y))return Math.max(0,y)}let l=Number(f.currentEpoch),r=Number(f.epochTarget??u.epochTarget),n=Date.parse(u.startedAt||"");if(!Number.isFinite(l)||l<=0||!Number.isFinite(r)||r<=l||!Number.isFinite(n))return null;let i=Math.max(0,(Date.now()-n)/1000);if(i<=0)return null;return Math.max(0,i/l*(r-l))}function VQ(u){let f=u.progress||{},l=Number(f.epochPerHour);if(Number.isFinite(l)&&l>0)return l;let r=Date.parse(u.startedAt||""),n=["succeeded","failed","canceled"].includes(u.status)?Date.parse(u.finishedAt||""):Date.now();if(!Number.isFinite(r)||!Number.isFinite(n)||n<=r)return null;let i=Number(f.currentEpoch??u.epochTarget);if(!Number.isFinite(i)||i<=0)return null;return i/((n-r)/3600000)}function DQ(u){if(u==="staged")return"待启动";if(u==="queued")return"排队中";if(u==="running")return"训练中";if(u==="succeeded")return"已完成";if(u==="failed")return"失败";if(u==="canceled")return"已取消";return u||"unknown"}function XQ(u,f,l){return{name:u,path:f,depth:l,count:0,children:[],project:null}}function VZ(u){let f=XQ("","",-1);for(let r of u){let i=String(r?.projectPath||"").replace(/\\/g,"/").split("/").filter(Boolean);if(i.length===0)continue;let y=f,_=[];for(let[$,c]of i.entries()){_.push(c);let A=_.join("/"),j=y.children.find((F)=>F.path===A);if(!j)j=XQ(c,A,$),y.children.push(j);if($===i.length-1)j.project=r;y=j}}let l=(r)=>{let n=r.children.reduce((i,y)=>i+l(y),0);return r.count=(r.project?1:0)+n,r.children.sort((i,y)=>{if(Boolean(i.project)!==Boolean(y.project))return i.project?1:-1;return i.name.localeCompare(y.name,"zh-CN",{numeric:!0,sensitivity:"base"})}),r.count};return l(f),f}function DZ(u){let f=hl(u.data);return hl(f.project).projectPath?hl(f.project):f}function XZ(u){return hl(hl(u.data).job)}function YQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((P)=>P.id==="met-nonlinear")||null,[n,i]=dc({loading:!1,actionBusy:!1,error:"",health:null,summary:null,queue:null,projects:null,history:null,images:null,refreshedAt:null}),[y,_]=dc({loading:!1,error:"",kind:"",key:"",title:"",data:null}),[$,c]=dc(()=>({activeTab:"projects",selectedProjects:{},expandedProjectDirs:{},sourceProject:"",forkCount:1,forkEpochs:200,forkPrefix:`ui_fork_${Date.now()}`,maxConcurrency:3,targetGpuName:"2080 Ti",actionMessage:""}));function A(P){c((e)=>({...e,...P}))}async function j(P=$.activeTab){if(!r)return;i((e)=>({...e,loading:!0,error:""}));try{let e=[["health",Eu(`${l}/microservices/met-nonlinear/health`)],["summary",Eu($r(l,"/api/summary"))]];if(P==="projects")e.push(["projectsRoot",Eu($r(l,"/api/projects?root=projects&limit=500"))]),e.push(["exProjectsRoot",Eu($r(l,"/api/projects?root=ex_projects&limit=500"))]);if(P==="current"||P==="completed"||P==="failed")e.push(["queue",Eu($r(l,"/api/queue"))]);if(P==="completed"||P==="failed")e.push(["history",Eu($r(l,"/api/history"))]);if(P==="gpu")e.push(["images",Eu($r(l,"/api/images"))]);let uu=Object.fromEntries(await Promise.all(e.map(async([g,Qu])=>[g,await Qu]))),Wu={loading:!1,actionBusy:!1,error:"",health:uu.health,summary:uu.summary,refreshedAt:new Date};if(uu.projectsRoot||uu.exProjectsRoot){let{projectsRoot:g,exProjectsRoot:Qu}=uu;Wu.projects={ok:g?.ok!==!1&&Qu?.ok!==!1,roots:[{root:"projects",count:d3(g).length},{root:"ex_projects",count:d3(Qu).length}],projects:[...d3(g),...d3(Qu)]}}if(uu.queue)Wu.queue=uu.queue;if(uu.history)Wu.history=uu.history;if(uu.images)Wu.images=uu.images;i((g)=>({...g,...Wu}))}catch(e){i((uu)=>({...uu,loading:!1,actionBusy:!1,error:Hu(e,"MET Nonlinear 加载失败")}))}}async function F(P,e){i((uu)=>({...uu,actionBusy:!0,error:""})),A({actionMessage:`${P}...`});try{let uu=await e();A({actionMessage:uu||`${P}完成`}),await j()}catch(uu){i((Wu)=>({...Wu,actionBusy:!1,error:Hu(uu,`${P}失败`)}))}}async function U(){await F("保存并发设置",async()=>{await Eu($r(l,"/api/queue/settings"),{method:"PUT",body:JSON.stringify({maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName})})})}function Q(){return Object.entries($.selectedProjects).filter(([,P])=>P).map(([P])=>P)}async function w(){let P=Q();if(P.length===0)throw Error("请先选择至少一个 project");await F("加入待启动队列",async()=>{await Eu($r(l,"/api/queue"),{method:"POST",body:JSON.stringify({projectPaths:P,maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName,start:!1})}),A({activeTab:"current",selectedProjects:{}})})}async function L(){let P=$.sourceProject||m[0]?.projectPath;if(!P)throw Error("请先选择源 project");await F("Fork Project",async()=>{let e=await Eu($r(l,"/api/projects/fork"),{method:"POST",body:JSON.stringify({sourceProject:P,count:Number($.forkCount),epochs:Number($.forkEpochs),prefix:$.forkPrefix})}),uu=Array.isArray(e.projectPaths)?e.projectPaths:[],Wu=uu.reduce((g,Qu)=>{return g[Qu]=!0,g},{...$.selectedProjects});return A({selectedProjects:Wu}),`已 fork ${uu.length} 个 project,并已自动勾选;请确认后点击加入待启动队列。`})}async function J(){await F("启动队列",async()=>{await Eu($r(l,"/api/queue/start"),{method:"POST",body:JSON.stringify({maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName})}),A({activeTab:"current"})})}async function N(P){await F("取消任务",async()=>{await Eu($r(l,`/api/jobs/${encodeURIComponent(P.id)}/cancel`),{method:"POST",body:JSON.stringify({})})})}async function q(P){let e=String(P?.projectPath||"");if(!e)return;_({loading:!0,error:"",kind:"project",key:e,title:e,data:null});try{let uu=await Eu($r(l,`/api/projects/config?path=${encodeURIComponent(e)}`));_({loading:!1,error:"",kind:"project",key:e,title:e,data:uu})}catch(uu){_({loading:!1,error:Hu(uu,"Project 详情加载失败"),kind:"project",key:e,title:e,data:null})}}async function W(P){let e=String(P?.id||"");if(!e)return;_({loading:!0,error:"",kind:"job",key:e,title:P.projectPath||e,data:null});try{let uu=await Eu($r(l,`/api/jobs/${encodeURIComponent(e)}`));_({loading:!1,error:"",kind:"job",key:e,title:uu?.job?.projectPath||P.projectPath||e,data:uu})}catch(uu){_({loading:!1,error:Hu(uu,"Job 详情加载失败"),kind:"job",key:e,title:P.projectPath||e,data:null})}}if(KZ(()=>{j($.activeTab)},[r?.id,r?.runtime?.providerStatus,$.activeTab]),!r)return M(Y0,{title:"MET Nonlinear 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=met-nonlinear"});let z=GZ(r),Z=TZ(r),H=zZ(r),E=EZ(n.queue?.queue||n.summary?.queue),D=HZ(n.health,n.queue),h=n.health?.targetGpu||n.summary?.targetGpu||D.find((P)=>String(P.name||"").includes("2080")),B=n.images?.mlImage||n.health?.image||{},X=ZZ(n.queue),m=OZ(n.projects),O=VZ(m),p=$.sourceProject||m[0]?.projectPath||"",Y=X.filter((P)=>["staged","queued","running"].includes(P.status)),v=X.filter((P)=>P.status==="succeeded"),T=X.filter((P)=>["failed","canceled"].includes(P.status)),S=Array.isArray(n.history?.jobs)?n.history.jobs.slice(0,120):[],k=[{id:"projects",label:"项目库",count:m.length},{id:"current",label:"当前队列",count:Y.length||Number(E.staged||0)+Number(E.queued||0)+Number(E.running||0)},{id:"completed",label:"已完成",count:v.length||Number(E.succeeded||0)},{id:"failed",label:"失败诊断",count:T.length||Number(E.failed||0)+Number(E.canceled||0)},{id:"gpu",label:"GPU/镜像",count:D.length}];function I(P,e){if(P.length===0)return M(Y0,{title:e==="current"?"当前队列为空":"暂无记录",text:e==="current"?"从项目库选择或 fork project 后先加入待启动队列,再启动队列。":"终态任务会显示耗时、exit code 和失败诊断。"});return M("div",{className:"table-wrap met-job-table"},M("table",null,M("thead",null,M("tr",null,M("th",null,"状态"),M("th",null,"Project"),M("th",null,"Epoch"),M("th",null,"速度"),M("th",null,"ETA/耗时"),M("th",null,"GPU"),M("th",null,"Exit"),M("th",null,"更新时间"),M("th",null,"操作"))),M("tbody",null,P.map((uu)=>{let Wu=uu.progress||{},g=["staged","queued","running"].includes(uu.status),Qu=y.kind==="job"&&y.key===uu.id;return M("tr",{key:uu.id,className:`met-click-row ${Qu?"active":""}`,onClick:()=>W(uu),"data-testid":`met-job-row-${o3(uu.id)}`},M("td",null,M(R_,{status:uu.status},DQ(uu.status))),M("td",null,M("button",{type:"button",className:"met-inline-link",onClick:(Tu)=>{Tu.stopPropagation(),W(uu)}},uu.projectPath),M("code",null,uu.id)),M("td",null,M("span",null,`${Wu.currentEpoch??"--"} / ${Wu.epochTarget??uu.epochTarget??"--"}`),M("div",{className:"met-progress"},M("span",{style:{width:C_(Wu.progressPercent)}}))),M("td",null,M("strong",null,a3(VQ(uu)))),M("td",null,uu.status==="succeeded"||uu.status==="failed"||uu.status==="canceled"?BQ(uu):uu.status==="running"?`ETA ${u5(BZ(uu))}`:"--"),M("td",null,uu.gpuName||"--"),M("td",null,uu.exitCode??"--"),M("td",null,Nu(uu.updatedAt)),M("td",null,g?M("button",{type:"button",className:"ghost-btn mini",onClick:(Tu)=>{Tu.stopPropagation(),N(uu)},disabled:n.actionBusy},"取消"):null,M(hi,{title:`MET Job ${uu.id}`,data:uu,onOpen:f,testId:`raw-met-job-${uu.id}`})))}))))}function b(){return M("div",{className:"met-queue-summary","data-testid":"met-current-summary"},M(R_,{status:"staged"},`待启动 ${E.staged??0}`),M(R_,{status:"queued"},`排队中 ${E.queued??0}`),M(R_,{status:"running"},`训练中 ${E.running??0}`),M("span",null,`最大并发 ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??$.maxConcurrency}`),M("span",null,`目标 GPU ${n.summary?.queue?.targetGpuName??n.queue?.queue?.targetGpuName??$.targetGpuName}`))}function o(P,e){let uu=$.expandedProjectDirs[P];return uu===void 0?e<2:Boolean(uu)}function s(P,e){let uu=o(P,e);A({expandedProjectDirs:{...$.expandedProjectDirs,[P]:!uu}})}function x(P){let e=8+Math.max(0,P.depth)*16;if(Boolean(P.project)){let g=P.project,Qu=Boolean($.selectedProjects[g.projectPath]),Tu=y.kind==="project"&&y.key===g.projectPath;return M("div",{key:P.path,className:`met-tree-row project ${Qu?"selected":""} ${Tu?"active":""}`,style:{paddingLeft:e},onClick:()=>q(g),"data-testid":`met-project-node-${o3(g.projectPath)}`},M("div",{className:"met-tree-name"},M("input",{type:"checkbox",checked:Qu,onClick:(Zu)=>Zu.stopPropagation(),onChange:(Zu)=>A({selectedProjects:{...$.selectedProjects,[g.projectPath]:Zu.target.checked}}),"data-testid":`met-project-checkbox-${o3(g.projectPath)}`}),M("button",{type:"button",className:"met-inline-link project-path",onClick:(Zu)=>{Zu.stopPropagation(),q(g)}},P.name)),M("span",null,g.useModel||"--"),M("span",null,g.epochTrain??"--"),M("span",null,C_(g.progress?.progressPercent)),M("span",null,a3(g.progress?.epochPerHour)))}let Wu=o(P.path,P.depth);return M(h_.default.Fragment,{key:P.path},M("div",{className:"met-tree-row folder",style:{paddingLeft:e},"data-testid":`met-project-folder-${o3(P.path)}`},M("button",{type:"button",className:"met-tree-toggle",onClick:()=>s(P.path,P.depth),"aria-label":Wu?`折叠 ${P.path}`:`展开 ${P.path}`},Wu?"-":"+"),M("strong",null,P.name),M("span",{className:"met-tree-count"},`${P.count} projects`)),Wu?P.children.map((g)=>x(g)):null)}function fu(P){return M("div",{className:"met-detail-kv"},P.map((e)=>M("div",{key:e.label,className:"met-detail-kv-item"},M("span",null,e.label),M("strong",null,x_(e.value)),e.hint?M("small",null,e.hint):null)))}function $u(P,e){return M("div",{className:"met-detail-section"},M("h3",null,P),fu(e))}function tu(P){if(!Array.isArray(P)||P.length===0)return M(Y0,{title:"模型层未上报",text:"等待 data/model_info.json 或 compute_analysis.json 生成。"});return M("div",{className:"table-wrap met-layer-table"},M("table",null,M("thead",null,M("tr",null,M("th",null,"Layer"),M("th",null,"Type"),M("th",null,"Params"),M("th",null,"Trainable"),M("th",null,"Compute"))),M("tbody",null,P.slice(0,18).map((e,uu)=>M("tr",{key:`${e.name||"layer"}-${uu}`},M("td",null,e.name||`#${uu+1}`),M("td",null,e.type||"--"),M("td",null,f5(e.num_params)),M("td",null,e.trainable===void 0?"--":String(Boolean(e.trainable))),M("td",null,f5(e.compute?.total??e.estimated_cost?.weighted_units?.total)))))))}function ju(P){let e=Array.isArray(P)?P:[];if(e.length===0)return M(Y0,{title:"data/ 暂无文件",text:"训练或评估完成后会生成 training_state、metrics、model_info 等文件。"});return M("div",{className:"met-file-chip-grid"},e.slice(0,48).map((uu)=>M("span",{key:uu},uu)),e.length>48?M("span",null,`+${e.length-48}`):null)}function Gu(P){let e=String(P||"").replace(/\x1b\[[0-9;]*[A-Za-z]/g,"").split(/\r?\n/).map((uu)=>uu.trim()).filter(Boolean).slice(-12);if(e.length===0)return M(Y0,{title:"暂无日志尾部",text:"该任务未上报 logTail 或日志已轮转。"});return M("div",{className:"met-log-lines"},e.map((uu,Wu)=>M("div",{key:`${Wu}-${uu.slice(0,16)}`},uu)))}function qu(){if(y.loading)return M("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},M("div",{className:"panel-head compact"},M("div",null,M("p",{className:"panel-eyebrow"},"Detail Loading"),M(nf,{title:"详情加载中",loading:!0}))),M(Y0,{title:"详情加载中",text:y.title||"正在读取 D601 data/ 和 config.json"}));if(y.error)return M("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},M(yf,{error:y.error,wide:!0}));if(!y.data)return M("section",{className:"met-detail-panel muted","data-testid":"met-detail-panel"},M(Y0,{title:"选择一个项目或任务查看详情",text:"项目库、当前队列、已完成和失败诊断中的行都可以点击;默认只展示结构化字段,原始 JSON 需显式点击按钮。"}));let P=DZ(y),e=XZ(y),uu=hl(P.config),Wu=hl(P.progress||e.progress),g=hl(P.data),Qu=hl(P.metrics||g.metrics||Wu.trainingInfo?.evaluation_metrics),Tu=hl(g.trainingInfo||Wu.trainingInfo),Zu=hl(g.trainingState),Xu=hl(P.model||g.model),ff=Array.isArray(Xu.modelSummary)&&Xu.modelSummary.length>0?Xu.modelSummary:Xu.computeLayers,_f=hl(Tu.evaluation_metrics),Jf=y.kind==="job"?"训练任务详情":"Project 详情";return M("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},M("div",{className:"panel-head compact"},M("div",null,M("p",{className:"panel-eyebrow"},y.kind==="job"?"Job + Project Detail":"Project Library Detail"),M(nf,{title:Jf}),M("code",null,P.projectPath||e.projectPath||y.title)),M("div",{className:"panel-actions"},M(hi,{title:`MET ${Jf}`,data:y.data,onOpen:f,testId:"raw-met-detail"}))),y.kind==="job"?$u("任务状态",[{label:"Job ID",value:e.id},{label:"状态",value:DQ(e.status)},{label:"GPU",value:e.gpuName},{label:"Exit Code",value:e.exitCode},{label:"耗时",value:BQ(e)},{label:"训练速度",value:a3(VQ({...e,progress:Wu}))}]):null,$u("config.json",[{label:"use_model",value:uu.use_model},{label:"epoch_train",value:uu.epoch_train},{label:"step_per_epoch",value:uu.step_per_epoch},{label:"learning_rate",value:uu.learning_rate},{label:"using_gpu",value:uu.using_gpu},{label:"use_points",value:uu.use_points},{label:"sample_rate",value:uu.sample_rate},{label:"time_clipped_s",value:uu.time_clipped_s},{label:"H_UNITS",value:uu.H_UNITS},{label:"INNER_KAN_UNITS",value:uu.INNER_KAN_UNITS},{label:"INNER_KAN_LAYERS",value:uu.INNER_KAN_LAYERS},{label:"GRID_SIZE",value:uu.GRID_SIZE},{label:"SPLINE_ORDER",value:uu.SPLINE_ORDER},{label:"USE_FAST_MODEL",value:uu.USE_FAST_MODEL},{label:"IIR_TRAINABLE",value:uu.IIR_TRAINABLE}]),$u("data/ 训练状态",[{label:"Epoch",value:`${Wu.currentEpoch??Zu.current_epoch??Zu.completed_epoch??"--"} / ${Wu.epochTarget??uu.epoch_train??"--"}`},{label:"Progress",value:C_(Wu.progressPercent)},{label:"Last Loss",value:Wu.lastLoss??Zu.loss},{label:"Last Val Loss",value:Wu.lastValLoss??Zu.val_loss},{label:"Min Loss",value:Tu.min_loss??Zu.min_loss},{label:"Min Val Loss",value:Tu.min_val_loss??Zu.min_val_loss},{label:"Log Lines",value:Wu.logLineCount},{label:"ETA",value:u5(Wu.etaSeconds??Zu.remaining_time)},{label:"训练速度",value:a3(Wu.epochPerHour??Zu.smoothed_speed)},{label:"Training Alive",value:Zu.training_alive}]),$u("模型参数",[{label:"Model Type",value:Xu.modelType??uu.use_model},{label:"Total Params",value:Xu.totalParams,hint:Xu.totalParams===null||Xu.totalParams===void 0?"未上报":"data/model_info.json"},{label:"Trainable",value:Xu.trainableParams},{label:"Non-trainable",value:Xu.nonTrainableParams},{label:"Compute Cost",value:Xu.computeCost},{label:"Estimate Status",value:Xu.estimateStatus},{label:"Unsupported Layers",value:Xu.unsupportedLayerCount}]),$u("指标",[{label:"train_loss",value:Qu.train_loss??_f.train_loss},{label:"val_loss",value:Qu.val_loss??_f.val_loss},{label:"train_mae",value:Qu.train_mae??_f.train_mae},{label:"val_mae",value:Qu.val_mae??_f.val_mae},{label:"train_afmae",value:Qu.train_afmae??_f.train_afmae},{label:"val_afmae",value:Qu.val_afmae??_f.val_afmae},{label:"freq_drift_hz",value:Qu.freq_drift_hz},{label:"sens_drift_percent",value:Qu.sens_drift_percent},{label:"linearity_percent",value:Qu.linearity_percent},{label:"weights_source",value:Qu.weights_source??_f.weights_source},{label:"lr min/mean/max",value:`${x_(Tu.learning_rate_min)} / ${x_(Tu.learning_rate_mean)} / ${x_(Tu.learning_rate_max)}`}]),M("div",{className:"met-detail-section"},M("h3",null,"模型层"),tu(ff)),M("div",{className:"met-detail-section"},M("h3",null,"data/ 文件"),ju(g.files)),y.kind==="job"?M("div",{className:"met-detail-section"},M("h3",null,"日志尾部"),Gu(hl(y.data).logTail)):null)}return M("div",{className:"met-page","data-testid":"met-nonlinear-page"},M(ec,{title:"MET Nonlinear 训练编排",eyebrow:"D601 GPU 用户服务",loading:n.loading||n.actionBusy,actions:M("div",{className:"panel-actions"},M("button",{type:"button",className:"ghost-btn",onClick:j,disabled:n.loading,"data-testid":"met-refresh-button"},n.loading?"刷新中":"刷新"),M(hi,{title:"MET Nonlinear 用户服务",data:r,onOpen:f,testId:"raw-met-service"}))},M("div",{className:"findjob-hero"},M("div",null,M("div",{className:"node-version-line"},M(R_,{status:z.providerStatus==="online"?"online":"warn"},z.providerStatus||"unknown"),M("span",null,r.providerId),M("span",null,H.public?"公网暴露":"仅 UniDesk frontend 代理访问")),M("p",{className:"muted paragraph"},r.description)),M("div",{className:"microservice-ref-card"},M("span",null,"Repo"),M("strong",null,Z.url||"--"),M("code",null,Z.commitId||"--")),M("div",{className:"microservice-ref-card"},M("span",null,"D601 Docker"),M("strong",null,`${H.nodeBindHost||"--"}:${H.nodePort||"--"}`),M("code",null,`${Z.composeFile||"--"} / ${Z.containerName||"--"}`))),M(yf,{error:n.error,wide:!0}),$.actionMessage?M("div",{className:"met-action-log","data-testid":"met-action-message"},$.actionMessage):null),M("div",{className:"met-grid"},M(ec,{title:"核心状态",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Queue + GPU",loading:n.loading},M("div",{className:"metric-grid"},M(Zn,{label:"Staged",value:E.staged??0,hint:"加入队列未开始",tone:Number(E.staged||0)>0?"warn":""}),M(Zn,{label:"Queued",value:E.queued??0,hint:"排队等待调度",tone:Number(E.queued||0)>0?"warn":""}),M(Zn,{label:"Running",value:E.running??0,hint:`max ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??"--"}`,tone:Number(E.running||0)>0?"ok":""}),M(Zn,{label:"Succeeded",value:E.succeeded??0,hint:"已完成"}),M(Zn,{label:"Failed",value:E.failed??0,hint:"需要诊断",tone:Number(E.failed||0)>0?"warn":""}),M(Zn,{label:"2080Ti Free",value:h?C_(Number(h.freeRatio)*100):"--",hint:h?`${h.memoryFreeMiB}/${h.memoryTotalMiB} MiB`:"等待 GPU 上报"}),M(Zn,{label:"ML Image",value:B.present?"READY":"MISSING",hint:B.image||"met-nonlinear-ml:tf26",tone:B.present?"ok":"warn"}),M(Zn,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /health"}))),M(ec,{title:"队列控制",eyebrow:"Downloader-like staging",loading:n.actionBusy},M("div",{className:"met-control-strip"},M("label",null,"最大并发",M("input",{type:"number",min:1,max:16,value:$.maxConcurrency,"data-testid":"met-max-concurrency-input",onChange:(P)=>A({maxConcurrency:P.target.value})})),M("label",null,"目标 GPU",M("input",{value:$.targetGpuName,"data-testid":"met-target-gpu-input",onChange:(P)=>A({targetGpuName:P.target.value})})),M("button",{type:"button",className:"ghost-btn",onClick:U,disabled:n.actionBusy,"data-testid":"met-save-settings-button"},"保存设置"),M("button",{type:"button",className:"primary-btn",onClick:J,disabled:n.actionBusy||Number(E.staged||0)===0,"data-testid":"met-start-queue-button"},"启动队列")),M("p",{className:"muted paragraph"},"Project 先进入待启动队列,不会立即训练;点击启动队列后才切换为排队中,并由 D601 scheduler 按最大并发和 2080Ti 显存策略调度。")),M("section",{className:"panel met-workspace"},M("div",{className:"met-tabs",role:"tablist"},k.map((P)=>M("button",{key:P.id,type:"button",className:$.activeTab===P.id?"active":"",onClick:()=>A({activeTab:P.id}),"data-testid":`met-tab-${P.id}`},`${P.label} ${P.count}`))),M("div",{className:"panel-body"},$.activeTab==="projects"?M("div",{className:"met-form-grid","data-testid":"met-projects-pane"},M("div",{className:"met-fork-card"},M("h3",null,"Fork Project"),M("label",null,"源 Project",M("select",{value:p,"data-testid":"met-source-project-select",onChange:(P)=>A({sourceProject:P.target.value})},m.map((P)=>M("option",{key:P.projectPath,value:P.projectPath},`${P.projectPath} · ${P.useModel||"model?"}`)))),M("label",null,"Fork 数量",M("input",{type:"number",min:1,max:100,value:$.forkCount,"data-testid":"met-fork-count-input",onChange:(P)=>A({forkCount:P.target.value})})),M("label",null,"训练轮数",M("input",{type:"number",min:1,max:1e5,value:$.forkEpochs,"data-testid":"met-fork-epochs-input",onChange:(P)=>A({forkEpochs:P.target.value})})),M("label",null,"目标前缀",M("input",{value:$.forkPrefix,"data-testid":"met-fork-prefix-input",onChange:(P)=>A({forkPrefix:P.target.value})})),M("button",{type:"button",className:"primary-btn",onClick:L,disabled:n.actionBusy||!p,"data-testid":"met-fork-button"},"Fork Project"),M("p",{className:"muted paragraph"},"Fork 只创建新 Project 并自动勾选,不会直接训练;需要在右侧确认后加入待启动队列。")),M("div",{className:"met-project-list"},M("div",{className:"panel-head compact"},M("div",null,M("p",{className:"panel-eyebrow"},`Existing Projects · ${(n.projects?.roots||[]).map((P)=>`${P.root} ${P.count}`).join(" / ")}`),M(nf,{title:"选择已有 Project",loading:n.loading||n.actionBusy})),M("button",{type:"button",className:"ghost-btn",onClick:w,disabled:n.actionBusy||Q().length===0,"data-testid":"met-stage-selected-button"},`加入待启动队列 (${Q().length})`)),m.length===0?M(Y0,{title:"暂无 project",text:"等待 D601 返回 /api/projects"}):M("div",{className:"met-project-table","data-testid":"met-project-tree"},M("div",{className:"met-tree-header"},M("span",null,"文件树 Project"),M("span",null,"Model"),M("span",null,"Epochs"),M("span",null,"Progress"),M("span",null,"速度")),O.children.map((P)=>x(P)))),qu()):null,$.activeTab==="current"?M("div",{"data-testid":"met-current-pane"},b(),I(Y,"current"),qu(),M("div",{className:"panel-actions inline-actions"},M(hi,{title:"MET Queue",data:n.queue,onOpen:f,testId:"raw-met-queue"}))):null,$.activeTab==="completed"?M("div",{"data-testid":"met-completed-pane"},I(v.length>0?v:S.filter((P)=>P.status==="succeeded"),"completed"),qu()):null,$.activeTab==="failed"?M("div",{"data-testid":"met-failed-pane"},I(T.length>0?T:S.filter((P)=>["failed","canceled"].includes(P.status)),"failed"),qu(),M("div",{className:"panel-actions inline-actions"},M(hi,{title:"MET History",data:n.history,onOpen:f,testId:"raw-met-history"}))):null,$.activeTab==="gpu"?M("div",{className:"met-gpu-pane","data-testid":"met-gpu-pane"},D.length===0?M(Y0,{title:"暂无 GPU 上报",text:"等待 D601 met-nonlinear-ts 或 ML image 提供 nvidia-smi 数据"}):M("div",{className:"table-wrap"},M("table",null,M("thead",null,M("tr",null,M("th",null,"Index"),M("th",null,"Name"),M("th",null,"Free"),M("th",null,"Policy"))),M("tbody",null,D.map((P)=>M("tr",{key:P.index},M("td",null,P.index),M("td",null,P.name),M("td",null,`${P.memoryFreeMiB} / ${P.memoryTotalMiB} MiB`,M("div",{className:"met-progress"},M("span",{style:{width:C_(Number(P.freeRatio)*100)}}))),M("td",null,String(P.name||"").includes("2080")?"target 2080Ti, <20% 限制并发":"non-target")))))),M("div",{className:"panel-actions inline-actions"},M(hi,{title:"MET Images",data:n.images,onOpen:f,testId:"raw-met-images"}))):null))))}var u6=[{id:"ops",label:"运行总览",code:"OPS",tabs:[{id:"status",label:"态势总览"},{id:"performance",label:"性能面板"},{id:"events",label:"事件摘要"},{id:"logs",label:"服务日志"}]},{id:"nodes",label:"资源节点",code:"NODE",tabs:[{id:"list",label:"节点清单"},{id:"monitor",label:"资源监控"},{id:"docker",label:"Docker 状态"},{id:"gateway",label:"网关版本"},{id:"labels",label:"资源标签"},{id:"heartbeats",label:"心跳状态"}]},{id:"tasks",label:"任务调度",code:"TASK",tabs:[{id:"dispatch",label:"下发任务"},{id:"scheduled",label:"定时任务"},{id:"pending",label:"待处理任务"},{id:"history",label:"任务历史"},{id:"results",label:"执行结果"}]},{id:"apps",label:"用户服务",code:"APP",routeSegment:"app",tabs:[{id:"catalog",label:"服务目录"},{id:"todo-note",label:"Todo Note"},{id:"findjob",label:"FindJob"},{id:"pipeline",label:"Pipeline"},{id:"met-nonlinear",label:"MET Nonlinear"},{id:"claudeqq",label:"ClaudeQQ"},{id:"baidu-netdisk",label:"Baidu Netdisk"},{id:"filebrowser",label:"File Browser"},{id:"oa-event-flow",label:"OA Event Flow"},{id:"code-queue",label:"Code Queue"},{id:"project-manager",label:"Project Manager"}]},{id:"config",label:"系统配置",code:"CFG",tabs:[{id:"topology",label:"连接拓扑"},{id:"auth",label:"认证策略"},{id:"security",label:"安全边界"}]}],b_=Object.fromEntries(u6.map((u)=>[u.id,u.tabs[0]?.id??""]));function YZ(u){let f=String(u||"").trim();if(!f)return"";try{return decodeURIComponent(f)}catch{return f}}function e3(u){let f=String(u||"/"),[l]=f.split(/[?#]/u,1);if(l==="/")return"/";let n=`/${l.split("/").map(YZ).filter(Boolean).join("/")}`;return n.endsWith("/")?n:`${n}/`}function SZ(u){let f=2166136261;for(let l of u)f^=l.charCodeAt(0),f=Math.imul(f,16777619);return Math.abs(f>>>0).toString(36)}function l5(u){return String(u||"").normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"")}function SQ(u){return String(u||"").trim().toLowerCase().replace(/[\s/\\?#%]+/gu,"-").replace(/-+/gu,"-").replace(/^-+|-+$/gu,"")}function mQ(u){let f=l5(u.routeSegment||"")||SQ(u.routeSegment||"");if(f)return f;let l=l5(u.id||"");if(l)return l;let r=l5(u.label||"")||SQ(u.label||"");if(r)return r;return`route-${SZ(JSON.stringify(u))}`}function r5(u,f){return`${u}:${f}`}function pQ(u){let f=u.map(($)=>{let c=mQ($);return{...$,routeSegment:c,tabs:$.tabs.map((A)=>({...A,routeSegment:mQ(A)}))}}),l={},r={},n={},i=f.map(($)=>{let c=$.tabs[0]?.id??"";n[$.id]=c;let A=$.tabs.map((U)=>{let Q=`/${$.routeSegment}/${U.routeSegment}/`,w=[Q],L={moduleId:$.id,tabId:U.id};for(let J of w)l[e3(J)]=L;return r[r5($.id,U.id)]=Q,{...U,canonicalPath:Q,aliases:w}}),j=`/${$.routeSegment}/`,F={moduleId:$.id,tabId:c};return l[e3(j)]=F,{...$,routeSegment:$.routeSegment,canonicalPath:j,tabs:A}}),y=i[0],_={moduleId:y?.id||"",tabId:y?.tabs[0]?.id||""};return l["/"]=_,{modules:i,moduleById:Object.fromEntries(i.map(($)=>[$.id,$])),defaultActiveTabs:n,routeMap:l,canonicalPathByTarget:r,fallbackTarget:_}}function n5(u,f){return u.routeMap[e3(f)]||u.fallbackTarget}function f6(u,f,l){return u.canonicalPathByTarget[r5(f,l)]||u.canonicalPathByTarget[r5(u.fallbackTarget.moduleId,u.fallbackTarget.tabId)]||"/"}function PQ(u,f){let l=u.routeMap[e3(f)];if(!l)return null;return f6(u,l.moduleId,l.tabId)}var i6=Mu(Qf(),1);var nu=i6.default.createElement,{useEffect:MQ,useMemo:mZ}=i6.default,i5=i6.default.useState;function n6({status:u,children:f,title:l}){let r=String(u||"unknown").toLowerCase();return nu("span",{className:`status-badge ${r}`,title:l},f||u||"unknown")}function v_({label:u,value:f,hint:l,tone:r}){return nu("article",{className:`metric-card ${r||""}`},nu("div",{className:"metric-label"},u),nu("div",{className:"metric-value"},f),nu("div",{className:"metric-hint"},l))}function l6({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return nu("section",{className:`panel ${n||""}`},nu("div",{className:"panel-head"},nu("div",null,f?nu("p",{className:"panel-eyebrow"},f):null,nu(nf,{title:u,loading:i})),l?nu("div",{className:"panel-actions"},l):null),nu("div",{className:"panel-body"},r))}function k_({title:u,data:f,onOpen:l,testId:r}){return nu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l?.(u,f)},"查看原始JSON")}function y5({title:u,text:f}){return nu("div",{className:"empty-state"},nu("strong",null,u),nu("span",null,f))}function pZ(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function S0(u){return Array.isArray(u)?u:[]}function bl(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}function CQ(u,f=140){if(u===null||u===void 0)return"--";let l=typeof u==="string"?u:JSON.stringify(u),r=String(l||"").replace(/\s+/gu," ").trim();return r.length>f?`${r.slice(0,f-1)}...`:r||"--"}function PZ(u){return S0(u?.tags).map((f)=>String(f||"").trim()).filter(Boolean)}function T1(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):0}function MZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function CZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function RZ(u){return String(u||"").split(/[\s,]+/u).map((f)=>f.trim()).filter(Boolean).join(",")}function r6(u,f){return`${u}/microservices/oa-event-flow/proxy${f}`}function xZ(u){if(u.includes("error")||u.includes("failed"))return"failed";if(u.includes("stats"))return"ok";if(u.includes("step")||u.includes("updated"))return"running";return"queued"}function hZ(u){let f=String(u?.subjectKind||"trace"),l=String(u?.subjectId||u?.scopeId||"");return l?`${f}:${l}`:String(u?.scopeId||"--")}function bZ({tags:u}){let f=PZ({tags:u}).slice(0,6);return nu("div",{className:"oa-tag-rail"},f.length===0?nu("span",{className:"muted"},"--"):f.map((l)=>nu("code",{key:l},l)))}function vZ({events:u,onRaw:f}){let l=[...S0(u)].reverse();return l.length===0?nu(y5,{title:"事件表暂无记录",text:"等待 Code Queue 或 Pipeline 按 tag 发布 OA 事件"}):nu("div",{className:"table-wrap oa-event-table-wrap"},nu("table",{className:"oa-event-table","data-testid":"oa-event-flow-event-table"},nu("thead",null,nu("tr",null,nu("th",null,"Seq"),nu("th",null,"Type"),nu("th",null,"Source"),nu("th",null,"Aggregate"),nu("th",null,"Tags"),nu("th",null,"Payload"),nu("th",null,"Created"),nu("th",null,"Raw"))),nu("tbody",null,l.map((r)=>{let n=String(r?.type||"event"),i=`${String(r?.aggregateType||"--")}:${String(r?.aggregateId||"--")}`;return nu("tr",{key:r?.eventId||r?.sequence},nu("td",null,nu("code",null,bl(r?.sequence))),nu("td",null,nu(n6,{status:xZ(n)},n)),nu("td",null,nu("strong",null,r?.sourceId||"--"),nu("code",null,r?.sourceKind||"--")),nu("td",null,nu("code",null,i)),nu("td",null,nu(bZ,{tags:r?.tags})),nu("td",null,nu("span",{className:"oa-payload-preview"},CQ(r?.payload,180))),nu("td",null,Nu(r?.createdAt)),nu("td",null,nu(k_,{title:`OA Event ${r?.sequence||""}`,data:r,onOpen:f,testId:`raw-oa-event-${r?.sequence||"unknown"}`})))}))))}function kZ({stats:u,onRaw:f}){let l=S0(u);return l.length===0?nu(y5,{title:"统计中心暂无投影",text:"trace-stats-snapshot / trace-step-created 进入事件流后会更新这里"}):nu("div",{className:"table-wrap oa-stats-table-wrap"},nu("table",{className:"oa-stats-table","data-testid":"oa-event-flow-stats"},nu("thead",null,nu("tr",null,nu("th",null,"Scope"),nu("th",null,"Service"),nu("th",null,"STEP"),nu("th",null,"Read"),nu("th",null,"Edit"),nu("th",null,"Run"),nu("th",null,"Error"),nu("th",null,"Output Seq"),nu("th",null,"Revision"),nu("th",null,"Updated"),nu("th",null,"Raw"))),nu("tbody",null,l.map((r)=>nu("tr",{key:r?.scopeId||`${r?.serviceId}-${r?.subjectId}`},nu("td",null,nu("strong",null,hZ(r)),nu("code",null,r?.scopeId||"--")),nu("td",null,nu(n6,{status:String(r?.serviceId||"unknown")==="code-queue"?"running":"queued"},r?.serviceId||"--")),nu("td",null,nu("strong",null,bl(T1(r?.stepCount??r?.llmStepCount)))),nu("td",null,bl(T1(r?.readCount))),nu("td",null,bl(T1(r?.editCount))),nu("td",null,bl(T1(r?.runCount))),nu("td",null,bl(T1(r?.errorCount))),nu("td",null,nu("code",null,bl(T1(r?.outputMaxSeq)))),nu("td",null,bl(T1(r?.statsRevision))),nu("td",null,Nu(r?.updatedAt)),nu("td",null,nu(k_,{title:`OA Trace Stats ${r?.scopeId||""}`,data:r,onOpen:f,testId:`raw-oa-stats-${String(r?.scopeId||"unknown").replace(/[^a-zA-Z0-9_-]/gu,"_")}`})))))))}function RQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((z)=>z.id==="oa-event-flow")||null,[n,i]=i5("service:code-queue"),[y,_]=i5({loading:!1,error:"",health:null,diagnostics:null,events:[],stats:[],refreshedAt:null}),[$,c]=i5({status:"idle",message:"未连接",lastEventAt:""}),A=mZ(()=>RZ(n),[n]);async function j(){if(!r)return;_((z)=>({...z,loading:!0,error:""}));try{let z=A?`tags=${encodeURIComponent(A)}&`:"",[Z,H,E,D]=await Promise.all([Eu(`${l}/microservices/oa-event-flow/health`,{failureFields:[]}),Eu(r6(l,"/api/diagnostics")),Eu(r6(l,`/api/events?${z}limit=100`)),Eu(r6(l,`/api/stats/trace?${z}limit=100`))]);_({loading:!1,error:"",health:Z,diagnostics:H,events:S0(E?.events),stats:S0(D?.stats),refreshedAt:new Date})}catch(z){_((Z)=>({...Z,loading:!1,error:Hu(z,"OA Event Flow 加载失败")}))}}if(MQ(()=>{j()},[r?.id,r?.runtime?.providerStatus,A]),MQ(()=>{if(!r||typeof EventSource>"u")return;let z=A?`?tags=${encodeURIComponent(A)}`:"",Z=new EventSource(`${r6(l,"/api/events/stream")}${z}`,{withCredentials:!0});c({status:"running",message:"SSE connecting",lastEventAt:""});let H=(h)=>{c({status:"online",message:CQ(h.data,120),lastEventAt:new Date().toISOString()})},E=(h)=>{try{let B=JSON.parse(String(h.data||"{}"));c({status:"online",message:String(B?.type||h.type||"event"),lastEventAt:new Date().toISOString()}),_((X)=>{let m=[...S0(X.events).filter((p)=>String(p?.eventId||"")!==String(B?.eventId||"")),B].sort((p,Y)=>Number(p?.sequence||0)-Number(Y?.sequence||0)).slice(-100),O=B?.type==="trace-stats-updated"&&pZ(B?.payload?.stats)?[B.payload.stats,...S0(X.stats).filter((p)=>String(p?.scopeId||"")!==String(B.payload.stats.scopeId||""))].slice(0,100):X.stats;return{...X,events:m,stats:O}})}catch(B){c({status:"warn",message:Hu(B,"SSE 事件解析失败"),lastEventAt:new Date().toISOString()})}},D=()=>{c((h)=>({...h,status:"warn",message:"SSE reconnecting"}))};return Z.addEventListener("hello",H),Z.addEventListener("task-updated",E),Z.addEventListener("queue-updated",E),Z.addEventListener("trace-step-created",E),Z.addEventListener("trace-stats-snapshot",E),Z.addEventListener("trace-stats-updated",E),Z.addEventListener("trace-error",E),Z.onerror=D,()=>Z.close()},[r?.id,l,A]),!r)return nu(y5,{title:"OA Event Flow 未登记",text:"请在 config.json 的 microservices 中登记 id=oa-event-flow"});let F=MZ(r),U=CZ(r),Q=y.diagnostics||{},w=y.health||{},L=Q.eventCount??w.eventCount,J=Q.traceStatsCount??w.traceStatsCount,N=Q.latestSequence??w.latestSequence,q=Q.pipelineBridge||w.pipelineBridge||{},W=S0(Q.eventTypes).slice(0,8);return nu("div",{className:"oa-event-flow-page","data-testid":"oa-event-flow-page"},nu(l6,{title:"OA Event Flow 控制台",eyebrow:"Unified OA Event Bus + Stats Projection",loading:y.loading,actions:nu("div",{className:"panel-actions"},nu("button",{type:"button",className:"ghost-btn",onClick:j,disabled:y.loading,"data-testid":"oa-event-flow-refresh"},y.loading?"刷新中":"刷新"),nu(k_,{title:"OA Event Flow Service",data:r,onOpen:f,testId:"raw-oa-event-flow-service"}))},nu("div",{className:"oa-flow-hero"},nu("div",null,nu("div",{className:"node-version-line"},nu(n6,{status:w?.ok||F.providerStatus==="online"?"online":"warn"},w?.ok?"HEALTH OK":F.providerStatus||"unknown"),nu(n6,{status:$.status},$.status.toUpperCase()),nu("span",null,U.public?"公网暴露":"仅 UniDesk frontend 代理访问")),nu("p",{className:"muted paragraph"},"独立事件流微服务统一承载 Code Queue 与 Pipeline 的事件发布、tag 订阅、事件表审计和 Trace/STEP 统计投影。")),nu("div",{className:"oa-flow-signal"},nu("span",null,"stream"),nu("strong",null,$.message||"--"),nu("code",null,$.lastEventAt?$f(new Date($.lastEventAt)):"waiting"))),nu(yf,{error:y.error,wide:!0})),nu("div",{className:"oa-flow-metrics"},nu(v_,{label:"事件总量",value:bl(L),hint:`latest seq ${bl(N)}`,tone:"ok"}),nu(v_,{label:"Trace Stats",value:bl(J),hint:"oa_trace_stats 投影"}),nu(v_,{label:"SSE Clients",value:bl(w?.sseClientCount??S0(Q.sseClients).length),hint:$.message||"tag subscription"}),nu(v_,{label:"Pipeline Bridge",value:q?.enabled?bl(q?.insertedCount):"OFF",hint:q?.lastError||q?.lastFinishedAt||`${q?.mode||"snapshot"} service:pipeline`}),nu(v_,{label:"DB",value:w?.databaseReady||Q.databaseReady?"READY":"WAIT",hint:w?.databaseLastError||Q.databaseLastError||"PostgreSQL persisted"})),nu(l6,{title:"标签订阅",eyebrow:y.refreshedAt?`Updated ${$f(y.refreshedAt)}`:"Tag Pub/Sub"},nu("div",{className:"oa-filter-bar"},nu("label",null,nu("span",null,"tags"),nu("input",{value:n,onChange:(z)=>i(z.target.value),placeholder:"service:code-queue, trace","data-testid":"oa-event-flow-tag-filter"})),nu("div",{className:"oa-filter-presets"},nu("button",{type:"button",className:"ghost-btn",onClick:()=>i("service:code-queue")},"Code Queue"),nu("button",{type:"button",className:"ghost-btn",onClick:()=>i("service:pipeline")},"Pipeline"),nu("button",{type:"button",className:"ghost-btn",onClick:()=>i("trace")},"Trace"),nu("button",{type:"button",className:"ghost-btn",onClick:()=>i("")},"All")),nu("code",null,A||"all events")),nu("div",{className:"oa-type-strip"},W.length===0?nu("span",{className:"muted"},"等待事件类型统计"):W.map((z)=>nu("span",{key:z.type,className:"data-chip"},`${z.type} ${bl(z.count)}`)))),nu("div",{className:"oa-flow-grid"},nu(l6,{title:"事件表",eyebrow:"oa_events persisted log",className:"oa-flow-wide",loading:y.loading,actions:nu(k_,{title:"OA Event Query",data:{events:y.events,diagnostics:Q},onOpen:f,testId:"raw-oa-events"})},nu(vZ,{events:y.events,onRaw:f})),nu(l6,{title:"统计中心",eyebrow:"oa_trace_stats read model",className:"oa-flow-wide",loading:y.loading,actions:nu(k_,{title:"OA Trace Stats",data:y.stats,onOpen:f,testId:"raw-oa-trace-stats"})},nu(kZ,{stats:y.stats,onRaw:f}))))}var Rn=Mu(Qf(),1);var ru=Mu(vQ(),1),yu=Mu(Qf(),1);function Xf(u){if(typeof u==="string"||typeof u==="number")return""+u;let f="";if(Array.isArray(u)){for(let l=0,r;l{}};function IQ(){for(var u=0,f=arguments.length,l={},r;u=0)r=l.slice(n+1),l=l.slice(0,n);if(l&&!f.hasOwnProperty(l))throw Error("unknown type: "+l);return{type:l,name:r}})}_6.prototype=IQ.prototype={constructor:_6,on:function(u,f){var l=this._,r=uO(u+"",l),n,i=-1,y=r.length;if(arguments.length<2){while(++i0)for(var l=Array(n),r=0,n,i;r=0&&(f=u.slice(0,l))!=="xmlns")u=u.slice(l+1);return _5.hasOwnProperty(f)?{space:_5[f],local:u}:u}function $5(u){let f;while(f=u.sourceEvent)u=f;return u}function Wl(u,f){if(u=$5(u),f===void 0)f=u.currentTarget;if(f){var l=f.ownerSVGElement||f;if(l.createSVGPoint){var r=l.createSVGPoint();return r.x=u.clientX,r.y=u.clientY,r=r.matrixTransform(f.getScreenCTM().inverse()),[r.x,r.y]}if(f.getBoundingClientRect){var n=f.getBoundingClientRect();return[u.clientX-n.left-f.clientLeft,u.clientY-n.top-f.clientTop]}}return[u.pageX,u.pageY]}function lO(){}function On(u){return u==null?lO:function(){return this.querySelector(u)}}function t5(u){if(typeof u!=="function")u=On(u);for(var f=this._groups,l=f.length,r=Array(l),n=0;n=q)q=N+1;while(!(z=L[q])&&++q=0;)if(y=r[n]){if(i&&y.compareDocumentPosition(i)^4)i.parentNode.insertBefore(y,i);i=y}return this}function K5(u){if(!u)u=UO;function f(j,F){return j&&F?u(j.__data__,F.__data__):!j-!F}for(var l=this._groups,r=l.length,n=Array(r),i=0;if?1:u>=f?0:NaN}function G5(){var u=arguments[0];return arguments[0]=this,u.apply(null,arguments),this}function z5(){return Array.from(this)}function T5(){for(var u=this._groups,f=0,l=u.length;f1?this.each((f==null?KO:typeof f==="function"?zO:GO)(u,f,l==null?"":l)):Hn(this.node(),u)}function Hn(u,f){return u.style.getPropertyValue(f)||s_(u).getComputedStyle(u,null).getPropertyValue(f)}function TO(u){return function(){delete this[u]}}function EO(u,f){return function(){this[u]=f}}function ZO(u,f){return function(){var l=f.apply(this,arguments);if(l==null)delete this[u];else this[u]=l}}function V5(u,f){return arguments.length>1?this.each((f==null?TO:typeof f==="function"?ZO:EO)(u,f)):this.node()[u]}function gQ(u){return u.trim().split(/^|\s+/)}function D5(u){return u.classList||new sQ(u)}function sQ(u){this._node=u,this._names=gQ(u.getAttribute("class")||"")}sQ.prototype={add:function(u){var f=this._names.indexOf(u);if(f<0)this._names.push(u),this._node.setAttribute("class",this._names.join(" "))},remove:function(u){var f=this._names.indexOf(u);if(f>=0)this._names.splice(f,1),this._node.setAttribute("class",this._names.join(" "))},contains:function(u){return this._names.indexOf(u)>=0}};function aQ(u,f){var l=D5(u),r=-1,n=f.length;while(++r=0)l=f.slice(r+1),f=f.slice(0,r);return{type:f,name:l}})}function IO(u){return function(){var f=this.__on;if(!f)return;for(var l=0,r=-1,n=f.length,i;l()=>u;function e_(u,{sourceEvent:f,subject:l,target:r,identifier:n,active:i,x:y,y:_,dx:$,dy:c,dispatch:A}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:f,enumerable:!0,configurable:!0},subject:{value:l,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:n,enumerable:!0,configurable:!0},active:{value:i,enumerable:!0,configurable:!0},x:{value:y,enumerable:!0,configurable:!0},y:{value:_,enumerable:!0,configurable:!0},dx:{value:$,enumerable:!0,configurable:!0},dy:{value:c,enumerable:!0,configurable:!0},_:{value:A}})}e_.prototype.on=function(){var u=this._.on.apply(this._,arguments);return u===this._?this:u};function iH(u){return!u.ctrlKey&&!u.button}function yH(){return this.parentNode}function _H(u,f){return f==null?{x:u.x,y:u.y}:f}function $H(){return navigator.maxTouchPoints||"ontouchstart"in this}function u$(){var u=iH,f=yH,l=_H,r=$H,n={},i=E1("start","drag","end"),y=0,_,$,c,A,j=0;function F(W){W.on("mousedown.drag",U).filter(r).on("touchstart.drag",L).on("touchmove.drag",J,uq).on("touchend.drag touchcancel.drag",N).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function U(W,z){if(A||!u.call(this,W,z))return;var Z=q(this,f.call(this,W,z),W,z,"mouse");if(!Z)return;of(W.view).on("mousemove.drag",Q,Z1).on("mouseup.drag",w,Z1),ki(W.view),c6(W),c=!1,_=W.clientX,$=W.clientY,Z("start",W)}function Q(W){if(p0(W),!c){var z=W.clientX-_,Z=W.clientY-$;c=z*z+Z*Z>j}n.mouse("drag",W)}function w(W){of(W.view).on("mousemove.drag mouseup.drag",null),o_(W.view,c),p0(W),n.mouse("end",W)}function L(W,z){if(!u.call(this,W,z))return;var Z=W.changedTouches,H=f.call(this,W,z),E=Z.length,D,h;for(D=0;D>8&15|f>>4&240,f>>4&15|f&240,(f&15)<<4|f&15,1):l===8?A6(f>>24&255,f>>16&255,f>>8&255,(f&255)/255):l===4?A6(f>>12&15|f>>8&240,f>>8&15|f>>4&240,f>>4&15|f&240,((f&15)<<4|f&15)/255):null):(f=cH.exec(u))?new vl(f[1],f[2],f[3],1):(f=AH.exec(u))?new vl(f[1]*255/100,f[2]*255/100,f[3]*255/100,1):(f=jH.exec(u))?A6(f[1],f[2],f[3],f[4]):(f=FH.exec(u))?A6(f[1]*255/100,f[2]*255/100,f[3]*255/100,f[4]):(f=JH.exec(u))?_q(f[1],f[2]/100,f[3]/100,1):(f=UH.exec(u))?_q(f[1],f[2]/100,f[3]/100,f[4]):fq.hasOwnProperty(u)?nq(fq[u]):u==="transparent"?new vl(NaN,NaN,NaN,0):null}function nq(u){return new vl(u>>16&255,u>>8&255,u&255,1)}function A6(u,f,l,r){if(r<=0)u=f=l=NaN;return new vl(u,f,l,r)}function NH(u){if(!(u instanceof n$))u=hr(u);if(!u)return new vl;return u=u.rgb(),new vl(u.r,u.g,u.b,u.opacity)}function gi(u,f,l,r){return arguments.length===1?NH(u):new vl(u,f,l,r==null?1:r)}function vl(u,f,l,r){this.r=+u,this.g=+f,this.b=+l,this.opacity=+r}f$(vl,gi,I5(n$,{brighter(u){return u=u==null?F6:Math.pow(F6,u),new vl(this.r*u,this.g*u,this.b*u,this.opacity)},darker(u){return u=u==null?l$:Math.pow(l$,u),new vl(this.r*u,this.g*u,this.b*u,this.opacity)},rgb(){return this},clamp(){return new vl(H1(this.r),H1(this.g),H1(this.b),J6(this.opacity))},displayable(){return-0.5<=this.r&&this.r<255.5&&(-0.5<=this.g&&this.g<255.5)&&(-0.5<=this.b&&this.b<255.5)&&(0<=this.opacity&&this.opacity<=1)},hex:iq,formatHex:iq,formatHex8:WH,formatRgb:yq,toString:yq}));function iq(){return`#${O1(this.r)}${O1(this.g)}${O1(this.b)}`}function WH(){return`#${O1(this.r)}${O1(this.g)}${O1(this.b)}${O1((isNaN(this.opacity)?1:this.opacity)*255)}`}function yq(){let u=J6(this.opacity);return`${u===1?"rgb(":"rgba("}${H1(this.r)}, ${H1(this.g)}, ${H1(this.b)}${u===1?")":`, ${u})`}`}function J6(u){return isNaN(u)?1:Math.max(0,Math.min(1,u))}function H1(u){return Math.max(0,Math.min(255,Math.round(u)||0))}function O1(u){return u=H1(u),(u<16?"0":"")+u.toString(16)}function _q(u,f,l,r){if(r<=0)u=f=l=NaN;else if(l<=0||l>=1)u=f=NaN;else if(f<=0)u=NaN;return new xr(u,f,l,r)}function tq(u){if(u instanceof xr)return new xr(u.h,u.s,u.l,u.opacity);if(!(u instanceof n$))u=hr(u);if(!u)return new xr;if(u instanceof xr)return u;u=u.rgb();var f=u.r/255,l=u.g/255,r=u.b/255,n=Math.min(f,l,r),i=Math.max(f,l,r),y=NaN,_=i-n,$=(i+n)/2;if(_){if(f===i)y=(l-r)/_+(l0&&$<1?0:y;return new xr(y,_,$,u.opacity)}function cq(u,f,l,r){return arguments.length===1?tq(u):new xr(u,f,l,r==null?1:r)}function xr(u,f,l,r){this.h=+u,this.s=+f,this.l=+l,this.opacity=+r}f$(xr,cq,I5(n$,{brighter(u){return u=u==null?F6:Math.pow(F6,u),new xr(this.h,this.s,this.l*u,this.opacity)},darker(u){return u=u==null?l$:Math.pow(l$,u),new xr(this.h,this.s,this.l*u,this.opacity)},rgb(){var u=this.h%360+(this.h<0)*360,f=isNaN(u)||isNaN(this.s)?0:this.s,l=this.l,r=l+(l<0.5?l:1-l)*f,n=2*l-r;return new vl(g5(u>=240?u-240:u+120,n,r),g5(u,n,r),g5(u<120?u+240:u-120,n,r),this.opacity)},clamp(){return new xr($q(this.h),j6(this.s),j6(this.l),J6(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&(0<=this.l&&this.l<=1)&&(0<=this.opacity&&this.opacity<=1)},formatHsl(){let u=J6(this.opacity);return`${u===1?"hsl(":"hsla("}${$q(this.h)}, ${j6(this.s)*100}%, ${j6(this.l)*100}%${u===1?")":`, ${u})`}`}}));function $q(u){return u=(u||0)%360,u<0?u+360:u}function j6(u){return Math.max(0,Math.min(1,u||0))}function g5(u,f,l){return(u<60?f+(l-f)*u/60:u<180?l:u<240?f+(l-f)*(240-u)/60:f)*255}function s5(u,f,l,r,n){var i=u*u,y=i*u;return((1-3*u+3*i-y)*f+(4-6*i+3*y)*l+(1+3*u+3*i-3*y)*r+y*n)/6}function a5(u){var f=u.length-1;return function(l){var r=l<=0?l=0:l>=1?(l=1,f-1):Math.floor(l*f),n=u[r],i=u[r+1],y=r>0?u[r-1]:2*n-i,_=r()=>u;function LH(u,f){return function(l){return u+l*f}}function KH(u,f,l){return u=Math.pow(u,l),f=Math.pow(f,l)-u,l=1/l,function(r){return Math.pow(u+r*f,l)}}function Aq(u){return(u=+u)===1?Q6:function(f,l){return l-f?KH(f,l,u):i$(isNaN(f)?l:f)}}function Q6(u,f){var l=f-u;return l?LH(u,l):i$(isNaN(u)?f:u)}var B1=function u(f){var l=Aq(f);function r(n,i){var y=l((n=gi(n)).r,(i=gi(i)).r),_=l(n.g,i.g),$=l(n.b,i.b),c=Q6(n.opacity,i.opacity);return function(A){return n.r=y(A),n.g=_(A),n.b=$(A),n.opacity=c(A),n+""}}return r.gamma=u,r}(1);function jq(u){return function(f){var l=f.length,r=Array(l),n=Array(l),i=Array(l),y,_;for(y=0;yl)if(i=f.slice(l,i),_[y])_[y]+=i;else _[++y]=i;if((r=r[0])===(n=n[0]))if(_[y])_[y]+=n;else _[++y]=n;else _[++y]=null,$.push({i:y,x:wl(r,n)});l=fA.lastIndex}if(l180)A+=360;else if(A-c>180)c+=360;F.push({i:j.push(n(j)+"rotate(",null,r)-2,x:wl(c,A)})}else if(A)j.push(n(j)+"rotate("+A+r)}function _(c,A,j,F){if(c!==A)F.push({i:j.push(n(j)+"skewX(",null,r)-2,x:wl(c,A)});else if(A)j.push(n(j)+"skewX("+A+r)}function $(c,A,j,F,U,Q){if(c!==j||A!==F){var w=U.push(n(U)+"scale(",null,",",null,")");Q.push({i:w-4,x:wl(c,j)},{i:w-2,x:wl(A,F)})}else if(j!==1||F!==1)U.push(n(U)+"scale("+j+","+F+")")}return function(c,A){var j=[],F=[];return c=u(c),A=u(A),i(c.translateX,c.translateY,A.translateX,A.translateY,j,F),y(c.rotate,A.rotate,j,F),_(c.skewX,A.skewX,j,F),$(c.scaleX,c.scaleY,A.scaleX,A.scaleY,j,F),c=A=null,function(U){var Q=-1,w=F.length,L;while(++Q=0)u._call.call(void 0,f);u=u._next}--ai}function Gq(){D1=(L6=t$.now())+K6,ai=_$=0;try{Eq()}finally{ai=0,bH(),D1=0}}function hH(){var u=t$.now(),f=u-L6;if(f>zq)K6-=f,L6=u}function bH(){var u,f=w6,l,r=1/0;while(f)if(f._call){if(r>f._time)r=f._time;u=f,f=f._next}else l=f._next,f._next=null,f=u?u._next=l:w6=l;$$=u,iA(r)}function iA(u){if(ai)return;if(_$)_$=clearTimeout(_$);var f=u-D1;if(f>24){if(u<1/0)_$=setTimeout(Gq,u-t$.now()-K6);if(y$)y$=clearInterval(y$)}else{if(!y$)L6=t$.now(),y$=setInterval(hH,zq);ai=1,Tq(Gq)}}function j$(u,f,l){var r=new c$;return f=f==null?0:+f,r.restart((n)=>{r.stop(),u(n+f)},f,l),r}var kH=E1("start","end","cancel","interrupt"),IH=[],Hq=0,Zq=1,T6=2,z6=3,Oq=4,E6=5,F$=6;function P0(u,f,l,r,n,i){var y=u.__transition;if(!y)u.__transition={};else if(l in y)return;gH(u,l,{name:f,index:r,group:n,on:kH,tween:IH,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:Hq})}function J$(u,f){var l=df(u,f);if(l.state>Hq)throw Error("too late; already scheduled");return l}function cl(u,f){var l=df(u,f);if(l.state>z6)throw Error("too late; already running");return l}function df(u,f){var l=u.__transition;if(!l||!(l=l[f]))throw Error("transition not found");return l}function gH(u,f,l){var r=u.__transition,n;r[f]=l,l.timer=G6(i,0,l.time);function i(c){if(l.state=Zq,l.timer.restart(y,l.delay,l.time),l.delay<=c)y(c-l.delay)}function y(c){var A,j,F,U;if(l.state!==Zq)return $();for(A in r){if(U=r[A],U.name!==l.name)continue;if(U.state===z6)return j$(y);if(U.state===Oq)U.state=F$,U.timer.stop(),U.on.call("interrupt",u,u.__data__,U.index,U.group),delete r[A];else if(+AT6&&r.state=0)f=f.slice(0,l);return!f||f==="start"})}function JB(u,f,l){var r,n,i=FB(f)?J$:cl;return function(){var y=i(this,u),_=y.on;if(_!==r)(n=(r=_).copy()).on(f,l);y.on=n}}function QA(u,f){var l=this._id;return arguments.length<2?df(this.node(),l).on.on(u):this.each(JB(l,u,f))}function UB(u){return function(){var f=this.parentNode;for(var l in this.__transition)if(+l!==u)return;if(f)f.removeChild(this)}}function qA(){return this.on("end.remove",UB(this._id))}function NA(u){var f=this._name,l=this._id;if(typeof u!=="function")u=On(u);for(var r=this._groups,n=r.length,i=Array(n),y=0;y()=>u;function OA(u,{sourceEvent:f,target:l,transform:r,dispatch:n}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:f,enumerable:!0,configurable:!0},target:{value:l,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:n}})}function br(u,f,l){this.k=u,this.x=f,this.y=l}br.prototype={constructor:br,scale:function(u){return u===1?this:new br(this.k*u,this.x,this.y)},translate:function(u,f){return u===0&f===0?this:new br(this.k,this.x+this.k*u,this.y+this.k*f)},apply:function(u){return[u[0]*this.k+this.x,u[1]*this.k+this.y]},applyX:function(u){return u*this.k+this.x},applyY:function(u){return u*this.k+this.y},invert:function(u){return[(u[0]-this.x)/this.k,(u[1]-this.y)/this.k]},invertX:function(u){return(u-this.x)/this.k},invertY:function(u){return(u-this.y)/this.k},rescaleX:function(u){return u.copy().domain(u.range().map(this.invertX,this).map(u.invert,u))},rescaleY:function(u){return u.copy().domain(u.range().map(this.invertY,this).map(u.invert,u))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var X1=new br(1,0,0);q$.prototype=br.prototype;function q$(u){while(!u.__zoom)if(!(u=u.parentNode))return X1;return u.__zoom}function p6(u){u.stopImmediatePropagation()}function Y1(u){u.preventDefault(),u.stopImmediatePropagation()}function VB(u){return(!u.ctrlKey||u.type==="wheel")&&!u.button}function DB(){var u=this;if(u instanceof SVGElement){if(u=u.ownerSVGElement||u,u.hasAttribute("viewBox"))return u=u.viewBox.baseVal,[[u.x,u.y],[u.x+u.width,u.y+u.height]];return[[0,0],[u.width.baseVal.value,u.height.baseVal.value]]}return[[0,0],[u.clientWidth,u.clientHeight]]}function Dq(){return this.__zoom||X1}function XB(u){return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*(u.ctrlKey?10:1)}function YB(){return navigator.maxTouchPoints||"ontouchstart"in this}function SB(u,f,l){var r=u.invertX(f[0][0])-l[0][0],n=u.invertX(f[1][0])-l[1][0],i=u.invertY(f[0][1])-l[0][1],y=u.invertY(f[1][1])-l[1][1];return u.translate(n>r?(r+n)/2:Math.min(0,r)||Math.max(0,n),y>i?(i+y)/2:Math.min(0,i)||Math.max(0,y))}function N$(){var u=VB,f=DB,l=SB,r=XB,n=YB,i=[0,1/0],y=[[-1/0,-1/0],[1/0,1/0]],_=250,$=V1,c=E1("start","zoom","end"),A,j,F,U=500,Q=150,w=0,L=10;function J(O){O.property("__zoom",Dq).on("wheel.zoom",E,{passive:!1}).on("mousedown.zoom",D).on("dblclick.zoom",h).filter(n).on("touchstart.zoom",B).on("touchmove.zoom",X).on("touchend.zoom touchcancel.zoom",m).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}J.transform=function(O,p,Y,v){var T=O.selection?O.selection():O;if(T.property("__zoom",Dq),O!==T)z(O,p,Y,v);else T.interrupt().each(function(){Z(this,arguments).event(v).start().zoom(null,typeof p==="function"?p.apply(this,arguments):p).end()})},J.scaleBy=function(O,p,Y,v){J.scaleTo(O,function(){var T=this.__zoom.k,S=typeof p==="function"?p.apply(this,arguments):p;return T*S},Y,v)},J.scaleTo=function(O,p,Y,v){J.transform(O,function(){var T=f.apply(this,arguments),S=this.__zoom,k=Y==null?W(T):typeof Y==="function"?Y.apply(this,arguments):Y,I=S.invert(k),b=typeof p==="function"?p.apply(this,arguments):p;return l(q(N(S,b),k,I),T,y)},Y,v)},J.translateBy=function(O,p,Y,v){J.transform(O,function(){return l(this.__zoom.translate(typeof p==="function"?p.apply(this,arguments):p,typeof Y==="function"?Y.apply(this,arguments):Y),f.apply(this,arguments),y)},null,v)},J.translateTo=function(O,p,Y,v,T){J.transform(O,function(){var S=f.apply(this,arguments),k=this.__zoom,I=v==null?W(S):typeof v==="function"?v.apply(this,arguments):v;return l(X1.translate(I[0],I[1]).scale(k.k).translate(typeof p==="function"?-p.apply(this,arguments):-p,typeof Y==="function"?-Y.apply(this,arguments):-Y),S,y)},v,T)};function N(O,p){return p=Math.max(i[0],Math.min(i[1],p)),p===O.k?O:new br(p,O.x,O.y)}function q(O,p,Y){var v=p[0]-Y[0]*O.k,T=p[1]-Y[1]*O.k;return v===O.x&&T===O.y?O:new br(O.k,v,T)}function W(O){return[(+O[0][0]+ +O[1][0])/2,(+O[0][1]+ +O[1][1])/2]}function z(O,p,Y,v){O.on("start.zoom",function(){Z(this,arguments).event(v).start()}).on("interrupt.zoom end.zoom",function(){Z(this,arguments).event(v).end()}).tween("zoom",function(){var T=this,S=arguments,k=Z(T,S).event(v),I=f.apply(T,S),b=Y==null?W(I):typeof Y==="function"?Y.apply(T,S):Y,o=Math.max(I[1][0]-I[0][0],I[1][1]-I[0][1]),s=T.__zoom,x=typeof p==="function"?p.apply(T,S):p,fu=$(s.invert(b).concat(o/s.k),x.invert(b).concat(o/x.k));return function($u){if($u===1)$u=x;else{var tu=fu($u),ju=o/tu[2];$u=new br(ju,b[0]-tu[0]*ju,b[1]-tu[1]*ju)}k.zoom(null,$u)}})}function Z(O,p,Y){return!Y&&O.__zooming||new H(O,p)}function H(O,p){this.that=O,this.args=p,this.active=0,this.sourceEvent=null,this.extent=f.apply(O,p),this.taps=0}H.prototype={event:function(O){if(O)this.sourceEvent=O;return this},start:function(){if(++this.active===1)this.that.__zooming=this,this.emit("start");return this},zoom:function(O,p){if(this.mouse&&O!=="mouse")this.mouse[1]=p.invert(this.mouse[0]);if(this.touch0&&O!=="touch")this.touch0[1]=p.invert(this.touch0[0]);if(this.touch1&&O!=="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(O){var p=of(this.that).datum();c.call(O,this.that,new OA(O,{sourceEvent:this.sourceEvent,target:J,type:O,transform:this.that.__zoom,dispatch:c}),p)}};function E(O,...p){if(!u.apply(this,arguments))return;var Y=Z(this,p).event(O),v=this.__zoom,T=Math.max(i[0],Math.min(i[1],v.k*Math.pow(2,r.apply(this,arguments)))),S=Wl(O);if(Y.wheel){if(Y.mouse[0][0]!==S[0]||Y.mouse[0][1]!==S[1])Y.mouse[1]=v.invert(Y.mouse[0]=S);clearTimeout(Y.wheel)}else if(v.k===T)return;else Y.mouse=[S,v.invert(S)],Bn(this),Y.start();Y1(O),Y.wheel=setTimeout(k,Q),Y.zoom("mouse",l(q(N(v,T),Y.mouse[0],Y.mouse[1]),Y.extent,y));function k(){Y.wheel=null,Y.end()}}function D(O,...p){if(F||!u.apply(this,arguments))return;var Y=O.currentTarget,v=Z(this,p,!0).event(O),T=of(O.view).on("mousemove.zoom",b,!0).on("mouseup.zoom",o,!0),S=Wl(O,Y),k=O.clientX,I=O.clientY;ki(O.view),p6(O),v.mouse=[S,this.__zoom.invert(S)],Bn(this),v.start();function b(s){if(Y1(s),!v.moved){var x=s.clientX-k,fu=s.clientY-I;v.moved=x*x+fu*fu>w}v.event(s).zoom("mouse",l(q(v.that.__zoom,v.mouse[0]=Wl(s,Y),v.mouse[1]),v.extent,y))}function o(s){T.on("mousemove.zoom mouseup.zoom",null),o_(s.view,v.moved),Y1(s),v.event(s).end()}}function h(O,...p){if(!u.apply(this,arguments))return;var Y=this.__zoom,v=Wl(O.changedTouches?O.changedTouches[0]:O,this),T=Y.invert(v),S=Y.k*(O.shiftKey?0.5:2),k=l(q(N(Y,S),v,T),f.apply(this,p),y);if(Y1(O),_>0)of(this).transition().duration(_).call(z,k,v,O);else of(this).call(J.transform,k,v,O)}function B(O,...p){if(!u.apply(this,arguments))return;var Y=O.touches,v=Y.length,T=Z(this,p,O.changedTouches.length===v).event(O),S,k,I,b;p6(O);for(k=0;k"[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001",error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:(u)=>`Node type "${u}" not found. Using fallback type "default".`,error004:()=>"The React Flow parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:(u)=>`The old edge with id=${u} does not exist.`,error009:(u)=>`Marker type "${u}" doesn't exist.`,error008:(u,{id:f,sourceHandle:l,targetHandle:r})=>`Couldn't create edge for ${u} handle id: "${u==="source"?l:r}", edge id: ${f}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:(u)=>`Edge type "${u}" not found. Using fallback type "default".`,error012:(u)=>`Node with id "${u}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(u="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${u}/dist/style.css' or base.css to make sure everything is working properly.`,error014:()=>"useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.",error015:()=>"It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs."},ly=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],XA=["Enter"," ","Escape"],YA={"node.a11yDescription.default":"Press enter or space to select a node. Press delete to remove it and escape to cancel.","node.a11yDescription.keyboardDisabled":"Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.","node.a11yDescription.ariaLiveMessage":({direction:u,x:f,y:l})=>`Moved selected node ${u}. New position, x: ${f}, y: ${l}`,"edge.a11yDescription.default":"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.","controls.ariaLabel":"Control Panel","controls.zoomIn.ariaLabel":"Zoom In","controls.zoomOut.ariaLabel":"Zoom Out","controls.fitView.ariaLabel":"Fit View","controls.interactive.ariaLabel":"Toggle Interactivity","minimap.ariaLabel":"Mini Map","handle.ariaLabel":"Handle"},Xn;(function(u){u.Strict="strict",u.Loose="loose"})(Xn||(Xn={}));var C0;(function(u){u.Free="free",u.Vertical="vertical",u.Horizontal="horizontal"})(C0||(C0={}));var S1;(function(u){u.Partial="partial",u.Full="full"})(S1||(S1={}));var SA={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null},_0;(function(u){u.Bezier="default",u.Straight="straight",u.Step="step",u.SmoothStep="smoothstep",u.SimpleBezier="simplebezier"})(_0||(_0={}));var Yn;(function(u){u.Arrow="arrow",u.ArrowClosed="arrowclosed"})(Yn||(Yn={}));var Lu;(function(u){u.Left="left",u.Top="top",u.Right="right",u.Bottom="bottom"})(Lu||(Lu={}));var Xq={[Lu.Left]:Lu.Right,[Lu.Right]:Lu.Left,[Lu.Top]:Lu.Bottom,[Lu.Bottom]:Lu.Top};function mA(u){return u===null?null:u?"valid":"invalid"}var pA=(u)=>("id"in u)&&("source"in u)&&("target"in u),kq=(u)=>("id"in u)&&("position"in u)&&!("source"in u)&&!("target"in u),PA=(u)=>("id"in u)&&("internals"in u)&&!("source"in u)&&!("target"in u);var L$=(u,f=[0,0])=>{let{width:l,height:r}=$0(u),n=u.origin??f,i=l*n[0],y=r*n[1];return{x:u.position.x-i,y:u.position.y-y}},MA=(u,f={nodeOrigin:[0,0]})=>{if(u.length===0)return{x:0,y:0,width:0,height:0};let l=u.reduce((r,n)=>{let i=typeof n==="string",y=!f.nodeLookup&&!i?n:void 0;if(f.nodeLookup)y=i?f.nodeLookup.get(n):!PA(n)?f.nodeLookup.get(n.id):n;let _=y?C6(y,f.nodeOrigin):{x:0,y:0,x2:0,y2:0};return x6(r,_)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return h6(l)},ry=(u,f={})=>{let l={x:1/0,y:1/0,x2:-1/0,y2:-1/0},r=!1;return u.forEach((n)=>{if(f.filter===void 0||f.filter(n))l=x6(l,C6(n)),r=!0}),r?h6(l):{x:0,y:0,width:0,height:0}},R6=(u,f,[l,r,n]=[0,0,1],i=!1,y=!1)=>{let _={...yy(f,[l,r,n]),width:f.width/n,height:f.height/n},$=[];for(let c of u.values()){let{measured:A,selectable:j=!0,hidden:F=!1}=c;if(y&&!j||F)continue;let U=A.width??c.width??c.initialWidth??null,Q=A.height??c.height??c.initialHeight??null,w=ny(_,p1(c)),L=(U??0)*(Q??0),J=i&&w>0;if(!c.internals.handleBounds||J||w>=L||c.dragging)$.push(c)}return $},Iq=(u,f)=>{let l=new Set;return u.forEach((r)=>{l.add(r.id)}),f.filter((r)=>l.has(r.source)||l.has(r.target))};function mB(u,f){let l=new Map,r=f?.nodes?new Set(f.nodes.map((n)=>n.id)):null;return u.forEach((n)=>{if(n.measured.width&&n.measured.height&&(f?.includeHiddenNodes||!n.hidden)&&(!r||r.has(n.id)))l.set(n.id,n)}),l}async function gq({nodes:u,width:f,height:l,panZoom:r,minZoom:n,maxZoom:i},y){if(u.size===0)return Promise.resolve(!0);let _=mB(u,y),$=ry(_),c=K$($,f,l,y?.minZoom??n,y?.maxZoom??i,y?.padding??0.1);return await r.setViewport(c,{duration:y?.duration,ease:y?.ease,interpolate:y?.interpolate}),Promise.resolve(!0)}function CA({nodeId:u,nextPosition:f,nodeLookup:l,nodeOrigin:r=[0,0],nodeExtent:n,onError:i}){let y=l.get(u),_=y.parentId?l.get(y.parentId):void 0,{x:$,y:c}=_?_.internals.positionAbsolute:{x:0,y:0},A=y.origin??r,j=y.extent||n;if(y.extent==="parent"&&!y.expandParent)if(!_)i?.("005",tr.error005());else{let U=_.measured.width,Q=_.measured.height;if(U&&Q)j=[[$,c],[$+U,c+Q]]}else if(_&&fy(y.extent))j=[[y.extent[0][0]+$,y.extent[0][1]+c],[y.extent[1][0]+$,y.extent[1][1]+c]];let F=fy(j)?m1(f,j,y.measured):f;if(y.measured.width===void 0||y.measured.height===void 0)i?.("015",tr.error015());return{position:{x:F.x-$+(y.measured.width??0)*A[0],y:F.y-c+(y.measured.height??0)*A[1]},positionAbsolute:F}}async function sq({nodesToRemove:u=[],edgesToRemove:f=[],nodes:l,edges:r,onBeforeDelete:n}){let i=new Set(u.map((F)=>F.id)),y=[];for(let F of l){if(F.deletable===!1)continue;let U=i.has(F.id),Q=!U&&F.parentId&&y.find((w)=>w.id===F.parentId);if(U||Q)y.push(F)}let _=new Set(f.map((F)=>F.id)),$=r.filter((F)=>F.deletable!==!1),A=Iq(y,$);for(let F of $)if(_.has(F.id)&&!A.find((Q)=>Q.id===F.id))A.push(F);if(!n)return{edges:A,nodes:y};let j=await n({nodes:y,edges:A});if(typeof j==="boolean")return j?{edges:A,nodes:y}:{edges:[],nodes:[]};return j}var uy=(u,f=0,l=1)=>Math.min(Math.max(u,f),l),m1=(u={x:0,y:0},f,l)=>({x:uy(u.x,f[0][0],f[1][0]-(l?.width??0)),y:uy(u.y,f[0][1],f[1][1]-(l?.height??0))});function aq(u,f,l){let{width:r,height:n}=$0(l),{x:i,y}=l.internals.positionAbsolute;return m1(u,[[i,y],[i+r,y+n]],f)}var Yq=(u,f,l)=>{if(ul)return-uy(Math.abs(u-l),1,f)/f;return 0},oq=(u,f,l=15,r=40)=>{let n=Yq(u.x,r,f.width-r)*l,i=Yq(u.y,r,f.height-r)*l;return[n,i]},x6=(u,f)=>({x:Math.min(u.x,f.x),y:Math.min(u.y,f.y),x2:Math.max(u.x2,f.x2),y2:Math.max(u.y2,f.y2)}),DA=({x:u,y:f,width:l,height:r})=>({x:u,y:f,x2:u+l,y2:f+r}),h6=({x:u,y:f,x2:l,y2:r})=>({x:u,y:f,width:l-u,height:r-f}),p1=(u,f=[0,0])=>{let{x:l,y:r}=PA(u)?u.internals.positionAbsolute:L$(u,f);return{x:l,y:r,width:u.measured?.width??u.width??u.initialWidth??0,height:u.measured?.height??u.height??u.initialHeight??0}},C6=(u,f=[0,0])=>{let{x:l,y:r}=PA(u)?u.internals.positionAbsolute:L$(u,f);return{x:l,y:r,x2:l+(u.measured?.width??u.width??u.initialWidth??0),y2:r+(u.measured?.height??u.height??u.initialHeight??0)}},RA=(u,f)=>h6(x6(DA(u),DA(f))),ny=(u,f)=>{let l=Math.max(0,Math.min(u.x+u.width,f.x+f.width)-Math.max(u.x,f.x)),r=Math.max(0,Math.min(u.y+u.height,f.y+f.height)-Math.max(u.y,f.y));return Math.ceil(l*r)},xA=(u)=>Gr(u.width)&&Gr(u.height)&&Gr(u.x)&&Gr(u.y),Gr=(u)=>!isNaN(u)&&isFinite(u),hA=(u,f)=>{},iy=(u,f=[1,1])=>{return{x:f[0]*Math.round(u.x/f[0]),y:f[1]*Math.round(u.y/f[1])}},yy=({x:u,y:f},[l,r,n],i=!1,y=[1,1])=>{let _={x:(u-l)/n,y:(f-r)/n};return i?iy(_,y):_},w$=({x:u,y:f},[l,r,n])=>{return{x:u*n+l,y:f*n+r}};function di(u,f){if(typeof u==="number")return Math.floor((f-f/(1+u))*0.5);if(typeof u==="string"&&u.endsWith("px")){let l=parseFloat(u);if(!Number.isNaN(l))return Math.floor(l)}if(typeof u==="string"&&u.endsWith("%")){let l=parseFloat(u);if(!Number.isNaN(l))return Math.floor(f*l*0.01)}return console.error(`[React Flow] The padding value "${u}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function pB(u,f,l){if(typeof u==="string"||typeof u==="number"){let r=di(u,l),n=di(u,f);return{top:r,right:n,bottom:r,left:n,x:n*2,y:r*2}}if(typeof u==="object"){let r=di(u.top??u.y??0,l),n=di(u.bottom??u.y??0,l),i=di(u.left??u.x??0,f),y=di(u.right??u.x??0,f);return{top:r,right:y,bottom:n,left:i,x:i+y,y:r+n}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function PB(u,f,l,r,n,i){let{x:y,y:_}=w$(u,[f,l,r]),{x:$,y:c}=w$({x:u.x+u.width,y:u.y+u.height},[f,l,r]),A=n-$,j=i-c;return{left:Math.floor(y),top:Math.floor(_),right:Math.floor(A),bottom:Math.floor(j)}}var K$=(u,f,l,r,n,i)=>{let y=pB(i,f,l),_=(f-y.x)/u.width,$=(l-y.y)/u.height,c=Math.min(_,$),A=uy(c,r,n),j=u.x+u.width/2,F=u.y+u.height/2,U=f/2-j*A,Q=l/2-F*A,w=PB(u,U,Q,A,f,l),L={left:Math.min(w.left-y.left,0),top:Math.min(w.top-y.top,0),right:Math.min(w.right-y.right,0),bottom:Math.min(w.bottom-y.bottom,0)};return{x:U-L.left+L.right,y:Q-L.top+L.bottom,zoom:A}},_y=()=>typeof navigator<"u"&&navigator?.userAgent?.indexOf("Mac")>=0;function fy(u){return u!==void 0&&u!==null&&u!=="parent"}function $0(u){return{width:u.measured?.width??u.width??u.initialWidth??0,height:u.measured?.height??u.height??u.initialHeight??0}}function bA(u){return(u.measured?.width??u.width??u.initialWidth)!==void 0&&(u.measured?.height??u.height??u.initialHeight)!==void 0}function vA(u,f={width:0,height:0},l,r,n){let i={...u},y=r.get(l);if(y){let _=y.origin||n;i.x+=y.internals.positionAbsolute.x-(f.width??0)*_[0],i.y+=y.internals.positionAbsolute.y-(f.height??0)*_[1]}return i}function kA(u,f){if(u.size!==f.size)return!1;for(let l of u)if(!f.has(l))return!1;return!0}function dq(){let u,f;return{promise:new Promise((r,n)=>{u=r,f=n}),resolve:u,reject:f}}function eq(u){return{...YA,...u||{}}}function W$(u,{snapGrid:f=[0,0],snapToGrid:l=!1,transform:r,containerBounds:n}){let{x:i,y}=zr(u),_=yy({x:i-(n?.left??0),y:y-(n?.top??0)},r),{x:$,y:c}=l?iy(_,f):_;return{xSnapped:$,ySnapped:c,..._}}var b6=(u)=>({width:u.offsetWidth,height:u.offsetHeight}),IA=(u)=>u?.getRootNode?.()||window?.document,MB=["INPUT","SELECT","TEXTAREA"];function gA(u){let f=u.composedPath?.()?.[0]||u.target;if(f?.nodeType!==1)return!1;return MB.includes(f.nodeName)||f.hasAttribute("contenteditable")||!!f.closest(".nokey")}var sA=(u)=>("clientX"in u),zr=(u,f)=>{let l=sA(u),r=l?u.clientX:u.touches?.[0].clientX,n=l?u.clientY:u.touches?.[0].clientY;return{x:r-(f?.left??0),y:n-(f?.top??0)}},Sq=(u,f,l,r,n)=>{let i=f.querySelectorAll(`.${u}`);if(!i||!i.length)return null;return Array.from(i).map((y)=>{let _=y.getBoundingClientRect();return{id:y.getAttribute("data-handleid"),type:u,nodeId:n,position:y.getAttribute("data-handlepos"),x:(_.left-l.left)/r,y:(_.top-l.top)/r,...b6(y)}})};function v6({sourceX:u,sourceY:f,targetX:l,targetY:r,sourceControlX:n,sourceControlY:i,targetControlX:y,targetControlY:_}){let $=u*0.125+n*0.375+y*0.375+l*0.125,c=f*0.125+i*0.375+_*0.375+r*0.125,A=Math.abs($-u),j=Math.abs(c-f);return[$,c,A,j]}function P6(u,f){if(u>=0)return 0.5*u;return f*25*Math.sqrt(-u)}function mq({pos:u,x1:f,y1:l,x2:r,y2:n,c:i}){switch(u){case Lu.Left:return[f-P6(f-r,i),l];case Lu.Right:return[f+P6(r-f,i),l];case Lu.Top:return[f,l-P6(l-n,i)];case Lu.Bottom:return[f,l+P6(n-l,i)]}}function k6({sourceX:u,sourceY:f,sourcePosition:l=Lu.Bottom,targetX:r,targetY:n,targetPosition:i=Lu.Top,curvature:y=0.25}){let[_,$]=mq({pos:l,x1:u,y1:f,x2:r,y2:n,c:y}),[c,A]=mq({pos:i,x1:r,y1:n,x2:u,y2:f,c:y}),[j,F,U,Q]=v6({sourceX:u,sourceY:f,targetX:r,targetY:n,sourceControlX:_,sourceControlY:$,targetControlX:c,targetControlY:A});return[`M${u},${f} C${_},${$} ${c},${A} ${r},${n}`,j,F,U,Q]}function aA({sourceX:u,sourceY:f,targetX:l,targetY:r}){let n=Math.abs(l-u)/2,i=l0}var CB=({source:u,sourceHandle:f,target:l,targetHandle:r})=>`xy-edge__${u}${f||""}-${l}${r||""}`,RB=(u,f)=>{return f.some((l)=>l.source===u.source&&l.target===u.target&&(l.sourceHandle===u.sourceHandle||!l.sourceHandle&&!u.sourceHandle)&&(l.targetHandle===u.targetHandle||!l.targetHandle&&!u.targetHandle))},oA=(u,f,l={})=>{if(!u.source||!u.target)return hA("006",tr.error006()),f;let r=l.getEdgeId||CB,n;if(pA(u))n={...u};else n={...u,id:r(u)};if(RB(n,f))return f;if(n.sourceHandle===null)delete n.sourceHandle;if(n.targetHandle===null)delete n.targetHandle;return f.concat(n)};function I6({sourceX:u,sourceY:f,targetX:l,targetY:r}){let[n,i,y,_]=aA({sourceX:u,sourceY:f,targetX:l,targetY:r});return[`M ${u},${f}L ${l},${r}`,n,i,y,_]}var pq={[Lu.Left]:{x:-1,y:0},[Lu.Right]:{x:1,y:0},[Lu.Top]:{x:0,y:-1},[Lu.Bottom]:{x:0,y:1}},xB=({source:u,sourcePosition:f=Lu.Bottom,target:l})=>{if(f===Lu.Left||f===Lu.Right)return u.xMath.sqrt(Math.pow(f.x-u.x,2)+Math.pow(f.y-u.y,2));function hB({source:u,sourcePosition:f=Lu.Bottom,target:l,targetPosition:r=Lu.Top,center:n,offset:i,stepPosition:y}){let _=pq[f],$=pq[r],c={x:u.x+_.x*i,y:u.y+_.y*i},A={x:l.x+$.x*i,y:l.y+$.y*i},j=xB({source:c,sourcePosition:f,target:A}),F=j.x!==0?"x":"y",U=j[F],Q=[],w,L,J={x:0,y:0},N={x:0,y:0},[,,q,W]=aA({sourceX:u.x,sourceY:u.y,targetX:l.x,targetY:l.y});if(_[F]*$[F]===-1){if(F==="x")w=n.x??c.x+(A.x-c.x)*y,L=n.y??(c.y+A.y)/2;else w=n.x??(c.x+A.x)/2,L=n.y??c.y+(A.y-c.y)*y;let E=[{x:w,y:c.y},{x:w,y:A.y}],D=[{x:c.x,y:L},{x:A.x,y:L}];if(_[F]===U)Q=F==="x"?E:D;else Q=F==="x"?D:E}else{let E=[{x:c.x,y:A.y}],D=[{x:A.x,y:c.y}];if(F==="x")Q=_.x===U?D:E;else Q=_.y===U?E:D;if(f===r){let O=Math.abs(u[F]-l[F]);if(O<=i){let p=Math.min(i-1,i-O);if(_[F]===U)J[F]=(c[F]>u[F]?-1:1)*p;else N[F]=(A[F]>l[F]?-1:1)*p}}if(f!==r){let O=F==="x"?"y":"x",p=_[F]===$[O],Y=c[O]>A[O],v=c[O]=m)w=(h.x+B.x)/2,L=Q[0].y;else w=Q[0].x,L=(h.y+B.y)/2}let z={x:c.x+J.x,y:c.y+J.y},Z={x:A.x+N.x,y:A.y+N.y};return[[u,...z.x!==Q[0].x||z.y!==Q[0].y?[z]:[],...Q,...Z.x!==Q[Q.length-1].x||Z.y!==Q[Q.length-1].y?[Z]:[],l],w,L,q,W]}function bB(u,f,l,r){let n=Math.min(Pq(u,f)/2,Pq(f,l)/2,r),{x:i,y}=f;if(u.x===i&&i===l.x||u.y===y&&y===l.y)return`L${i} ${y}`;if(u.y===y){let c=u.xl.id===f))||null}function g6(u,f){if(!u)return"";if(typeof u==="string")return u;return`${f?`${f}__`:""}${Object.keys(u).sort().map((r)=>`${r}=${u[r]}`).join("&")}`}function rN(u,{id:f,defaultColor:l,defaultMarkerStart:r,defaultMarkerEnd:n}){let i=new Set;return u.reduce((y,_)=>{return[_.markerStart||r,_.markerEnd||n].forEach(($)=>{if($&&typeof $==="object"){let c=g6($,f);if(!i.has(c))y.push({id:c,color:$.color||l,...$}),i.add(c)}}),y},[]).sort((y,_)=>y.id.localeCompare(_.id))}var nN=1000,vB=10,dA={nodeOrigin:[0,0],nodeExtent:ly,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},kB={...dA,checkEquality:!0};function eA(u,f){let l={...u};for(let r in f)if(f[r]!==void 0)l[r]=f[r];return l}function iN(u,f,l){let r=eA(dA,l);for(let n of u.values())if(n.parentId)f9(n,u,f,r);else{let i=L$(n,r.nodeOrigin),y=fy(n.extent)?n.extent:r.nodeExtent,_=m1(i,y,$0(n));n.internals.positionAbsolute=_}}function IB(u,f){if(!u.handles)return!u.measured?void 0:f?.internals.handleBounds;let l=[],r=[];for(let n of u.handles){let i={id:n.id,width:n.width??1,height:n.height??1,nodeId:u.id,x:n.x,y:n.y,position:n.position,type:n.type};if(n.type==="source")l.push(i);else if(n.type==="target")r.push(i)}return{source:l,target:r}}function u9(u){return u==="manual"}function s6(u,f,l,r={}){let n=eA(kB,r),i={i:0},y=new Map(f),_=n?.elevateNodesOnSelect&&!u9(n.zIndexMode)?nN:0,$=u.length>0,c=!1;f.clear(),l.clear();for(let A of u){let j=y.get(A.id);if(n.checkEquality&&A===j?.internals.userNode)f.set(A.id,j);else{let F=L$(A,n.nodeOrigin),U=fy(A.extent)?A.extent:n.nodeExtent,Q=m1(F,U,$0(A));j={...n.defaults,...A,measured:{width:A.measured?.width,height:A.measured?.height},internals:{positionAbsolute:Q,handleBounds:IB(A,j),z:yN(A,_,n.zIndexMode),userNode:A}},f.set(A.id,j)}if((j.measured===void 0||j.measured.width===void 0||j.measured.height===void 0)&&!j.hidden)$=!1;if(A.parentId)f9(j,f,l,r,i);c||=A.selected??!1}return{nodesInitialized:$,hasSelectedNodes:c}}function gB(u,f){if(!u.parentId)return;let l=f.get(u.parentId);if(l)l.set(u.id,u);else f.set(u.parentId,new Map([[u.id,u]]))}function f9(u,f,l,r,n){let{elevateNodesOnSelect:i,nodeOrigin:y,nodeExtent:_,zIndexMode:$}=eA(dA,r),c=u.parentId,A=f.get(c);if(!A){console.warn(`Parent node ${c} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}if(gB(u,l),n&&!A.parentId&&A.internals.rootParentIndex===void 0&&$==="auto")A.internals.rootParentIndex=++n.i,A.internals.z=A.internals.z+n.i*vB;if(n&&A.internals.rootParentIndex!==void 0)n.i=A.internals.rootParentIndex;let j=i&&!u9($)?nN:0,{x:F,y:U,z:Q}=sB(u,A,y,_,j,$),{positionAbsolute:w}=u.internals,L=F!==w.x||U!==w.y;if(L||Q!==u.internals.z)f.set(u.id,{...u,internals:{...u.internals,positionAbsolute:L?{x:F,y:U}:w,z:Q}})}function yN(u,f,l){let r=Gr(u.zIndex)?u.zIndex:0;if(u9(l))return r;return r+(u.selected?f:0)}function sB(u,f,l,r,n,i){let{x:y,y:_}=f.internals.positionAbsolute,$=$0(u),c=L$(u,l),A=fy(u.extent)?m1(c,u.extent,$):c,j=m1({x:y+A.x,y:_+A.y},r,$);if(u.extent==="parent")j=aq(j,$,f);let F=yN(u,n,i),U=f.internals.z??0;return{x:j.x,y:j.y,z:U>=F?U+1:F}}function a6(u,f,l,r=[0,0]){let n=[],i=new Map;for(let y of u){let _=f.get(y.parentId);if(!_)continue;let $=i.get(y.parentId)?.expandedRect??p1(_),c=RA($,y.rect);i.set(y.parentId,{expandedRect:c,parent:_})}if(i.size>0)i.forEach(({expandedRect:y,parent:_},$)=>{let c=_.internals.positionAbsolute,A=$0(_),j=_.origin??r,F=y.x0||U>0||L||J)n.push({id:$,type:"position",position:{x:_.position.x-F+L,y:_.position.y-U+J}}),l.get($)?.forEach((N)=>{if(!u.some((q)=>q.id===N.id))n.push({id:N.id,type:"position",position:{x:N.position.x+F,y:N.position.y+U}})});if(A.width0){let U=a6(F,f,l,n);c.push(...U)}return{changes:c,updatedInternals:$}}async function $N({delta:u,panZoom:f,transform:l,translateExtent:r,width:n,height:i}){if(!f||!u.x&&!u.y)return Promise.resolve(!1);let y=await f.setViewportConstrained({x:l[0]+u.x,y:l[1]+u.y,zoom:l[2]},[[0,0],[n,i]],r),_=!!y&&(y.x!==l[0]||y.y!==l[1]||y.k!==l[2]);return Promise.resolve(_)}function xq(u,f,l,r,n,i){let y=n,_=r.get(y)||new Map;r.set(y,_.set(l,f)),y=`${n}-${u}`;let $=r.get(y)||new Map;if(r.set(y,$.set(l,f)),i){y=`${n}-${u}-${i}`;let c=r.get(y)||new Map;r.set(y,c.set(l,f))}}function l9(u,f,l){u.clear(),f.clear();for(let r of l){let{source:n,target:i,sourceHandle:y=null,targetHandle:_=null}=r,$={edgeId:r.id,source:n,target:i,sourceHandle:y,targetHandle:_},c=`${n}-${y}--${i}-${_}`,A=`${i}-${_}--${n}-${y}`;xq("source",$,A,u,n,y),xq("target",$,c,u,i,_),f.set(r.id,r)}}function tN(u,f){if(!u.parentId)return!1;let l=f.get(u.parentId);if(!l)return!1;if(l.selected)return!0;return tN(l,f)}function hq(u,f,l){let r=u;do{if(r?.matches?.(f))return!0;if(r===l)return!1;r=r?.parentElement}while(r);return!1}function aB(u,f,l,r){let n=new Map;for(let[i,y]of u)if((y.selected||y.id===r)&&(!y.parentId||!tN(y,u))&&(y.draggable||f&&typeof y.draggable>"u")){let _=u.get(i);if(_)n.set(i,{id:i,position:_.position||{x:0,y:0},distance:{x:l.x-_.internals.positionAbsolute.x,y:l.y-_.internals.positionAbsolute.y},extent:_.extent,parentId:_.parentId,origin:_.origin,expandParent:_.expandParent,internals:{positionAbsolute:_.internals.positionAbsolute||{x:0,y:0}},measured:{width:_.measured.width??0,height:_.measured.height??0}})}return n}function HA({nodeId:u,dragItems:f,nodeLookup:l,dragging:r=!0}){let n=[];for(let[y,_]of f){let $=l.get(y)?.internals.userNode;if($)n.push({...$,position:_.position,dragging:r})}if(!u)return[n[0],n];let i=l.get(u)?.internals.userNode;return[!i?n[0]:{...i,position:f.get(u)?.position||i.position,dragging:r},n]}function oB({dragItems:u,snapGrid:f,x:l,y:r}){let n=u.values().next().value;if(!n)return null;let i={x:l-n.distance.x,y:r-n.distance.y},y=iy(i,f);return{x:y.x-i.x,y:y.y-i.y}}function cN({onNodeMouseDown:u,getStoreItems:f,onDragStart:l,onDrag:r,onDragStop:n}){let i={x:null,y:null},y=0,_=new Map,$=!1,c={x:0,y:0},A=null,j=!1,F=null,U=!1,Q=!1,w=null;function L({noDragClassName:N,handleSelector:q,domNode:W,isSelectable:z,nodeId:Z,nodeClickDistance:H=0}){F=of(W);function E({x:X,y:m}){let{nodeLookup:O,nodeExtent:p,snapGrid:Y,snapToGrid:v,nodeOrigin:T,onNodeDrag:S,onSelectionDrag:k,onError:I,updateNodePositions:b}=f();i={x:X,y:m};let o=!1,s=_.size>1,x=s&&p?DA(ry(_)):null,fu=s&&v?oB({dragItems:_,snapGrid:Y,x:X,y:m}):null;for(let[$u,tu]of _){if(!O.has($u))continue;let ju={x:X-tu.distance.x,y:m-tu.distance.y};if(v)ju=fu?{x:Math.round(ju.x+fu.x),y:Math.round(ju.y+fu.y)}:iy(ju,Y);let Gu=null;if(s&&p&&!tu.extent&&x){let{positionAbsolute:e}=tu.internals,uu=e.x-x.x+p[0][0],Wu=e.x+tu.measured.width-x.x2+p[1][0],g=e.y-x.y+p[0][1],Qu=e.y+tu.measured.height-x.y2+p[1][1];Gu=[[uu,g],[Wu,Qu]]}let{position:qu,positionAbsolute:P}=CA({nodeId:$u,nextPosition:ju,nodeLookup:O,nodeExtent:Gu?Gu:p,nodeOrigin:T,onError:I});o=o||tu.position.x!==qu.x||tu.position.y!==qu.y,tu.position=qu,tu.internals.positionAbsolute=P}if(Q=Q||o,!o)return;if(b(_,!0),w&&(r||S||!Z&&k)){let[$u,tu]=HA({nodeId:Z,dragItems:_,nodeLookup:O});if(r?.(w,_,$u,tu),S?.(w,$u,tu),!Z)k?.(w,tu)}}async function D(){if(!A)return;let{transform:X,panBy:m,autoPanSpeed:O,autoPanOnNodeDrag:p}=f();if(!p){$=!1,cancelAnimationFrame(y);return}let[Y,v]=oq(c,A,O);if(Y!==0||v!==0){if(i.x=(i.x??0)-Y/X[2],i.y=(i.y??0)-v/X[2],await m({x:Y,y:v}))E(i)}y=requestAnimationFrame(D)}function h(X){let{nodeLookup:m,multiSelectionActive:O,nodesDraggable:p,transform:Y,snapGrid:v,snapToGrid:T,selectNodesOnDrag:S,onNodeDragStart:k,onSelectionDragStart:I,unselectNodesAndEdges:b}=f();if(j=!0,(!S||!z)&&!O&&Z){if(!m.get(Z)?.selected)b()}if(z&&S&&Z)u?.(Z);let o=W$(X.sourceEvent,{transform:Y,snapGrid:v,snapToGrid:T,containerBounds:A});if(i=o,_=aB(m,p,o,Z),_.size>0&&(l||k||!Z&&I)){let[s,x]=HA({nodeId:Z,dragItems:_,nodeLookup:m});if(l?.(X.sourceEvent,_,s,x),k?.(X.sourceEvent,s,x),!Z)I?.(X.sourceEvent,x)}}let B=u$().clickDistance(H).on("start",(X)=>{let{domNode:m,nodeDragThreshold:O,transform:p,snapGrid:Y,snapToGrid:v}=f();if(A=m?.getBoundingClientRect()||null,U=!1,Q=!1,w=X.sourceEvent,O===0)h(X);i=W$(X.sourceEvent,{transform:p,snapGrid:Y,snapToGrid:v,containerBounds:A}),c=zr(X.sourceEvent,A)}).on("drag",(X)=>{let{autoPanOnNodeDrag:m,transform:O,snapGrid:p,snapToGrid:Y,nodeDragThreshold:v,nodeLookup:T}=f(),S=W$(X.sourceEvent,{transform:O,snapGrid:p,snapToGrid:Y,containerBounds:A});if(w=X.sourceEvent,X.sourceEvent.type==="touchmove"&&X.sourceEvent.touches.length>1||Z&&!T.has(Z))U=!0;if(U)return;if(!$&&m&&j)$=!0,D();if(!j){let k=zr(X.sourceEvent,A),I=k.x-c.x,b=k.y-c.y;if(Math.sqrt(I*I+b*b)>v)h(X)}if((i.x!==S.xSnapped||i.y!==S.ySnapped)&&_&&j)c=zr(X.sourceEvent,A),E(S)}).on("end",(X)=>{if(!j||U)return;if($=!1,j=!1,cancelAnimationFrame(y),_.size>0){let{nodeLookup:m,updateNodePositions:O,onNodeDragStop:p,onSelectionDragStop:Y}=f();if(Q)O(_,!1),Q=!1;if(n||p||!Z&&Y){let[v,T]=HA({nodeId:Z,dragItems:_,nodeLookup:m,dragging:!1});if(n?.(X.sourceEvent,_,v,T),p?.(X.sourceEvent,v,T),!Z)Y?.(X.sourceEvent,T)}}}).filter((X)=>{let m=X.target;return!X.button&&(!N||!hq(m,`.${N}`,W))&&(!q||hq(m,q,W))});F.call(B)}function J(){F?.on(".drag",null)}return{update:L,destroy:J}}function dB(u,f,l){let r=[],n={x:u.x-l,y:u.y-l,width:l*2,height:l*2};for(let i of f.values())if(ny(n,p1(i))>0)r.push(i);return r}var eB=250;function uV(u,f,l,r){let n=[],i=1/0,y=dB(u,l,f+eB);for(let _ of y){let $=[..._.internals.handleBounds?.source??[],..._.internals.handleBounds?.target??[]];for(let c of $){if(r.nodeId===c.nodeId&&r.type===c.type&&r.id===c.id)continue;let{x:A,y:j}=Sn(_,c,c.position,!0),F=Math.sqrt(Math.pow(A-u.x,2)+Math.pow(j-u.y,2));if(F>f)continue;if(F1){let _=r.type==="source"?"target":"source";return n.find(($)=>$.type===_)??n[0]}return n[0]}function AN(u,f,l,r,n,i=!1){let y=r.get(u);if(!y)return null;let _=n==="strict"?y.internals.handleBounds?.[f]:[...y.internals.handleBounds?.source??[],...y.internals.handleBounds?.target??[]],$=(l?_?.find((c)=>c.id===l):_?.[0])??null;return $&&i?{...$,...Sn(y,$,$.position,!0)}:$}function jN(u,f){if(u)return u;else if(f?.classList.contains("target"))return"target";else if(f?.classList.contains("source"))return"source";return null}function fV(u,f){let l=null;if(f)l=!0;else if(u&&!f)l=!1;return l}var FN=()=>!0;function lV(u,{connectionMode:f,connectionRadius:l,handleId:r,nodeId:n,edgeUpdaterType:i,isTarget:y,domNode:_,nodeLookup:$,lib:c,autoPanOnConnect:A,flowId:j,panBy:F,cancelConnection:U,onConnectStart:Q,onConnect:w,onConnectEnd:L,isValidConnection:J=FN,onReconnectEnd:N,updateConnection:q,getTransform:W,getFromHandle:z,autoPanSpeed:Z,dragThreshold:H=1,handleDomNode:E}){let D=IA(u.target),h=0,B,{x:X,y:m}=zr(u),O=jN(i,E),p=_?.getBoundingClientRect(),Y=!1;if(!p||!O)return;let v=AN(n,O,r,$,f);if(!v)return;let T=zr(u,p),S=!1,k=null,I=!1,b=null;function o(){if(!A||!p)return;let[qu,P]=oq(T,p,Z);F({x:qu,y:P}),h=requestAnimationFrame(o)}let s={...v,nodeId:n,type:O,position:v.position},x=$.get(n),$u={inProgress:!0,isValid:null,from:Sn(x,s,Lu.Left,!0),fromHandle:s,fromPosition:s.position,fromNode:x,to:T,toHandle:null,toPosition:Xq[s.position],toNode:null,pointer:T};function tu(){Y=!0,q($u),Q?.(u,{nodeId:n,handleId:r,handleType:O})}if(H===0)tu();function ju(qu){if(!Y){let{x:Qu,y:Tu}=zr(qu),Zu=Qu-X,Xu=Tu-m;if(!(Zu*Zu+Xu*Xu>H*H))return;tu()}if(!z()||!s){Gu(qu);return}let P=W();if(T=zr(qu,p),B=uV(yy(T,P,!1,[1,1]),l,$,s),!S)o(),S=!0;let e=JN(qu,{handle:B,connectionMode:f,fromNodeId:n,fromHandleId:r,fromType:y?"target":"source",isValidConnection:J,doc:D,lib:c,flowId:j,nodeLookup:$});b=e.handleDomNode,k=e.connection,I=fV(!!B,e.isValid);let uu=$.get(n),Wu=uu?Sn(uu,s,Lu.Left,!0):$u.from,g={...$u,from:Wu,isValid:I,to:e.toHandle&&I?w$({x:e.toHandle.x,y:e.toHandle.y},P):T,toHandle:e.toHandle,toPosition:I&&e.toHandle?e.toHandle.position:Xq[s.position],toNode:e.toHandle?$.get(e.toHandle.nodeId):null,pointer:T};q(g),$u=g}function Gu(qu){if("touches"in qu&&qu.touches.length>0)return;if(Y){if((B||b)&&k&&I)w?.(k);let{inProgress:P,...e}=$u,uu={...e,toPosition:$u.toHandle?$u.toPosition:null};if(L?.(qu,uu),i)N?.(qu,uu)}U(),cancelAnimationFrame(h),S=!1,I=!1,k=null,b=null,D.removeEventListener("mousemove",ju),D.removeEventListener("mouseup",Gu),D.removeEventListener("touchmove",ju),D.removeEventListener("touchend",Gu)}D.addEventListener("mousemove",ju),D.addEventListener("mouseup",Gu),D.addEventListener("touchmove",ju),D.addEventListener("touchend",Gu)}function JN(u,{handle:f,connectionMode:l,fromNodeId:r,fromHandleId:n,fromType:i,doc:y,lib:_,flowId:$,isValidConnection:c=FN,nodeLookup:A}){let j=i==="target",F=f?y.querySelector(`.${_}-flow__handle[data-id="${$}-${f?.nodeId}-${f?.id}-${f?.type}"]`):null,{x:U,y:Q}=zr(u),w=y.elementFromPoint(U,Q),L=w?.classList.contains(`${_}-flow__handle`)?w:F,J={handleDomNode:L,isValid:!1,connection:null,toHandle:null};if(L){let N=jN(void 0,L),q=L.getAttribute("data-nodeid"),W=L.getAttribute("data-handleid"),z=L.classList.contains("connectable"),Z=L.classList.contains("connectableend");if(!q||!N)return J;let H={source:j?q:r,sourceHandle:j?W:n,target:j?r:q,targetHandle:j?n:W};J.connection=H;let D=z&&Z&&(l===Xn.Strict?j&&N==="source"||!j&&N==="target":q!==r||W!==n);J.isValid=D&&c(H),J.toHandle=AN(q,N,W,A,l,!0)}return J}var o6={onPointerDown:lV,isValid:JN};function UN({domNode:u,panZoom:f,getTransform:l,getViewScale:r}){let n=of(u);function i({translateExtent:_,width:$,height:c,zoomStep:A=1,pannable:j=!0,zoomable:F=!0,inversePan:U=!1}){let Q=(q)=>{if(q.sourceEvent.type!=="wheel"||!f)return;let W=l(),z=q.sourceEvent.ctrlKey&&_y()?10:1,Z=-q.sourceEvent.deltaY*(q.sourceEvent.deltaMode===1?0.05:q.sourceEvent.deltaMode?1:0.002)*A,H=W[2]*Math.pow(2,Z*z);f.scaleTo(H)},w=[0,0],L=(q)=>{if(q.sourceEvent.type==="mousedown"||q.sourceEvent.type==="touchstart")w=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY]},J=(q)=>{let W=l();if(q.sourceEvent.type!=="mousemove"&&q.sourceEvent.type!=="touchmove"||!f)return;let z=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY],Z=[z[0]-w[0],z[1]-w[1]];w=z;let H=r()*Math.max(W[2],Math.log(W[2]))*(U?-1:1),E={x:W[0]-Z[0]*H,y:W[1]-Z[1]*H},D=[[0,0],[$,c]];f.setViewportConstrained({x:E.x,y:E.y,zoom:W[2]},D,_)},N=N$().on("start",L).on("zoom",j?J:null).on("zoom.wheel",F?Q:null);n.call(N,{})}function y(){n.on("zoom",null)}return{update:i,destroy:y,pointer:Wl}}var d6=(u)=>({x:u.x,y:u.y,zoom:u.k}),BA=({x:u,y:f,zoom:l})=>X1.translate(u,f).scale(l),ei=(u,f)=>u.target.closest(`.${f}`),QN=(u,f)=>f===2&&Array.isArray(u)&&u.includes(2),rV=(u)=>((u*=2)<=1?u*u*u:(u-=2)*u*u+2)/2,VA=(u,f=0,l=rV,r=()=>{})=>{let n=typeof f==="number"&&f>0;if(!n)r();return n?u.transition().duration(f).ease(l).on("end",r):u},qN=(u)=>{let f=u.ctrlKey&&_y()?10:1;return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*f};function nV({zoomPanValues:u,noWheelClassName:f,d3Selection:l,d3Zoom:r,panOnScrollMode:n,panOnScrollSpeed:i,zoomOnPinch:y,onPanZoomStart:_,onPanZoom:$,onPanZoomEnd:c}){return(A)=>{if(ei(A,f)){if(A.ctrlKey)A.preventDefault();return!1}A.preventDefault(),A.stopImmediatePropagation();let j=l.property("__zoom").k||1;if(A.ctrlKey&&y){let L=Wl(A),J=qN(A),N=j*Math.pow(2,J);r.scaleTo(l,N,L,A);return}let F=A.deltaMode===1?20:1,U=n===C0.Vertical?0:A.deltaX*F,Q=n===C0.Horizontal?0:A.deltaY*F;if(!_y()&&A.shiftKey&&n!==C0.Vertical)U=A.deltaY*F,Q=0;r.translateBy(l,-(U/j)*i,-(Q/j)*i,{internal:!0});let w=d6(l.property("__zoom"));if(clearTimeout(u.panScrollTimeout),!u.isPanScrolling)u.isPanScrolling=!0,_?.(A,w);else $?.(A,w),u.panScrollTimeout=setTimeout(()=>{c?.(A,w),u.isPanScrolling=!1},150)}}function iV({noWheelClassName:u,preventScrolling:f,d3ZoomHandler:l}){return function(r,n){let i=r.type==="wheel",y=!f&&i&&!r.ctrlKey,_=ei(r,u);if(r.ctrlKey&&i&&_)r.preventDefault();if(y||_)return null;r.preventDefault(),l.call(this,r,n)}}function yV({zoomPanValues:u,onDraggingChange:f,onPanZoomStart:l}){return(r)=>{if(r.sourceEvent?.internal)return;let n=d6(r.transform);if(u.mouseButton=r.sourceEvent?.button||0,u.isZoomingOrPanning=!0,u.prevViewport=n,r.sourceEvent?.type==="mousedown")f(!0);if(l)l?.(r.sourceEvent,n)}}function _V({zoomPanValues:u,panOnDrag:f,onPaneContextMenu:l,onTransformChange:r,onPanZoom:n}){return(i)=>{if(u.usedRightMouseButton=!!(l&&QN(f,u.mouseButton??0)),!i.sourceEvent?.sync)r([i.transform.x,i.transform.y,i.transform.k]);if(n&&!i.sourceEvent?.internal)n?.(i.sourceEvent,d6(i.transform))}}function $V({zoomPanValues:u,panOnDrag:f,panOnScroll:l,onDraggingChange:r,onPanZoomEnd:n,onPaneContextMenu:i}){return(y)=>{if(y.sourceEvent?.internal)return;if(u.isZoomingOrPanning=!1,i&&QN(f,u.mouseButton??0)&&!u.usedRightMouseButton&&y.sourceEvent)i(y.sourceEvent);if(u.usedRightMouseButton=!1,r(!1),n){let _=d6(y.transform);u.prevViewport=_,clearTimeout(u.timerId),u.timerId=setTimeout(()=>{n?.(y.sourceEvent,_)},l?150:0)}}}function tV({zoomActivationKeyPressed:u,zoomOnScroll:f,zoomOnPinch:l,panOnDrag:r,panOnScroll:n,zoomOnDoubleClick:i,userSelectionActive:y,noWheelClassName:_,noPanClassName:$,lib:c,connectionInProgress:A}){return(j)=>{let F=u||f,U=l&&j.ctrlKey,Q=j.type==="wheel";if(j.button===1&&j.type==="mousedown"&&(ei(j,`${c}-flow__node`)||ei(j,`${c}-flow__edge`)))return!0;if(!r&&!F&&!n&&!i&&!l)return!1;if(y)return!1;if(A&&!Q)return!1;if(ei(j,_)&&Q)return!1;if(ei(j,$)&&(!Q||n&&Q&&!u))return!1;if(!l&&j.ctrlKey&&Q)return!1;if(!l&&j.type==="touchstart"&&j.touches?.length>1)return j.preventDefault(),!1;if(!F&&!n&&!U&&Q)return!1;if(!r&&(j.type==="mousedown"||j.type==="touchstart"))return!1;if(Array.isArray(r)&&!r.includes(j.button)&&j.type==="mousedown")return!1;let w=Array.isArray(r)&&r.includes(j.button)||!j.button||j.button<=1;return(!j.ctrlKey||Q)&&w}}function NN({domNode:u,minZoom:f,maxZoom:l,translateExtent:r,viewport:n,onPanZoom:i,onPanZoomStart:y,onPanZoomEnd:_,onDraggingChange:$}){let c={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},A=u.getBoundingClientRect(),j=N$().scaleExtent([f,l]).translateExtent(r),F=of(u).call(j);N({x:n.x,y:n.y,zoom:uy(n.zoom,f,l)},[[0,0],[A.width,A.height]],r);let U=F.on("wheel.zoom"),Q=F.on("dblclick.zoom");j.wheelDelta(qN);function w(B,X){if(F)return new Promise((m)=>{j?.interpolate(X?.interpolate==="linear"?y0:V1).transform(VA(F,X?.duration,X?.ease,()=>m(!0)),B)});return Promise.resolve(!1)}function L({noWheelClassName:B,noPanClassName:X,onPaneContextMenu:m,userSelectionActive:O,panOnScroll:p,panOnDrag:Y,panOnScrollMode:v,panOnScrollSpeed:T,preventScrolling:S,zoomOnPinch:k,zoomOnScroll:I,zoomOnDoubleClick:b,zoomActivationKeyPressed:o,lib:s,onTransformChange:x,connectionInProgress:fu,paneClickDistance:$u,selectionOnDrag:tu}){if(O&&!c.isZoomingOrPanning)J();let ju=p&&!o&&!O;j.clickDistance(tu?1/0:!Gr($u)||$u<0?0:$u);let Gu=ju?nV({zoomPanValues:c,noWheelClassName:B,d3Selection:F,d3Zoom:j,panOnScrollMode:v,panOnScrollSpeed:T,zoomOnPinch:k,onPanZoomStart:y,onPanZoom:i,onPanZoomEnd:_}):iV({noWheelClassName:B,preventScrolling:S,d3ZoomHandler:U});if(F.on("wheel.zoom",Gu,{passive:!1}),!O){let P=yV({zoomPanValues:c,onDraggingChange:$,onPanZoomStart:y});j.on("start",P);let e=_V({zoomPanValues:c,panOnDrag:Y,onPaneContextMenu:!!m,onPanZoom:i,onTransformChange:x});j.on("zoom",e);let uu=$V({zoomPanValues:c,panOnDrag:Y,panOnScroll:p,onPaneContextMenu:m,onPanZoomEnd:_,onDraggingChange:$});j.on("end",uu)}let qu=tV({zoomActivationKeyPressed:o,panOnDrag:Y,zoomOnScroll:I,panOnScroll:p,zoomOnDoubleClick:b,zoomOnPinch:k,userSelectionActive:O,noPanClassName:X,noWheelClassName:B,lib:s,connectionInProgress:fu});if(j.filter(qu),b)F.on("dblclick.zoom",Q);else F.on("dblclick.zoom",null)}function J(){j.on("zoom",null)}async function N(B,X,m){let O=BA(B),p=j?.constrain()(O,X,m);if(p)await w(p);return new Promise((Y)=>Y(p))}async function q(B,X){let m=BA(B);return await w(m,X),new Promise((O)=>O(m))}function W(B){if(F){let X=BA(B),m=F.property("__zoom");if(m.k!==B.zoom||m.x!==B.x||m.y!==B.y)j?.transform(F,X,null,{sync:!0})}}function z(){let B=F?q$(F.node()):{x:0,y:0,k:1};return{x:B.x,y:B.y,zoom:B.k}}function Z(B,X){if(F)return new Promise((m)=>{j?.interpolate(X?.interpolate==="linear"?y0:V1).scaleTo(VA(F,X?.duration,X?.ease,()=>m(!0)),B)});return Promise.resolve(!1)}function H(B,X){if(F)return new Promise((m)=>{j?.interpolate(X?.interpolate==="linear"?y0:V1).scaleBy(VA(F,X?.duration,X?.ease,()=>m(!0)),B)});return Promise.resolve(!1)}function E(B){j?.scaleExtent(B)}function D(B){j?.translateExtent(B)}function h(B){let X=!Gr(B)||B<0?0:B;j?.clickDistance(X)}return{update:L,destroy:J,setViewport:q,setViewportConstrained:N,getViewport:z,scaleTo:Z,scaleBy:H,setScaleExtent:E,setTranslateExtent:D,syncViewport:W,setClickDistance:h}}var mn;(function(u){u.Line="line",u.Handle="handle"})(mn||(mn={}));function cV({width:u,prevWidth:f,height:l,prevHeight:r,affectsX:n,affectsY:i}){let y=u-f,_=l-r,$=[y>0?1:y<0?-1:0,_>0?1:_<0?-1:0];if(y&&n)$[0]=$[0]*-1;if(_&&i)$[1]=$[1]*-1;return $}function bq(u){let f=u.includes("right")||u.includes("left"),l=u.includes("bottom")||u.includes("top"),r=u.includes("left"),n=u.includes("top");return{isHorizontal:f,isVertical:l,affectsX:r,affectsY:n}}function Vn(u,f){return Math.max(0,f-u)}function Dn(u,f){return Math.max(0,u-f)}function M6(u,f,l){return Math.max(0,f-u,u-l)}function vq(u,f){return u?!f:f}function AV(u,f,l,r,n,i,y,_){let{affectsX:$,affectsY:c}=f,{isHorizontal:A,isVertical:j}=f,F=A&&j,{xSnapped:U,ySnapped:Q}=l,{minWidth:w,maxWidth:L,minHeight:J,maxHeight:N}=r,{x:q,y:W,width:z,height:Z,aspectRatio:H}=u,E=Math.floor(A?U-u.pointerX:0),D=Math.floor(j?Q-u.pointerY:0),h=z+($?-E:E),B=Z+(c?-D:D),X=-i[0]*z,m=-i[1]*Z,O=M6(h,w,L),p=M6(B,J,N);if(y){let T=0,S=0;if($&&E<0)T=Vn(q+E+X,y[0][0]);else if(!$&&E>0)T=Dn(q+h+X,y[1][0]);if(c&&D<0)S=Vn(W+D+m,y[0][1]);else if(!c&&D>0)S=Dn(W+B+m,y[1][1]);O=Math.max(O,T),p=Math.max(p,S)}if(_){let T=0,S=0;if($&&E>0)T=Dn(q+E,_[0][0]);else if(!$&&E<0)T=Vn(q+h,_[1][0]);if(c&&D>0)S=Dn(W+D,_[0][1]);else if(!c&&D<0)S=Vn(W+B,_[1][1]);O=Math.max(O,T),p=Math.max(p,S)}if(n){if(A){let T=M6(h/H,J,N)*H;if(O=Math.max(O,T),y){let S=0;if(!$&&!c||$&&!c&&F)S=Dn(W+m+h/H,y[1][1])*H;else S=Vn(W+m+($?E:-E)/H,y[0][1])*H;O=Math.max(O,S)}if(_){let S=0;if(!$&&!c||$&&!c&&F)S=Vn(W+h/H,_[1][1])*H;else S=Dn(W+($?E:-E)/H,_[0][1])*H;O=Math.max(O,S)}}if(j){let T=M6(B*H,w,L)/H;if(p=Math.max(p,T),y){let S=0;if(!$&&!c||c&&!$&&F)S=Dn(q+B*H+X,y[1][0])/H;else S=Vn(q+(c?D:-D)*H+X,y[0][0])/H;p=Math.max(p,S)}if(_){let S=0;if(!$&&!c||c&&!$&&F)S=Vn(q+B*H,_[1][0])/H;else S=Dn(q+(c?D:-D)*H,_[0][0])/H;p=Math.max(p,S)}}}if(D=D+(D<0?p:-p),E=E+(E<0?O:-O),n)if(F)if(h>B*H)D=(vq($,c)?-E:E)/H;else E=(vq($,c)?-D:D)*H;else if(A)D=E/H,c=$;else E=D*H,$=c;let Y=$?q+E:q,v=c?W+D:W;return{width:z+($?-E:E),height:Z+(c?-D:D),x:i[0]*E*(!$?1:-1)+Y,y:i[1]*D*(!c?1:-1)+v}}var WN={width:0,height:0,x:0,y:0},jV={...WN,pointerX:0,pointerY:0,aspectRatio:1};function FV(u){return[[0,0],[u.measured.width,u.measured.height]]}function JV(u,f,l){let r=f.position.x+u.position.x,n=f.position.y+u.position.y,i=u.measured.width??0,y=u.measured.height??0,_=l[0]*i,$=l[1]*y;return[[r-_,n-$],[r+i-_,n+y-$]]}function wN({domNode:u,nodeId:f,getStoreItems:l,onChange:r,onEnd:n}){let i=of(u),y={controlDirection:bq("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function _({controlPosition:c,boundaries:A,keepAspectRatio:j,resizeDirection:F,onResizeStart:U,onResize:Q,onResizeEnd:w,shouldResize:L}){let J={...WN},N={...jV};y={boundaries:A,resizeDirection:F,keepAspectRatio:j,controlDirection:bq(c)};let q=void 0,W=null,z=[],Z=void 0,H=void 0,E=void 0,D=!1,h=u$().on("start",(B)=>{let{nodeLookup:X,transform:m,snapGrid:O,snapToGrid:p,nodeOrigin:Y,paneDomNode:v}=l();if(q=X.get(f),!q)return;W=v?.getBoundingClientRect()??null;let{xSnapped:T,ySnapped:S}=W$(B.sourceEvent,{transform:m,snapGrid:O,snapToGrid:p,containerBounds:W});if(J={width:q.measured.width??0,height:q.measured.height??0,x:q.position.x??0,y:q.position.y??0},N={...J,pointerX:T,pointerY:S,aspectRatio:J.width/J.height},Z=void 0,q.parentId&&(q.extent==="parent"||q.expandParent))Z=X.get(q.parentId),H=Z&&q.extent==="parent"?FV(Z):void 0;z=[],E=void 0;for(let[k,I]of X)if(I.parentId===f){if(z.push({id:k,position:{...I.position},extent:I.extent}),I.extent==="parent"||I.expandParent){let b=JV(I,q,I.origin??Y);if(E)E=[[Math.min(b[0][0],E[0][0]),Math.min(b[0][1],E[0][1])],[Math.max(b[1][0],E[1][0]),Math.max(b[1][1],E[1][1])]];else E=b}}U?.(B,{...J})}).on("drag",(B)=>{let{transform:X,snapGrid:m,snapToGrid:O,nodeOrigin:p}=l(),Y=W$(B.sourceEvent,{transform:X,snapGrid:m,snapToGrid:O,containerBounds:W}),v=[];if(!q)return;let{x:T,y:S,width:k,height:I}=J,b={},o=q.origin??p,{width:s,height:x,x:fu,y:$u}=AV(N,y.controlDirection,Y,y.boundaries,y.keepAspectRatio,o,H,E),tu=s!==k,ju=x!==I,Gu=fu!==T&&tu,qu=$u!==S&&ju;if(!Gu&&!qu&&!tu&&!ju)return;if(Gu||qu||o[0]===1||o[1]===1){if(b.x=Gu?fu:J.x,b.y=qu?$u:J.y,J.x=b.x,J.y=b.y,z.length>0){let Wu=fu-T,g=$u-S;for(let Qu of z)Qu.position={x:Qu.position.x-Wu+o[0]*(s-k),y:Qu.position.y-g+o[1]*(x-I)},v.push(Qu)}}if(tu||ju)b.width=tu&&(!y.resizeDirection||y.resizeDirection==="horizontal")?s:J.width,b.height=ju&&(!y.resizeDirection||y.resizeDirection==="vertical")?x:J.height,J.width=b.width,J.height=b.height;if(Z&&q.expandParent){let Wu=o[0]*(b.width??0);if(b.x&&b.x{if(!D)return;w?.(B,{...J}),n?.({...J}),D=!1});i.call(h)}function $(){i.on(".drag",null)}return{update:_,destroy:$}}var DN=Mu(Qf(),1),XN=Mu(ON(),1);var HN=(u)=>{let f,l=new Set,r=(A,j)=>{let F=typeof A==="function"?A(f):A;if(!Object.is(F,f)){let U=f;f=(j!=null?j:typeof F!=="object"||F===null)?F:Object.assign({},f,F),l.forEach((Q)=>Q(f,U))}},n=()=>f,$={setState:r,getState:n,getInitialState:()=>c,subscribe:(A)=>{return l.add(A),()=>l.delete(A)},destroy:()=>{l.clear()}},c=f=u(r,n,$);return $},BN=(u)=>u?HN(u):HN;var{useDebugValue:DV}=DN.default,{useSyncExternalStoreWithSelector:XV}=XN.default,YV=(u)=>u;function n9(u,f=YV,l){let r=XV(u.subscribe,u.getState,u.getServerState||u.getInitialState,f,l);return DV(r),r}var VN=(u,f)=>{let l=BN(u),r=(n,i=f)=>n9(l,n,i);return Object.assign(r,l),r},YN=(u,f)=>u?VN(u,f):VN;function Kf(u,f){if(Object.is(u,f))return!0;if(typeof u!=="object"||u===null||typeof f!=="object"||f===null)return!1;if(u instanceof Map&&f instanceof Map){if(u.size!==f.size)return!1;for(let[r,n]of u)if(!Object.is(n,f.get(r)))return!1;return!0}if(u instanceof Set&&f instanceof Set){if(u.size!==f.size)return!1;for(let r of u)if(!f.has(r))return!1;return!0}let l=Object.keys(u);if(l.length!==Object.keys(f).length)return!1;for(let r of l)if(!Object.prototype.hasOwnProperty.call(f,r)||!Object.is(u[r],f[r]))return!1;return!0}var SV=Mu(jc(),1),r8=yu.createContext(null),mV=r8.Provider,nW=tr.error001();function uf(u,f){let l=yu.useContext(r8);if(l===null)throw Error(nW);return n9(l,u,f)}function Tf(){let u=yu.useContext(r8);if(u===null)throw Error(nW);return yu.useMemo(()=>({getState:u.getState,setState:u.setState,subscribe:u.subscribe}),[u])}var SN={display:"none"},pV={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},iW="react-flow__node-desc",yW="react-flow__edge-desc",PV="react-flow__aria-live",MV=(u)=>u.ariaLiveMessage,CV=(u)=>u.ariaLabelConfig;function RV({rfId:u}){let f=uf(MV);return ru.jsx("div",{id:`${PV}-${u}`,"aria-live":"assertive","aria-atomic":"true",style:pV,children:f})}function xV({rfId:u,disableKeyboardA11y:f}){let l=uf(CV);return ru.jsxs(ru.Fragment,{children:[ru.jsx("div",{id:`${iW}-${u}`,style:SN,children:f?l["node.a11yDescription.default"]:l["node.a11yDescription.keyboardDisabled"]}),ru.jsx("div",{id:`${yW}-${u}`,style:SN,children:l["edge.a11yDescription.default"]}),!f&&ru.jsx(RV,{rfId:u})]})}var n8=yu.forwardRef(({position:u="top-left",children:f,className:l,style:r,...n},i)=>{let y=`${u}`.split("-");return ru.jsx("div",{className:Xf(["react-flow__panel",l,...y]),style:r,ref:i,...n,children:f})});n8.displayName="Panel";function hV({proOptions:u,position:f="bottom-right"}){if(u?.hideAttribution)return null;return ru.jsx(n8,{position:f,className:"react-flow__attribution","data-message":"Please only hide this attribution when you are subscribed to React Flow Pro: https://pro.reactflow.dev",children:ru.jsx("a",{href:"https://reactflow.dev",target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}var bV=(u)=>{let f=[],l=[];for(let[,r]of u.nodeLookup)if(r.selected)f.push(r.internals.userNode);for(let[,r]of u.edgeLookup)if(r.selected)l.push(r);return{selectedNodes:f,selectedEdges:l}},u8=(u)=>u.id;function vV(u,f){return Kf(u.selectedNodes.map(u8),f.selectedNodes.map(u8))&&Kf(u.selectedEdges.map(u8),f.selectedEdges.map(u8))}function kV({onSelectionChange:u}){let f=Tf(),{selectedNodes:l,selectedEdges:r}=uf(bV,vV);return yu.useEffect(()=>{let n={nodes:l,edges:r};u?.(n),f.getState().onSelectionChangeHandlers.forEach((i)=>i(n))},[l,r,u]),null}var IV=(u)=>!!u.onSelectionChangeHandlers;function gV({onSelectionChange:u}){let f=uf(IV);if(u||f)return ru.jsx(kV,{onSelectionChange:u});return null}var _9=typeof window<"u"?yu.useLayoutEffect:yu.useEffect,_W=[0,0],sV={x:0,y:0,zoom:1},aV=["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"],mN=[...aV,"rfId"],oV=(u)=>({setNodes:u.setNodes,setEdges:u.setEdges,setMinZoom:u.setMinZoom,setMaxZoom:u.setMaxZoom,setTranslateExtent:u.setTranslateExtent,setNodeExtent:u.setNodeExtent,reset:u.reset,setDefaultNodesAndEdges:u.setDefaultNodesAndEdges}),pN={translateExtent:ly,nodeOrigin:_W,minZoom:0.5,maxZoom:2,elementsSelectable:!0,noPanClassName:"nopan",rfId:"1"};function dV(u){let{setNodes:f,setEdges:l,setMinZoom:r,setMaxZoom:n,setTranslateExtent:i,setNodeExtent:y,reset:_,setDefaultNodesAndEdges:$}=uf(oV,Kf),c=Tf();_9(()=>{return $(u.defaultNodes,u.defaultEdges),()=>{A.current=pN,_()}},[]);let A=yu.useRef(pN);return _9(()=>{for(let j of mN){let F=u[j],U=A.current[j];if(F===U)continue;if(typeof u[j]>"u")continue;if(j==="nodes")f(F);else if(j==="edges")l(F);else if(j==="minZoom")r(F);else if(j==="maxZoom")n(F);else if(j==="translateExtent")i(F);else if(j==="nodeExtent")y(F);else if(j==="ariaLabelConfig")c.setState({ariaLabelConfig:eq(F)});else if(j==="fitView")c.setState({fitViewQueued:F});else if(j==="fitViewOptions")c.setState({fitViewOptions:F});else c.setState({[j]:F})}A.current=u},mN.map((j)=>u[j])),null}function PN(){if(typeof window>"u"||!window.matchMedia)return null;return window.matchMedia("(prefers-color-scheme: dark)")}function eV(u){let[f,l]=yu.useState(u==="system"?null:u);return yu.useEffect(()=>{if(u!=="system"){l(u);return}let r=PN(),n=()=>l(r?.matches?"dark":"light");return n(),r?.addEventListener("change",n),()=>{r?.removeEventListener("change",n)}},[u]),f!==null?f:PN()?.matches?"dark":"light"}var MN=typeof document<"u"?document:null;function z$(u=null,f={target:MN,actInsideInputWithModifier:!0}){let[l,r]=yu.useState(!1),n=yu.useRef(!1),i=yu.useRef(new Set([])),[y,_]=yu.useMemo(()=>{if(u!==null){let c=(Array.isArray(u)?u:[u]).filter((j)=>typeof j==="string").map((j)=>j.replace("+",` +`;function a5({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Bu("section",{className:`panel ${n||""}`},Bu("div",{className:"panel-head"},Bu("div",null,f?Bu("p",{className:"panel-eyebrow"},f):null,Bu(nf,{title:u,loading:i})),l?Bu("div",{className:"panel-actions"},l):null),Bu("div",{className:"panel-body"},r))}function UZ({title:u,data:f,onOpen:l,testId:r}){return Bu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function QZ({title:u,text:f}){return Bu("div",{className:"empty-state"},Bu("strong",null,u),Bu("span",null,f))}function OQ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function HQ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function BQ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function qZ(u){return u.filter((l)=>l?.id==="filebrowser"||String(l?.id||"").startsWith("filebrowser-")).sort((l,r)=>{let n=(i)=>i.providerId==="D518"?0:i.providerId==="D601"?1:i.id==="filebrowser"?2:3;return n(l)-n(r)||String(l.id).localeCompare(String(r.id))})}function NZ(u){if(u?.providerId==="D518")return"D518";return u?.providerId||u?.name||u?.id||"Unknown"}function WZ(u,f,l="/"){let r=l.startsWith("/")?l:`/${l}`;return`${u}/microservices/${encodeURIComponent(f)}/proxy${r}`}function LZ(u,f){return`${u}/microservices/${encodeURIComponent(f)}/health`}async function wZ(u,f=16000){let l=new AbortController,r=setTimeout(()=>l.abort(),f);try{return await Eu(u,{signal:l.signal,failureFields:[!1]})}finally{clearTimeout(r)}}function VQ(u){if(u?.providerId==="main-server")return"host / -> /srv";if(u?.providerId==="D601"||u?.providerId==="D518")return"WSL / + /mnt/c -> /srv";return"provider / -> /srv"}function vt(u){return u?.status==="OK"||u?.ok===!0}function KZ({service:u,active:f,health:l,onSelect:r,onRaw:n}){let i=OQ(u),y=HQ(u),_=BQ(u),$=i.container||{},A=vt(l?.body);return Bu("button",{type:"button",className:`filebrowser-target-card ${f?"active":""}`,"data-testid":`filebrowser-target-card-${u.id}`,onClick:r},Bu("span",{className:`status-badge ${A?"ok":i.providerStatus==="online"?"running":"warn"}`},A?"Health OK":i.providerStatus||"unknown"),Bu("strong",null,u.name||u.id),Bu("span",null,VQ(u)),Bu("code",null,`${y.nodeBindHost||"--"}:${y.nodePort||"--"}`),Bu("small",null,$.name?`${$.name} / ${$.state||"--"}`:`${_.composeService||"--"}`),Bu("span",{className:"filebrowser-card-raw",onClick:(c)=>{c.stopPropagation(),n(`${u.name} service`,u)}},"JSON"))}function DQ(u){try{return u?.contentDocument||u?.contentWindow?.document||null}catch{return null}}function d5(u){let f=DQ(u);if(f===null||f.head===null)return!1;let l=f.getElementById("unidesk-filebrowser-compact-style");if(l===null)l=f.createElement("style"),l.id="unidesk-filebrowser-compact-style",f.head.appendChild(l);if(l.textContent!==o5)l.textContent=o5;return!0}function GZ(u,f){let l=URL.createObjectURL(u),r=document.createElement("a");r.href=l,r.download=f,document.body.appendChild(r),r.click(),r.remove(),setTimeout(()=>URL.revokeObjectURL(l),2000)}function zZ(u,f){let l=DQ(u);if(l===null||l.documentElement===null)throw Error("无法访问 File Browser iframe 文档");d5(u);let r=Math.max(640,Math.ceil(u.clientWidth||l.documentElement.clientWidth||1280)),n=Math.max(480,Math.ceil(u.clientHeight||l.documentElement.clientHeight||720)),i=l.documentElement.cloneNode(!0);i.querySelectorAll("script, style, link[rel='stylesheet'], link[rel='preload'], link[rel='icon']").forEach((c)=>c.remove()),i.querySelectorAll("img").forEach((c)=>{c.removeAttribute("src"),c.removeAttribute("srcset")});let y=i.querySelector("head");if(y===null)y=l.createElement("head"),i.insertBefore(y,i.firstChild);let _=l.createElement("style");_.textContent=`${o5} +html,body{width:${r}px!important;min-height:${n}px!important;overflow:hidden!important;}`,y.appendChild(_);let $=new XMLSerializer().serializeToString(i),A=`${$}`;GZ(new Blob([A],{type:"image/svg+xml;charset=utf-8"}),f.replace(/\.png$/i,".svg"))}function XQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=qZ(Array.isArray(u)?u:[]),n=new URLSearchParams(window.location.search).get("target")||"",i=n==="filebrowser-d518"?"filebrowser":n,y=r.some((Z)=>Z.id===i)?i:r[0]?.id||"",[_,$]=s5(y),[A,c]=s5({loading:!1,refreshedAt:null,health:{},error:""}),[j,F]=s5({exporting:!1,message:"",error:""}),U=JZ(null),Q=r.find((Z)=>Z.id===_)||r[0]||null,L=OQ(Q),w=HQ(Q),J=BQ(Q),N=Q?A.health[Q.id]:null,q=Q?WZ(l,Q.id,"/"):"about:blank";g5(()=>{if(r.length===0)return;if(!_||!r.some((Z)=>Z.id===_))$(r[0].id)},[r.map((Z)=>Z.id).join(",")]),g5(()=>{let Z=0,H=setInterval(()=>{if(Z+=1,d5(U.current)||Z>=24)clearInterval(H)},500);return()=>clearInterval(H)},[q]),g5(()=>{if(r.length===0)return;let Z=!1;async function H(){c((h)=>({...h,loading:!0,error:""}));let D=await Promise.all(r.map(async(h)=>{try{let V=await wZ(LZ(l,h.id));return[h.id,{ok:!0,body:V}]}catch(V){return[h.id,{ok:!1,error:Hu(V,"File Browser health failed")}]}}));if(Z)return;c({loading:!1,refreshedAt:new Date().toISOString(),health:Object.fromEntries(D),error:""})}H();let E=setInterval(H,30000);return()=>{Z=!0,clearInterval(E)}},[r.map((Z)=>`${Z.id}:${Z.runtime?.providerStatus||""}`).join(","),l]);function W(Z){$(Z);let H=new URL(window.location.href);H.searchParams.set("target",Z),window.history.replaceState({},"",`${H.pathname}${H.search}`)}async function z(){if(j.exporting)return;F({exporting:!0,message:"",error:""});try{let Z=new Date().toISOString().replace(/[-:.TZ]/g,"").slice(0,14);await zZ(U.current,`unidesk-filebrowser-${Q?.id||"target"}-${Z}.png`),F({exporting:!1,message:"截图已导出",error:""})}catch(Z){F({exporting:!1,message:"",error:Hu(Z,"截图导出失败")})}}if(r.length===0)return Bu(QZ,{title:"File Browser 未登记",text:"请在 config.json 的 microservices 中登记 id=filebrowser 或 filebrowser-* 用户服务"});return Bu("div",{className:"filebrowser-page","data-testid":"filebrowser-page"},A.error?Bu(yf,{error:A.error,wide:!0}):null,Bu(a5,{title:"文件管理器",eyebrow:"File Browser / Host Files",loading:A.loading,actions:Bu("div",{className:"panel-actions"},Q?Bu("button",{type:"button",className:"ghost-btn",onClick:z,disabled:j.exporting,"data-testid":"filebrowser-export-screenshot"},j.exporting?"导出中...":"导出截图"):null,Q?Bu("a",{className:"ghost-btn",href:q,target:"_blank",rel:"noreferrer"},"新窗口打开"):null,Q?Bu(UZ,{title:"File Browser 当前目标",data:{service:Q,health:N},onOpen:f,testId:"raw-filebrowser-active"}):null)},Bu("div",{className:"filebrowser-hero"},Bu("div",null,Bu("span",{className:`status-badge ${vt(N?.body)?"ok":"warn"}`},vt(N?.body)?"Health OK":"Health Pending"),Bu("h3",null,Q?.name||"File Browser"),Bu("p",{className:"muted paragraph"},Q?.description||"通过 UniDesk 登录态代理访问,不开放 File Browser 公网端口。"),j.error?Bu("p",{className:"filebrowser-shot-error"},j.error):null,j.message?Bu("p",{className:"filebrowser-shot-ok"},j.message):null),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Provider"),Bu("strong",null,Q?.providerId||"--"),Bu("code",null,L.providerName||Q?.providerId||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Private Backend"),Bu("strong",null,`${w.nodeBindHost||"--"}:${w.nodePort||"--"}`),Bu("code",null,w.nodeBaseUrl||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Image"),Bu("strong",null,J.dockerfile||"filebrowser/filebrowser:v2.63.3"),Bu("code",null,J.commitId||"--")),Bu("div",{className:"microservice-ref-card"},Bu("span",null,"Mount"),Bu("strong",null,VQ(Q)),Bu("code",null,Q?.providerId==="main-server"?"/root, /var, /home":"/home, /mnt/c, /mnt/d")))),Bu(a5,{title:"浏览目标",eyebrow:`${r.length} host targets`,loading:A.loading},Bu("div",{className:"filebrowser-target-grid"},r.map((Z)=>Bu(KZ,{key:Z.id,service:Z,active:Z.id===Q?.id,health:A.health[Z.id],onSelect:()=>W(Z.id),onRaw:f})))),Bu(a5,{title:`${NZ(Q)} 文件视图`,eyebrow:N?.body?`Health ${vt(N.body)?"OK":"UNKNOWN"} / ${A.refreshedAt?tf(A.refreshedAt):"--"}`:"Embedded WebUI",className:"filebrowser-frame-panel"},Bu("div",{className:"filebrowser-frame-shell"},Bu("div",{className:"filebrowser-frame-toolbar"},Bu("span",null,"BaseURL"),Bu("code",null,`/api/microservices/${Q?.id||"filebrowser"}/proxy`),Bu("span",null,"Root"),Bu("code",null,"/srv"),Bu("span",{className:"filebrowser-compact-note"},"Compact layout injected")),Bu("iframe",{ref:U,key:q,title:`${Q?.name||"File Browser"} WebUI`,src:q,className:"filebrowser-frame","data-testid":"filebrowser-frame",onLoad:(Z)=>d5(Z.currentTarget),sandbox:"allow-downloads allow-forms allow-modals allow-same-origin allow-scripts"}))))}var st=Pu(qf(),1);var Ju=st.default.createElement,{useEffect:TZ}=st.default,EZ=st.default.useState;function kt({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return Ju("span",{className:`status-badge ${l}`},f||u||"unknown")}function zn({label:u,value:f,hint:l,tone:r}){return Ju("article",{className:`metric-card ${r||""}`},Ju("div",{className:"metric-label"},u),Ju("div",{className:"metric-value"},f),Ju("div",{className:"metric-hint"},l))}function It({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Ju("section",{className:`panel ${n||""}`},Ju("div",{className:"panel-head"},Ju("div",null,f?Ju("p",{className:"panel-eyebrow"},f):null,Ju(nf,{title:u,loading:i})),l?Ju("div",{className:"panel-actions"},l):null),Ju("div",{className:"panel-body"},r))}function gt({title:u,data:f,onOpen:l,testId:r}){return Ju("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function e5({title:u,text:f}){return Ju("div",{className:"empty-state"},Ju("strong",null,u),Ju("span",null,f))}function ZZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function OZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function HZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function K1(u,f){let l=u&&typeof u==="object"?u[f]:void 0;return Number.isFinite(Number(l))?String(l):"--"}function BZ(u){return(Array.isArray(u?.jobs)?u.jobs:[]).slice(0,40)}function VZ(u){return(Array.isArray(u?.drafts)?u.drafts:[]).slice(0,12)}function YQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((Q)=>Q.id==="findjob")||null,[n,i]=EZ({loading:!1,error:"",health:null,summary:null,jobs:null,drafts:null,refreshedAt:null});async function y(){if(!r)return;i((Q)=>({...Q,loading:!0,error:""}));try{let[Q,L,w,J]=await Promise.all([Eu(`${l}/microservices/findjob/health`),Eu(`${l}/microservices/findjob/proxy/api/summary`),Eu(`${l}/microservices/findjob/proxy/api/jobs?__unideskArrayLimit=jobs:40`),Eu(`${l}/microservices/findjob/proxy/api/drafts`)]);i({loading:!1,error:"",health:Q,summary:L,jobs:w,drafts:J,refreshedAt:new Date})}catch(Q){i((L)=>({...L,loading:!1,error:Hu(Q,"FindJob 加载失败")}))}}if(TZ(()=>{y()},[r?.id,r?.runtime?.providerStatus]),!r)return Ju(e5,{title:"FindJob 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=findjob"});let _=ZZ(r),$=HZ(r),A=OZ(r),c=n.summary||{},j=BZ(n.jobs),F=VZ(n.drafts),U=n.jobs?._unidesk?.arrayLimits?.jobs;return Ju("div",{className:"findjob-page","data-testid":"findjob-page"},Ju(It,{title:"FindJob 工作台",eyebrow:"D601 用户服务",loading:n.loading,actions:Ju("div",{className:"panel-actions"},Ju("button",{type:"button",className:"ghost-btn",onClick:y,disabled:n.loading,"data-testid":"findjob-refresh-button"},n.loading?"刷新中":"刷新"),Ju(gt,{title:"FindJob 用户服务",data:r,onOpen:f,testId:"raw-findjob-service"}))},Ju("div",{className:"findjob-hero"},Ju("div",null,Ju("div",{className:"node-version-line"},Ju(kt,{status:_.providerStatus==="online"?"online":"warn"},_.providerStatus||"unknown"),Ju("span",null,r.providerId),Ju("span",null,A.public?"公网暴露":"仅 UniDesk frontend 代理访问")),Ju("p",{className:"muted paragraph"},r.description)),Ju("div",{className:"microservice-ref-card"},Ju("span",null,"Repo"),Ju("strong",null,$.url||"--"),Ju("code",null,$.commitId||"--")),Ju("div",{className:"microservice-ref-card"},Ju("span",null,"D601 Docker"),Ju("strong",null,`${A.nodeBindHost||"--"}:${A.nodePort||"--"}`),Ju("code",null,`${$.composeFile||"--"} / ${$.composeService||"--"}`))),Ju(yf,{error:n.error,wide:!0})),Ju("div",{className:"findjob-grid"},Ju(It,{title:"岗位指标",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Summary",loading:n.loading},Ju("div",{className:"metric-grid"},Ju(zn,{label:"岗位总量",value:K1(c,"totalJobs"),hint:"tracked jobs",tone:"ok"}),Ju(zn,{label:"原始岗位",value:K1(c,"rawJobs"),hint:"raw queue"}),Ju(zn,{label:"已验证",value:K1(c,"verifiedJobs"),hint:"verified set"}),Ju(zn,{label:"优先处理",value:K1(c,"prioritizedJobs"),hint:"prioritized"}),Ju(zn,{label:"过期",value:K1(c,"staleJobs"),hint:"stale jobs",tone:"warn"}),Ju(zn,{label:"无效",value:K1(c,"invalidJobs"),hint:"invalid jobs",tone:"warn"}),Ju(zn,{label:"上海",value:K1(c,"shanghaiJobs"),hint:"city filter"}),Ju(zn,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /api/health"})),Ju("div",{className:"panel-actions inline-actions"},Ju(gt,{title:"FindJob Summary",data:c,onOpen:f,testId:"raw-findjob-summary"}))),Ju(It,{title:"近期岗位",eyebrow:U?`${U.returnedLength}/${U.originalLength} Preview`:`${j.length} Preview`,loading:n.loading},j.length===0?Ju(e5,{title:"暂无岗位预览",text:"等待 D601 findjob backend 返回 /api/jobs"}):Ju("div",{className:"table-wrap findjob-job-table"},Ju("table",null,Ju("thead",null,Ju("tr",null,Ju("th",null,"优先级"),Ju("th",null,"状态"),Ju("th",null,"单位"),Ju("th",null,"职位"),Ju("th",null,"城市"),Ju("th",null,"阶段"),Ju("th",null,"截止"),Ju("th",null,"证据"))),Ju("tbody",null,j.map((Q)=>Ju("tr",{key:Q.id},Ju("td",null,Ju(kt,{status:String(Q.priority||"").toLowerCase()||"unknown"},Q.priority||"--")),Ju("td",null,Ju(kt,{status:String(Q.status||"").toLowerCase()||"unknown"},Q.status||"--")),Ju("td",null,Q.organization_name||"--",Ju("code",null,Q.id||"--")),Ju("td",null,Q.display_title||Q.title||"--"),Ju("td",null,Q.display_city||Q.city||"--"),Ju("td",null,Q.workflow_stage||"--"),Ju("td",null,Q.deadline||"--"),Ju("td",null,Q.evidence_url?Ju("a",{href:Q.evidence_url,target:"_blank",rel:"noreferrer"},"打开"):Ju("span",{className:"muted"},"无"))))))),Ju("div",{className:"panel-actions inline-actions"},Ju(gt,{title:"FindJob Jobs Preview",data:n.jobs,onOpen:f,testId:"raw-findjob-jobs"}))),Ju(It,{title:"草稿与报告",eyebrow:`${F.length} Drafts`,loading:n.loading},F.length===0?Ju(e5,{title:"暂无草稿",text:"D601 findjob backend 未返回 drafts"}):Ju("div",{className:"draft-list"},F.map((Q)=>Ju("article",{key:Q.id,className:"draft-card"},Ju("div",{className:"node-card-head"},Ju("strong",null,Q.id),Ju(kt,{status:Q.status},Q.status||"--")),Ju("div",{className:"docker-meta compact"},Ju("span",null,Q.workflow_stage||"--"),Ju("span",null,`jobs ${Q.counts?.jobs??0}`),Ju("span",null,`reports ${Q.counts?.reports??0}`)),Ju("span",null,Q.latestReportPath||"暂无报告"),Ju("code",null,Nu(Q.updated_at||Q.updatedAt))))),Ju("div",{className:"panel-actions inline-actions"},Ju(gt,{title:"FindJob Drafts",data:n.drafts,onOpen:f,testId:"raw-findjob-drafts"})))))}var h_=Pu(qf(),1);var C=h_.default.createElement,{useEffect:DZ}=h_.default,uA=h_.default.useState;function C_(u){let f=Number(u);return Number.isFinite(f)?`${Math.max(0,Math.min(100,f)).toFixed(1)}%`:"--"}function lA(u){if(u===null||u===void 0||u==="")return"--";let f=Number(u);if(!Number.isFinite(f))return"--";if(f<60)return`${Math.max(0,Math.round(f))}s`;if(f<3600)return`${Math.floor(f/60)}m ${Math.round(f%60)}s`;return`${Math.floor(f/3600)}h ${Math.floor(f%3600/60)}m`}function rA(u,f=2){let l=Number(u);if(!Number.isFinite(l))return u===!1?"false":u===!0?"true":"--";let r=Math.abs(l);if(Number.isInteger(l)||r>=1000)return l.toLocaleString("zh-CN",{maximumFractionDigits:0});if(r>=1)return l.toLocaleString("zh-CN",{maximumFractionDigits:f});return l.toLocaleString("zh-CN",{maximumFractionDigits:Math.max(f,6)})}function x_(u){if(u===null||u===void 0||u==="")return"--";if(typeof u==="boolean")return u?"true":"false";if(typeof u==="number")return rA(u,4);if(Array.isArray(u))return u.map((f)=>x_(f)).join(" x ");if(typeof u==="object")return"已上报";return String(u)}function at(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=f>=100?0:f>=10?1:2;return`${f.toLocaleString("zh-CN",{maximumFractionDigits:l})} epoch/h`}function ot(u){return u.replace(/[^a-zA-Z0-9_-]/g,"-")}function vl(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:{}}function R_({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return C("span",{className:`status-badge ${l}`},f||u||"unknown")}function Tn({label:u,value:f,hint:l,tone:r}){return C("article",{className:`metric-card ${r||""}`},C("div",{className:"metric-label"},u),C("div",{className:"metric-value"},f),C("div",{className:"metric-hint"},l))}function fA({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return C("section",{className:`panel ${n||""}`},C("div",{className:"panel-head"},C("div",null,f?C("p",{className:"panel-eyebrow"},f):null,C(nf,{title:u,loading:i})),l?C("div",{className:"panel-actions"},l):null),C("div",{className:"panel-body"},r))}function hi({title:u,data:f,onOpen:l,testId:r}){return C("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:(n)=>{n?.stopPropagation?.(),l(u,f)}},"查看原始JSON")}function Y0({title:u,text:f}){return C("div",{className:"empty-state"},C("strong",null,u),C("span",null,f))}function XZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function YZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function SZ(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function pZ(u){return u?.counts&&typeof u.counts==="object"&&!Array.isArray(u.counts)?u.counts:{}}function mZ(u){return Array.isArray(u?.jobs)?u.jobs.slice(0,240):[]}function PZ(u){return Array.isArray(u?.projects)?u.projects.slice(0,1000):[]}function dt(u){return Array.isArray(u?.projects)?u.projects:[]}function MZ(u,f){if(Array.isArray(f?.gpu))return f.gpu;if(Array.isArray(u?.gpu))return u.gpu;return[]}function jr(u,f){return`${u}/microservices/met-nonlinear/proxy${f}`}function SQ(u){return u.startedAt&&u.finishedAt?lA((Date.parse(u.finishedAt)-Date.parse(u.startedAt))/1000):"--"}function CZ(u){let f=u.progress||{};if(f.etaSeconds!==null&&f.etaSeconds!==void 0&&f.etaSeconds!==""){let y=Number(f.etaSeconds);if(Number.isFinite(y))return Math.max(0,y)}let l=Number(f.currentEpoch),r=Number(f.epochTarget??u.epochTarget),n=Date.parse(u.startedAt||"");if(!Number.isFinite(l)||l<=0||!Number.isFinite(r)||r<=l||!Number.isFinite(n))return null;let i=Math.max(0,(Date.now()-n)/1000);if(i<=0)return null;return Math.max(0,i/l*(r-l))}function pQ(u){let f=u.progress||{},l=Number(f.epochPerHour);if(Number.isFinite(l)&&l>0)return l;let r=Date.parse(u.startedAt||""),n=["succeeded","failed","canceled"].includes(u.status)?Date.parse(u.finishedAt||""):Date.now();if(!Number.isFinite(r)||!Number.isFinite(n)||n<=r)return null;let i=Number(f.currentEpoch??u.epochTarget);if(!Number.isFinite(i)||i<=0)return null;return i/((n-r)/3600000)}function mQ(u){if(u==="staged")return"待启动";if(u==="queued")return"排队中";if(u==="running")return"训练中";if(u==="succeeded")return"已完成";if(u==="failed")return"失败";if(u==="canceled")return"已取消";return u||"unknown"}function PQ(u,f,l){return{name:u,path:f,depth:l,count:0,children:[],project:null}}function RZ(u){let f=PQ("","",-1);for(let r of u){let i=String(r?.projectPath||"").replace(/\\/g,"/").split("/").filter(Boolean);if(i.length===0)continue;let y=f,_=[];for(let[$,A]of i.entries()){_.push(A);let c=_.join("/"),j=y.children.find((F)=>F.path===c);if(!j)j=PQ(A,c,$),y.children.push(j);if($===i.length-1)j.project=r;y=j}}let l=(r)=>{let n=r.children.reduce((i,y)=>i+l(y),0);return r.count=(r.project?1:0)+n,r.children.sort((i,y)=>{if(Boolean(i.project)!==Boolean(y.project))return i.project?1:-1;return i.name.localeCompare(y.name,"zh-CN",{numeric:!0,sensitivity:"base"})}),r.count};return l(f),f}function xZ(u){let f=vl(u.data);return vl(f.project).projectPath?vl(f.project):f}function hZ(u){return vl(vl(u.data).job)}function MQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((P)=>P.id==="met-nonlinear")||null,[n,i]=uA({loading:!1,actionBusy:!1,error:"",health:null,summary:null,queue:null,projects:null,history:null,images:null,refreshedAt:null}),[y,_]=uA({loading:!1,error:"",kind:"",key:"",title:"",data:null}),[$,A]=uA(()=>({activeTab:"projects",selectedProjects:{},expandedProjectDirs:{},sourceProject:"",forkCount:1,forkEpochs:200,forkPrefix:`ui_fork_${Date.now()}`,maxConcurrency:3,targetGpuName:"2080 Ti",actionMessage:""}));function c(P){A((e)=>({...e,...P}))}async function j(P=$.activeTab){if(!r)return;i((e)=>({...e,loading:!0,error:""}));try{let e=[["health",Eu(`${l}/microservices/met-nonlinear/health`)],["summary",Eu(jr(l,"/api/summary"))]];if(P==="projects")e.push(["projectsRoot",Eu(jr(l,"/api/projects?root=projects&limit=500"))]),e.push(["exProjectsRoot",Eu(jr(l,"/api/projects?root=ex_projects&limit=500"))]);if(P==="current"||P==="completed"||P==="failed")e.push(["queue",Eu(jr(l,"/api/queue"))]);if(P==="completed"||P==="failed")e.push(["history",Eu(jr(l,"/api/history"))]);if(P==="gpu")e.push(["images",Eu(jr(l,"/api/images"))]);let uu=Object.fromEntries(await Promise.all(e.map(async([g,Qu])=>[g,await Qu]))),Wu={loading:!1,actionBusy:!1,error:"",health:uu.health,summary:uu.summary,refreshedAt:new Date};if(uu.projectsRoot||uu.exProjectsRoot){let{projectsRoot:g,exProjectsRoot:Qu}=uu;Wu.projects={ok:g?.ok!==!1&&Qu?.ok!==!1,roots:[{root:"projects",count:dt(g).length},{root:"ex_projects",count:dt(Qu).length}],projects:[...dt(g),...dt(Qu)]}}if(uu.queue)Wu.queue=uu.queue;if(uu.history)Wu.history=uu.history;if(uu.images)Wu.images=uu.images;i((g)=>({...g,...Wu}))}catch(e){i((uu)=>({...uu,loading:!1,actionBusy:!1,error:Hu(e,"MET Nonlinear 加载失败")}))}}async function F(P,e){i((uu)=>({...uu,actionBusy:!0,error:""})),c({actionMessage:`${P}...`});try{let uu=await e();c({actionMessage:uu||`${P}完成`}),await j()}catch(uu){i((Wu)=>({...Wu,actionBusy:!1,error:Hu(uu,`${P}失败`)}))}}async function U(){await F("保存并发设置",async()=>{await Eu(jr(l,"/api/queue/settings"),{method:"PUT",body:JSON.stringify({maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName})})})}function Q(){return Object.entries($.selectedProjects).filter(([,P])=>P).map(([P])=>P)}async function L(){let P=Q();if(P.length===0)throw Error("请先选择至少一个 project");await F("加入待启动队列",async()=>{await Eu(jr(l,"/api/queue"),{method:"POST",body:JSON.stringify({projectPaths:P,maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName,start:!1})}),c({activeTab:"current",selectedProjects:{}})})}async function w(){let P=$.sourceProject||p[0]?.projectPath;if(!P)throw Error("请先选择源 project");await F("Fork Project",async()=>{let e=await Eu(jr(l,"/api/projects/fork"),{method:"POST",body:JSON.stringify({sourceProject:P,count:Number($.forkCount),epochs:Number($.forkEpochs),prefix:$.forkPrefix})}),uu=Array.isArray(e.projectPaths)?e.projectPaths:[],Wu=uu.reduce((g,Qu)=>{return g[Qu]=!0,g},{...$.selectedProjects});return c({selectedProjects:Wu}),`已 fork ${uu.length} 个 project,并已自动勾选;请确认后点击加入待启动队列。`})}async function J(){await F("启动队列",async()=>{await Eu(jr(l,"/api/queue/start"),{method:"POST",body:JSON.stringify({maxConcurrency:Number($.maxConcurrency),targetGpuName:$.targetGpuName})}),c({activeTab:"current"})})}async function N(P){await F("取消任务",async()=>{await Eu(jr(l,`/api/jobs/${encodeURIComponent(P.id)}/cancel`),{method:"POST",body:JSON.stringify({})})})}async function q(P){let e=String(P?.projectPath||"");if(!e)return;_({loading:!0,error:"",kind:"project",key:e,title:e,data:null});try{let uu=await Eu(jr(l,`/api/projects/config?path=${encodeURIComponent(e)}`));_({loading:!1,error:"",kind:"project",key:e,title:e,data:uu})}catch(uu){_({loading:!1,error:Hu(uu,"Project 详情加载失败"),kind:"project",key:e,title:e,data:null})}}async function W(P){let e=String(P?.id||"");if(!e)return;_({loading:!0,error:"",kind:"job",key:e,title:P.projectPath||e,data:null});try{let uu=await Eu(jr(l,`/api/jobs/${encodeURIComponent(e)}`));_({loading:!1,error:"",kind:"job",key:e,title:uu?.job?.projectPath||P.projectPath||e,data:uu})}catch(uu){_({loading:!1,error:Hu(uu,"Job 详情加载失败"),kind:"job",key:e,title:P.projectPath||e,data:null})}}if(DZ(()=>{j($.activeTab)},[r?.id,r?.runtime?.providerStatus,$.activeTab]),!r)return C(Y0,{title:"MET Nonlinear 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=met-nonlinear"});let z=XZ(r),Z=SZ(r),H=YZ(r),E=pZ(n.queue?.queue||n.summary?.queue),D=MZ(n.health,n.queue),h=n.health?.targetGpu||n.summary?.targetGpu||D.find((P)=>String(P.name||"").includes("2080")),V=n.images?.mlImage||n.health?.image||{},Y=mZ(n.queue),p=PZ(n.projects),O=RZ(p),m=$.sourceProject||p[0]?.projectPath||"",X=Y.filter((P)=>["staged","queued","running"].includes(P.status)),v=Y.filter((P)=>P.status==="succeeded"),T=Y.filter((P)=>["failed","canceled"].includes(P.status)),S=Array.isArray(n.history?.jobs)?n.history.jobs.slice(0,120):[],k=[{id:"projects",label:"项目库",count:p.length},{id:"current",label:"当前队列",count:X.length||Number(E.staged||0)+Number(E.queued||0)+Number(E.running||0)},{id:"completed",label:"已完成",count:v.length||Number(E.succeeded||0)},{id:"failed",label:"失败诊断",count:T.length||Number(E.failed||0)+Number(E.canceled||0)},{id:"gpu",label:"GPU/镜像",count:D.length}];function I(P,e){if(P.length===0)return C(Y0,{title:e==="current"?"当前队列为空":"暂无记录",text:e==="current"?"从项目库选择或 fork project 后先加入待启动队列,再启动队列。":"终态任务会显示耗时、exit code 和失败诊断。"});return C("div",{className:"table-wrap met-job-table"},C("table",null,C("thead",null,C("tr",null,C("th",null,"状态"),C("th",null,"Project"),C("th",null,"Epoch"),C("th",null,"速度"),C("th",null,"ETA/耗时"),C("th",null,"GPU"),C("th",null,"Exit"),C("th",null,"更新时间"),C("th",null,"操作"))),C("tbody",null,P.map((uu)=>{let Wu=uu.progress||{},g=["staged","queued","running"].includes(uu.status),Qu=y.kind==="job"&&y.key===uu.id;return C("tr",{key:uu.id,className:`met-click-row ${Qu?"active":""}`,onClick:()=>W(uu),"data-testid":`met-job-row-${ot(uu.id)}`},C("td",null,C(R_,{status:uu.status},mQ(uu.status))),C("td",null,C("button",{type:"button",className:"met-inline-link",onClick:(Tu)=>{Tu.stopPropagation(),W(uu)}},uu.projectPath),C("code",null,uu.id)),C("td",null,C("span",null,`${Wu.currentEpoch??"--"} / ${Wu.epochTarget??uu.epochTarget??"--"}`),C("div",{className:"met-progress"},C("span",{style:{width:C_(Wu.progressPercent)}}))),C("td",null,C("strong",null,at(pQ(uu)))),C("td",null,uu.status==="succeeded"||uu.status==="failed"||uu.status==="canceled"?SQ(uu):uu.status==="running"?`ETA ${lA(CZ(uu))}`:"--"),C("td",null,uu.gpuName||"--"),C("td",null,uu.exitCode??"--"),C("td",null,Nu(uu.updatedAt)),C("td",null,g?C("button",{type:"button",className:"ghost-btn mini",onClick:(Tu)=>{Tu.stopPropagation(),N(uu)},disabled:n.actionBusy},"取消"):null,C(hi,{title:`MET Job ${uu.id}`,data:uu,onOpen:f,testId:`raw-met-job-${uu.id}`})))}))))}function b(){return C("div",{className:"met-queue-summary","data-testid":"met-current-summary"},C(R_,{status:"staged"},`待启动 ${E.staged??0}`),C(R_,{status:"queued"},`排队中 ${E.queued??0}`),C(R_,{status:"running"},`训练中 ${E.running??0}`),C("span",null,`最大并发 ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??$.maxConcurrency}`),C("span",null,`目标 GPU ${n.summary?.queue?.targetGpuName??n.queue?.queue?.targetGpuName??$.targetGpuName}`))}function o(P,e){let uu=$.expandedProjectDirs[P];return uu===void 0?e<2:Boolean(uu)}function s(P,e){let uu=o(P,e);c({expandedProjectDirs:{...$.expandedProjectDirs,[P]:!uu}})}function x(P){let e=8+Math.max(0,P.depth)*16;if(Boolean(P.project)){let g=P.project,Qu=Boolean($.selectedProjects[g.projectPath]),Tu=y.kind==="project"&&y.key===g.projectPath;return C("div",{key:P.path,className:`met-tree-row project ${Qu?"selected":""} ${Tu?"active":""}`,style:{paddingLeft:e},onClick:()=>q(g),"data-testid":`met-project-node-${ot(g.projectPath)}`},C("div",{className:"met-tree-name"},C("input",{type:"checkbox",checked:Qu,onClick:(Zu)=>Zu.stopPropagation(),onChange:(Zu)=>c({selectedProjects:{...$.selectedProjects,[g.projectPath]:Zu.target.checked}}),"data-testid":`met-project-checkbox-${ot(g.projectPath)}`}),C("button",{type:"button",className:"met-inline-link project-path",onClick:(Zu)=>{Zu.stopPropagation(),q(g)}},P.name)),C("span",null,g.useModel||"--"),C("span",null,g.epochTrain??"--"),C("span",null,C_(g.progress?.progressPercent)),C("span",null,at(g.progress?.epochPerHour)))}let Wu=o(P.path,P.depth);return C(h_.default.Fragment,{key:P.path},C("div",{className:"met-tree-row folder",style:{paddingLeft:e},"data-testid":`met-project-folder-${ot(P.path)}`},C("button",{type:"button",className:"met-tree-toggle",onClick:()=>s(P.path,P.depth),"aria-label":Wu?`折叠 ${P.path}`:`展开 ${P.path}`},Wu?"-":"+"),C("strong",null,P.name),C("span",{className:"met-tree-count"},`${P.count} projects`)),Wu?P.children.map((g)=>x(g)):null)}function fu(P){return C("div",{className:"met-detail-kv"},P.map((e)=>C("div",{key:e.label,className:"met-detail-kv-item"},C("span",null,e.label),C("strong",null,x_(e.value)),e.hint?C("small",null,e.hint):null)))}function $u(P,e){return C("div",{className:"met-detail-section"},C("h3",null,P),fu(e))}function tu(P){if(!Array.isArray(P)||P.length===0)return C(Y0,{title:"模型层未上报",text:"等待 data/model_info.json 或 compute_analysis.json 生成。"});return C("div",{className:"table-wrap met-layer-table"},C("table",null,C("thead",null,C("tr",null,C("th",null,"Layer"),C("th",null,"Type"),C("th",null,"Params"),C("th",null,"Trainable"),C("th",null,"Compute"))),C("tbody",null,P.slice(0,18).map((e,uu)=>C("tr",{key:`${e.name||"layer"}-${uu}`},C("td",null,e.name||`#${uu+1}`),C("td",null,e.type||"--"),C("td",null,rA(e.num_params)),C("td",null,e.trainable===void 0?"--":String(Boolean(e.trainable))),C("td",null,rA(e.compute?.total??e.estimated_cost?.weighted_units?.total)))))))}function ju(P){let e=Array.isArray(P)?P:[];if(e.length===0)return C(Y0,{title:"data/ 暂无文件",text:"训练或评估完成后会生成 training_state、metrics、model_info 等文件。"});return C("div",{className:"met-file-chip-grid"},e.slice(0,48).map((uu)=>C("span",{key:uu},uu)),e.length>48?C("span",null,`+${e.length-48}`):null)}function Gu(P){let e=String(P||"").replace(/\x1b\[[0-9;]*[A-Za-z]/g,"").split(/\r?\n/).map((uu)=>uu.trim()).filter(Boolean).slice(-12);if(e.length===0)return C(Y0,{title:"暂无日志尾部",text:"该任务未上报 logTail 或日志已轮转。"});return C("div",{className:"met-log-lines"},e.map((uu,Wu)=>C("div",{key:`${Wu}-${uu.slice(0,16)}`},uu)))}function qu(){if(y.loading)return C("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},C("div",{className:"panel-head compact"},C("div",null,C("p",{className:"panel-eyebrow"},"Detail Loading"),C(nf,{title:"详情加载中",loading:!0}))),C(Y0,{title:"详情加载中",text:y.title||"正在读取 D601 data/ 和 config.json"}));if(y.error)return C("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},C(yf,{error:y.error,wide:!0}));if(!y.data)return C("section",{className:"met-detail-panel muted","data-testid":"met-detail-panel"},C(Y0,{title:"选择一个项目或任务查看详情",text:"项目库、当前队列、已完成和失败诊断中的行都可以点击;默认只展示结构化字段,原始 JSON 需显式点击按钮。"}));let P=xZ(y),e=hZ(y),uu=vl(P.config),Wu=vl(P.progress||e.progress),g=vl(P.data),Qu=vl(P.metrics||g.metrics||Wu.trainingInfo?.evaluation_metrics),Tu=vl(g.trainingInfo||Wu.trainingInfo),Zu=vl(g.trainingState),Xu=vl(P.model||g.model),uf=Array.isArray(Xu.modelSummary)&&Xu.modelSummary.length>0?Xu.modelSummary:Xu.computeLayers,_f=vl(Tu.evaluation_metrics),Jf=y.kind==="job"?"训练任务详情":"Project 详情";return C("section",{className:"met-detail-panel","data-testid":"met-detail-panel"},C("div",{className:"panel-head compact"},C("div",null,C("p",{className:"panel-eyebrow"},y.kind==="job"?"Job + Project Detail":"Project Library Detail"),C(nf,{title:Jf}),C("code",null,P.projectPath||e.projectPath||y.title)),C("div",{className:"panel-actions"},C(hi,{title:`MET ${Jf}`,data:y.data,onOpen:f,testId:"raw-met-detail"}))),y.kind==="job"?$u("任务状态",[{label:"Job ID",value:e.id},{label:"状态",value:mQ(e.status)},{label:"GPU",value:e.gpuName},{label:"Exit Code",value:e.exitCode},{label:"耗时",value:SQ(e)},{label:"训练速度",value:at(pQ({...e,progress:Wu}))}]):null,$u("config.json",[{label:"use_model",value:uu.use_model},{label:"epoch_train",value:uu.epoch_train},{label:"step_per_epoch",value:uu.step_per_epoch},{label:"learning_rate",value:uu.learning_rate},{label:"using_gpu",value:uu.using_gpu},{label:"use_points",value:uu.use_points},{label:"sample_rate",value:uu.sample_rate},{label:"time_clipped_s",value:uu.time_clipped_s},{label:"H_UNITS",value:uu.H_UNITS},{label:"INNER_KAN_UNITS",value:uu.INNER_KAN_UNITS},{label:"INNER_KAN_LAYERS",value:uu.INNER_KAN_LAYERS},{label:"GRID_SIZE",value:uu.GRID_SIZE},{label:"SPLINE_ORDER",value:uu.SPLINE_ORDER},{label:"USE_FAST_MODEL",value:uu.USE_FAST_MODEL},{label:"IIR_TRAINABLE",value:uu.IIR_TRAINABLE}]),$u("data/ 训练状态",[{label:"Epoch",value:`${Wu.currentEpoch??Zu.current_epoch??Zu.completed_epoch??"--"} / ${Wu.epochTarget??uu.epoch_train??"--"}`},{label:"Progress",value:C_(Wu.progressPercent)},{label:"Last Loss",value:Wu.lastLoss??Zu.loss},{label:"Last Val Loss",value:Wu.lastValLoss??Zu.val_loss},{label:"Min Loss",value:Tu.min_loss??Zu.min_loss},{label:"Min Val Loss",value:Tu.min_val_loss??Zu.min_val_loss},{label:"Log Lines",value:Wu.logLineCount},{label:"ETA",value:lA(Wu.etaSeconds??Zu.remaining_time)},{label:"训练速度",value:at(Wu.epochPerHour??Zu.smoothed_speed)},{label:"Training Alive",value:Zu.training_alive}]),$u("模型参数",[{label:"Model Type",value:Xu.modelType??uu.use_model},{label:"Total Params",value:Xu.totalParams,hint:Xu.totalParams===null||Xu.totalParams===void 0?"未上报":"data/model_info.json"},{label:"Trainable",value:Xu.trainableParams},{label:"Non-trainable",value:Xu.nonTrainableParams},{label:"Compute Cost",value:Xu.computeCost},{label:"Estimate Status",value:Xu.estimateStatus},{label:"Unsupported Layers",value:Xu.unsupportedLayerCount}]),$u("指标",[{label:"train_loss",value:Qu.train_loss??_f.train_loss},{label:"val_loss",value:Qu.val_loss??_f.val_loss},{label:"train_mae",value:Qu.train_mae??_f.train_mae},{label:"val_mae",value:Qu.val_mae??_f.val_mae},{label:"train_afmae",value:Qu.train_afmae??_f.train_afmae},{label:"val_afmae",value:Qu.val_afmae??_f.val_afmae},{label:"freq_drift_hz",value:Qu.freq_drift_hz},{label:"sens_drift_percent",value:Qu.sens_drift_percent},{label:"linearity_percent",value:Qu.linearity_percent},{label:"weights_source",value:Qu.weights_source??_f.weights_source},{label:"lr min/mean/max",value:`${x_(Tu.learning_rate_min)} / ${x_(Tu.learning_rate_mean)} / ${x_(Tu.learning_rate_max)}`}]),C("div",{className:"met-detail-section"},C("h3",null,"模型层"),tu(uf)),C("div",{className:"met-detail-section"},C("h3",null,"data/ 文件"),ju(g.files)),y.kind==="job"?C("div",{className:"met-detail-section"},C("h3",null,"日志尾部"),Gu(vl(y.data).logTail)):null)}return C("div",{className:"met-page","data-testid":"met-nonlinear-page"},C(fA,{title:"MET Nonlinear 训练编排",eyebrow:"D601 GPU 用户服务",loading:n.loading||n.actionBusy,actions:C("div",{className:"panel-actions"},C("button",{type:"button",className:"ghost-btn",onClick:j,disabled:n.loading,"data-testid":"met-refresh-button"},n.loading?"刷新中":"刷新"),C(hi,{title:"MET Nonlinear 用户服务",data:r,onOpen:f,testId:"raw-met-service"}))},C("div",{className:"findjob-hero"},C("div",null,C("div",{className:"node-version-line"},C(R_,{status:z.providerStatus==="online"?"online":"warn"},z.providerStatus||"unknown"),C("span",null,r.providerId),C("span",null,H.public?"公网暴露":"仅 UniDesk frontend 代理访问")),C("p",{className:"muted paragraph"},r.description)),C("div",{className:"microservice-ref-card"},C("span",null,"Repo"),C("strong",null,Z.url||"--"),C("code",null,Z.commitId||"--")),C("div",{className:"microservice-ref-card"},C("span",null,"D601 Docker"),C("strong",null,`${H.nodeBindHost||"--"}:${H.nodePort||"--"}`),C("code",null,`${Z.composeFile||"--"} / ${Z.containerName||"--"}`))),C(yf,{error:n.error,wide:!0}),$.actionMessage?C("div",{className:"met-action-log","data-testid":"met-action-message"},$.actionMessage):null),C("div",{className:"met-grid"},C(fA,{title:"核心状态",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Queue + GPU",loading:n.loading},C("div",{className:"metric-grid"},C(Tn,{label:"Staged",value:E.staged??0,hint:"加入队列未开始",tone:Number(E.staged||0)>0?"warn":""}),C(Tn,{label:"Queued",value:E.queued??0,hint:"排队等待调度",tone:Number(E.queued||0)>0?"warn":""}),C(Tn,{label:"Running",value:E.running??0,hint:`max ${n.summary?.queue?.maxConcurrency??n.queue?.queue?.maxConcurrency??"--"}`,tone:Number(E.running||0)>0?"ok":""}),C(Tn,{label:"Succeeded",value:E.succeeded??0,hint:"已完成"}),C(Tn,{label:"Failed",value:E.failed??0,hint:"需要诊断",tone:Number(E.failed||0)>0?"warn":""}),C(Tn,{label:"2080Ti Free",value:h?C_(Number(h.freeRatio)*100):"--",hint:h?`${h.memoryFreeMiB}/${h.memoryTotalMiB} MiB`:"等待 GPU 上报"}),C(Tn,{label:"ML Image",value:V.present?"READY":"MISSING",hint:V.image||"met-nonlinear-ml:tf26",tone:V.present?"ok":"warn"}),C(Tn,{label:"Health",value:n.health?.ok?"OK":"--",hint:"D601 /health"}))),C(fA,{title:"队列控制",eyebrow:"Downloader-like staging",loading:n.actionBusy},C("div",{className:"met-control-strip"},C("label",null,"最大并发",C("input",{type:"number",min:1,max:16,value:$.maxConcurrency,"data-testid":"met-max-concurrency-input",onChange:(P)=>c({maxConcurrency:P.target.value})})),C("label",null,"目标 GPU",C("input",{value:$.targetGpuName,"data-testid":"met-target-gpu-input",onChange:(P)=>c({targetGpuName:P.target.value})})),C("button",{type:"button",className:"ghost-btn",onClick:U,disabled:n.actionBusy,"data-testid":"met-save-settings-button"},"保存设置"),C("button",{type:"button",className:"primary-btn",onClick:J,disabled:n.actionBusy||Number(E.staged||0)===0,"data-testid":"met-start-queue-button"},"启动队列")),C("p",{className:"muted paragraph"},"Project 先进入待启动队列,不会立即训练;点击启动队列后才切换为排队中,并由 D601 scheduler 按最大并发和 2080Ti 显存策略调度。")),C("section",{className:"panel met-workspace"},C("div",{className:"met-tabs",role:"tablist"},k.map((P)=>C("button",{key:P.id,type:"button",className:$.activeTab===P.id?"active":"",onClick:()=>c({activeTab:P.id}),"data-testid":`met-tab-${P.id}`},`${P.label} ${P.count}`))),C("div",{className:"panel-body"},$.activeTab==="projects"?C("div",{className:"met-form-grid","data-testid":"met-projects-pane"},C("div",{className:"met-fork-card"},C("h3",null,"Fork Project"),C("label",null,"源 Project",C("select",{value:m,"data-testid":"met-source-project-select",onChange:(P)=>c({sourceProject:P.target.value})},p.map((P)=>C("option",{key:P.projectPath,value:P.projectPath},`${P.projectPath} · ${P.useModel||"model?"}`)))),C("label",null,"Fork 数量",C("input",{type:"number",min:1,max:100,value:$.forkCount,"data-testid":"met-fork-count-input",onChange:(P)=>c({forkCount:P.target.value})})),C("label",null,"训练轮数",C("input",{type:"number",min:1,max:1e5,value:$.forkEpochs,"data-testid":"met-fork-epochs-input",onChange:(P)=>c({forkEpochs:P.target.value})})),C("label",null,"目标前缀",C("input",{value:$.forkPrefix,"data-testid":"met-fork-prefix-input",onChange:(P)=>c({forkPrefix:P.target.value})})),C("button",{type:"button",className:"primary-btn",onClick:w,disabled:n.actionBusy||!m,"data-testid":"met-fork-button"},"Fork Project"),C("p",{className:"muted paragraph"},"Fork 只创建新 Project 并自动勾选,不会直接训练;需要在右侧确认后加入待启动队列。")),C("div",{className:"met-project-list"},C("div",{className:"panel-head compact"},C("div",null,C("p",{className:"panel-eyebrow"},`Existing Projects · ${(n.projects?.roots||[]).map((P)=>`${P.root} ${P.count}`).join(" / ")}`),C(nf,{title:"选择已有 Project",loading:n.loading||n.actionBusy})),C("button",{type:"button",className:"ghost-btn",onClick:L,disabled:n.actionBusy||Q().length===0,"data-testid":"met-stage-selected-button"},`加入待启动队列 (${Q().length})`)),p.length===0?C(Y0,{title:"暂无 project",text:"等待 D601 返回 /api/projects"}):C("div",{className:"met-project-table","data-testid":"met-project-tree"},C("div",{className:"met-tree-header"},C("span",null,"文件树 Project"),C("span",null,"Model"),C("span",null,"Epochs"),C("span",null,"Progress"),C("span",null,"速度")),O.children.map((P)=>x(P)))),qu()):null,$.activeTab==="current"?C("div",{"data-testid":"met-current-pane"},b(),I(X,"current"),qu(),C("div",{className:"panel-actions inline-actions"},C(hi,{title:"MET Queue",data:n.queue,onOpen:f,testId:"raw-met-queue"}))):null,$.activeTab==="completed"?C("div",{"data-testid":"met-completed-pane"},I(v.length>0?v:S.filter((P)=>P.status==="succeeded"),"completed"),qu()):null,$.activeTab==="failed"?C("div",{"data-testid":"met-failed-pane"},I(T.length>0?T:S.filter((P)=>["failed","canceled"].includes(P.status)),"failed"),qu(),C("div",{className:"panel-actions inline-actions"},C(hi,{title:"MET History",data:n.history,onOpen:f,testId:"raw-met-history"}))):null,$.activeTab==="gpu"?C("div",{className:"met-gpu-pane","data-testid":"met-gpu-pane"},D.length===0?C(Y0,{title:"暂无 GPU 上报",text:"等待 D601 met-nonlinear-ts 或 ML image 提供 nvidia-smi 数据"}):C("div",{className:"table-wrap"},C("table",null,C("thead",null,C("tr",null,C("th",null,"Index"),C("th",null,"Name"),C("th",null,"Free"),C("th",null,"Policy"))),C("tbody",null,D.map((P)=>C("tr",{key:P.index},C("td",null,P.index),C("td",null,P.name),C("td",null,`${P.memoryFreeMiB} / ${P.memoryTotalMiB} MiB`,C("div",{className:"met-progress"},C("span",{style:{width:C_(Number(P.freeRatio)*100)}}))),C("td",null,String(P.name||"").includes("2080")?"target 2080Ti, <20% 限制并发":"non-target")))))),C("div",{className:"panel-actions inline-actions"},C(hi,{title:"MET Images",data:n.images,onOpen:f,testId:"raw-met-images"}))):null))))}var u6=[{id:"ops",label:"运行总览",code:"OPS",tabs:[{id:"status",label:"态势总览"},{id:"performance",label:"性能面板"},{id:"events",label:"事件摘要"},{id:"logs",label:"服务日志"}]},{id:"nodes",label:"资源节点",code:"NODE",tabs:[{id:"list",label:"节点清单"},{id:"monitor",label:"资源监控"},{id:"docker",label:"Docker 状态"},{id:"gateway",label:"网关版本"},{id:"labels",label:"资源标签"},{id:"heartbeats",label:"心跳状态"}]},{id:"tasks",label:"任务调度",code:"TASK",tabs:[{id:"dispatch",label:"下发任务"},{id:"scheduled",label:"定时任务"},{id:"pending",label:"待处理任务"},{id:"history",label:"任务历史"},{id:"results",label:"执行结果"}]},{id:"apps",label:"用户服务",code:"APP",routeSegment:"app",tabs:[{id:"catalog",label:"服务目录"},{id:"todo-note",label:"Todo Note"},{id:"findjob",label:"FindJob"},{id:"pipeline",label:"Pipeline"},{id:"met-nonlinear",label:"MET Nonlinear"},{id:"claudeqq",label:"ClaudeQQ"},{id:"baidu-netdisk",label:"Baidu Netdisk"},{id:"filebrowser",label:"File Browser"},{id:"oa-event-flow",label:"OA Event Flow"},{id:"code-queue",label:"Code Queue"},{id:"project-manager",label:"Project Manager"}]},{id:"config",label:"系统配置",code:"CFG",tabs:[{id:"topology",label:"连接拓扑"},{id:"auth",label:"认证策略"},{id:"security",label:"安全边界"}]}],b_=Object.fromEntries(u6.map((u)=>[u.id,u.tabs[0]?.id??""]));function bZ(u){let f=String(u||"").trim();if(!f)return"";try{return decodeURIComponent(f)}catch{return f}}function et(u){let f=String(u||"/"),[l]=f.split(/[?#]/u,1);if(l==="/")return"/";let n=`/${l.split("/").map(bZ).filter(Boolean).join("/")}`;return n.endsWith("/")?n:`${n}/`}function vZ(u){let f=2166136261;for(let l of u)f^=l.charCodeAt(0),f=Math.imul(f,16777619);return Math.abs(f>>>0).toString(36)}function nA(u){return String(u||"").normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"")}function CQ(u){return String(u||"").trim().toLowerCase().replace(/[\s/\\?#%]+/gu,"-").replace(/-+/gu,"-").replace(/^-+|-+$/gu,"")}function RQ(u){let f=nA(u.routeSegment||"")||CQ(u.routeSegment||"");if(f)return f;let l=nA(u.id||"");if(l)return l;let r=nA(u.label||"")||CQ(u.label||"");if(r)return r;return`route-${vZ(JSON.stringify(u))}`}function iA(u,f){return`${u}:${f}`}function xQ(u){let f=u.map(($)=>{let A=RQ($);return{...$,routeSegment:A,tabs:$.tabs.map((c)=>({...c,routeSegment:RQ(c)}))}}),l={},r={},n={},i=f.map(($)=>{let A=$.tabs[0]?.id??"";n[$.id]=A;let c=$.tabs.map((U)=>{let Q=`/${$.routeSegment}/${U.routeSegment}/`,L=[Q],w={moduleId:$.id,tabId:U.id};for(let J of L)l[et(J)]=w;return r[iA($.id,U.id)]=Q,{...U,canonicalPath:Q,aliases:L}}),j=`/${$.routeSegment}/`,F={moduleId:$.id,tabId:A};return l[et(j)]=F,{...$,routeSegment:$.routeSegment,canonicalPath:j,tabs:c}}),y=i[0],_={moduleId:y?.id||"",tabId:y?.tabs[0]?.id||""};return l["/"]=_,{modules:i,moduleById:Object.fromEntries(i.map(($)=>[$.id,$])),defaultActiveTabs:n,routeMap:l,canonicalPathByTarget:r,fallbackTarget:_}}function yA(u,f){return u.routeMap[et(f)]||u.fallbackTarget}function f6(u,f,l){return u.canonicalPathByTarget[iA(f,l)]||u.canonicalPathByTarget[iA(u.fallbackTarget.moduleId,u.fallbackTarget.tabId)]||"/"}function hQ(u,f){let l=u.routeMap[et(f)];if(!l)return null;return f6(u,l.moduleId,l.tabId)}var i6=Pu(qf(),1);var iu=i6.default.createElement,{useEffect:bQ,useMemo:kZ}=i6.default,_A=i6.default.useState;function n6({status:u,children:f,title:l}){let r=String(u||"unknown").toLowerCase();return iu("span",{className:`status-badge ${r}`,title:l},f||u||"unknown")}function v_({label:u,value:f,hint:l,tone:r}){return iu("article",{className:`metric-card ${r||""}`},iu("div",{className:"metric-label"},u),iu("div",{className:"metric-value"},f),iu("div",{className:"metric-hint"},l))}function l6({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return iu("section",{className:`panel ${n||""}`},iu("div",{className:"panel-head"},iu("div",null,f?iu("p",{className:"panel-eyebrow"},f):null,iu(nf,{title:u,loading:i})),l?iu("div",{className:"panel-actions"},l):null),iu("div",{className:"panel-body"},r))}function k_({title:u,data:f,onOpen:l,testId:r}){return iu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l?.(u,f)},"查看原始JSON")}function $A({title:u,text:f}){return iu("div",{className:"empty-state"},iu("strong",null,u),iu("span",null,f))}function IZ(u){return u&&typeof u==="object"&&!Array.isArray(u)?u:null}function S0(u){return Array.isArray(u)?u:[]}function kl(u){let f=Number(u);return Number.isFinite(f)?f.toLocaleString("zh-CN"):"--"}function vQ(u,f=140){if(u===null||u===void 0)return"--";let l=typeof u==="string"?u:JSON.stringify(u),r=String(l||"").replace(/\s+/gu," ").trim();return r.length>f?`${r.slice(0,f-1)}...`:r||"--"}function gZ(u){return S0(u?.tags).map((f)=>String(f||"").trim()).filter(Boolean)}function G1(u){let f=Number(u);return Number.isFinite(f)&&f>=0?Math.floor(f):0}function sZ(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function aZ(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function oZ(u){return String(u||"").split(/[\s,]+/u).map((f)=>f.trim()).filter(Boolean).join(",")}function r6(u,f){return`${u}/microservices/oa-event-flow/proxy${f}`}function dZ(u){if(u.includes("error")||u.includes("failed"))return"failed";if(u.includes("stats"))return"ok";if(u.includes("step")||u.includes("updated"))return"running";return"queued"}function eZ(u){let f=String(u?.subjectKind||"trace"),l=String(u?.subjectId||u?.scopeId||"");return l?`${f}:${l}`:String(u?.scopeId||"--")}function uO({tags:u}){let f=gZ({tags:u}).slice(0,6);return iu("div",{className:"oa-tag-rail"},f.length===0?iu("span",{className:"muted"},"--"):f.map((l)=>iu("code",{key:l},l)))}function fO({events:u,onRaw:f}){let l=[...S0(u)].reverse();return l.length===0?iu($A,{title:"事件表暂无记录",text:"等待 Code Queue 或 Pipeline 按 tag 发布 OA 事件"}):iu("div",{className:"table-wrap oa-event-table-wrap"},iu("table",{className:"oa-event-table","data-testid":"oa-event-flow-event-table"},iu("thead",null,iu("tr",null,iu("th",null,"Seq"),iu("th",null,"Type"),iu("th",null,"Source"),iu("th",null,"Aggregate"),iu("th",null,"Tags"),iu("th",null,"Payload"),iu("th",null,"Created"),iu("th",null,"Raw"))),iu("tbody",null,l.map((r)=>{let n=String(r?.type||"event"),i=`${String(r?.aggregateType||"--")}:${String(r?.aggregateId||"--")}`;return iu("tr",{key:r?.eventId||r?.sequence},iu("td",null,iu("code",null,kl(r?.sequence))),iu("td",null,iu(n6,{status:dZ(n)},n)),iu("td",null,iu("strong",null,r?.sourceId||"--"),iu("code",null,r?.sourceKind||"--")),iu("td",null,iu("code",null,i)),iu("td",null,iu(uO,{tags:r?.tags})),iu("td",null,iu("span",{className:"oa-payload-preview"},vQ(r?.payload,180))),iu("td",null,Nu(r?.createdAt)),iu("td",null,iu(k_,{title:`OA Event ${r?.sequence||""}`,data:r,onOpen:f,testId:`raw-oa-event-${r?.sequence||"unknown"}`})))}))))}function lO({stats:u,onRaw:f}){let l=S0(u);return l.length===0?iu($A,{title:"统计中心暂无投影",text:"trace-stats-snapshot / trace-step-created 进入事件流后会更新这里"}):iu("div",{className:"table-wrap oa-stats-table-wrap"},iu("table",{className:"oa-stats-table","data-testid":"oa-event-flow-stats"},iu("thead",null,iu("tr",null,iu("th",null,"Scope"),iu("th",null,"Service"),iu("th",null,"STEP"),iu("th",null,"Read"),iu("th",null,"Edit"),iu("th",null,"Run"),iu("th",null,"Error"),iu("th",null,"Output Seq"),iu("th",null,"Revision"),iu("th",null,"Updated"),iu("th",null,"Raw"))),iu("tbody",null,l.map((r)=>iu("tr",{key:r?.scopeId||`${r?.serviceId}-${r?.subjectId}`},iu("td",null,iu("strong",null,eZ(r)),iu("code",null,r?.scopeId||"--")),iu("td",null,iu(n6,{status:String(r?.serviceId||"unknown")==="code-queue"?"running":"queued"},r?.serviceId||"--")),iu("td",null,iu("strong",null,kl(G1(r?.stepCount??r?.llmStepCount)))),iu("td",null,kl(G1(r?.readCount))),iu("td",null,kl(G1(r?.editCount))),iu("td",null,kl(G1(r?.runCount))),iu("td",null,kl(G1(r?.errorCount))),iu("td",null,iu("code",null,kl(G1(r?.outputMaxSeq)))),iu("td",null,kl(G1(r?.statsRevision))),iu("td",null,Nu(r?.updatedAt)),iu("td",null,iu(k_,{title:`OA Trace Stats ${r?.scopeId||""}`,data:r,onOpen:f,testId:`raw-oa-stats-${String(r?.scopeId||"unknown").replace(/[^a-zA-Z0-9_-]/gu,"_")}`})))))))}function kQ({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((z)=>z.id==="oa-event-flow")||null,[n,i]=_A("service:code-queue"),[y,_]=_A({loading:!1,error:"",health:null,diagnostics:null,events:[],stats:[],refreshedAt:null}),[$,A]=_A({status:"idle",message:"未连接",lastEventAt:""}),c=kZ(()=>oZ(n),[n]);async function j(){if(!r)return;_((z)=>({...z,loading:!0,error:""}));try{let z=c?`tags=${encodeURIComponent(c)}&`:"",[Z,H,E,D]=await Promise.all([Eu(`${l}/microservices/oa-event-flow/health`,{failureFields:[]}),Eu(r6(l,"/api/diagnostics")),Eu(r6(l,`/api/events?${z}limit=100`)),Eu(r6(l,`/api/stats/trace?${z}limit=100`))]);_({loading:!1,error:"",health:Z,diagnostics:H,events:S0(E?.events),stats:S0(D?.stats),refreshedAt:new Date})}catch(z){_((Z)=>({...Z,loading:!1,error:Hu(z,"OA Event Flow 加载失败")}))}}if(bQ(()=>{j()},[r?.id,r?.runtime?.providerStatus,c]),bQ(()=>{if(!r||typeof EventSource>"u")return;let z=c?`?tags=${encodeURIComponent(c)}`:"",Z=new EventSource(`${r6(l,"/api/events/stream")}${z}`,{withCredentials:!0});A({status:"running",message:"SSE connecting",lastEventAt:""});let H=(h)=>{A({status:"online",message:vQ(h.data,120),lastEventAt:new Date().toISOString()})},E=(h)=>{try{let V=JSON.parse(String(h.data||"{}"));A({status:"online",message:String(V?.type||h.type||"event"),lastEventAt:new Date().toISOString()}),_((Y)=>{let p=[...S0(Y.events).filter((m)=>String(m?.eventId||"")!==String(V?.eventId||"")),V].sort((m,X)=>Number(m?.sequence||0)-Number(X?.sequence||0)).slice(-100),O=V?.type==="trace-stats-updated"&&IZ(V?.payload?.stats)?[V.payload.stats,...S0(Y.stats).filter((m)=>String(m?.scopeId||"")!==String(V.payload.stats.scopeId||""))].slice(0,100):Y.stats;return{...Y,events:p,stats:O}})}catch(V){A({status:"warn",message:Hu(V,"SSE 事件解析失败"),lastEventAt:new Date().toISOString()})}},D=()=>{A((h)=>({...h,status:"warn",message:"SSE reconnecting"}))};return Z.addEventListener("hello",H),Z.addEventListener("task-updated",E),Z.addEventListener("queue-updated",E),Z.addEventListener("trace-step-created",E),Z.addEventListener("trace-stats-snapshot",E),Z.addEventListener("trace-stats-updated",E),Z.addEventListener("trace-error",E),Z.onerror=D,()=>Z.close()},[r?.id,l,c]),!r)return iu($A,{title:"OA Event Flow 未登记",text:"请在 config.json 的 microservices 中登记 id=oa-event-flow"});let F=sZ(r),U=aZ(r),Q=y.diagnostics||{},L=y.health||{},w=Q.eventCount??L.eventCount,J=Q.traceStatsCount??L.traceStatsCount,N=Q.latestSequence??L.latestSequence,q=Q.pipelineBridge||L.pipelineBridge||{},W=S0(Q.eventTypes).slice(0,8);return iu("div",{className:"oa-event-flow-page","data-testid":"oa-event-flow-page"},iu(l6,{title:"OA Event Flow 控制台",eyebrow:"Unified OA Event Bus + Stats Projection",loading:y.loading,actions:iu("div",{className:"panel-actions"},iu("button",{type:"button",className:"ghost-btn",onClick:j,disabled:y.loading,"data-testid":"oa-event-flow-refresh"},y.loading?"刷新中":"刷新"),iu(k_,{title:"OA Event Flow Service",data:r,onOpen:f,testId:"raw-oa-event-flow-service"}))},iu("div",{className:"oa-flow-hero"},iu("div",null,iu("div",{className:"node-version-line"},iu(n6,{status:L?.ok||F.providerStatus==="online"?"online":"warn"},L?.ok?"HEALTH OK":F.providerStatus||"unknown"),iu(n6,{status:$.status},$.status.toUpperCase()),iu("span",null,U.public?"公网暴露":"仅 UniDesk frontend 代理访问")),iu("p",{className:"muted paragraph"},"独立事件流微服务统一承载 Code Queue 与 Pipeline 的事件发布、tag 订阅、事件表审计和 Trace/STEP 统计投影。")),iu("div",{className:"oa-flow-signal"},iu("span",null,"stream"),iu("strong",null,$.message||"--"),iu("code",null,$.lastEventAt?tf(new Date($.lastEventAt)):"waiting"))),iu(yf,{error:y.error,wide:!0})),iu("div",{className:"oa-flow-metrics"},iu(v_,{label:"事件总量",value:kl(w),hint:`latest seq ${kl(N)}`,tone:"ok"}),iu(v_,{label:"Trace Stats",value:kl(J),hint:"oa_trace_stats 投影"}),iu(v_,{label:"SSE Clients",value:kl(L?.sseClientCount??S0(Q.sseClients).length),hint:$.message||"tag subscription"}),iu(v_,{label:"Pipeline Bridge",value:q?.enabled?kl(q?.insertedCount):"OFF",hint:q?.lastError||q?.lastFinishedAt||`${q?.mode||"snapshot"} service:pipeline`}),iu(v_,{label:"DB",value:L?.databaseReady||Q.databaseReady?"READY":"WAIT",hint:L?.databaseLastError||Q.databaseLastError||"PostgreSQL persisted"})),iu(l6,{title:"标签订阅",eyebrow:y.refreshedAt?`Updated ${tf(y.refreshedAt)}`:"Tag Pub/Sub"},iu("div",{className:"oa-filter-bar"},iu("label",null,iu("span",null,"tags"),iu("input",{value:n,onChange:(z)=>i(z.target.value),placeholder:"service:code-queue, trace","data-testid":"oa-event-flow-tag-filter"})),iu("div",{className:"oa-filter-presets"},iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("service:code-queue")},"Code Queue"),iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("service:pipeline")},"Pipeline"),iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("trace")},"Trace"),iu("button",{type:"button",className:"ghost-btn",onClick:()=>i("")},"All")),iu("code",null,c||"all events")),iu("div",{className:"oa-type-strip"},W.length===0?iu("span",{className:"muted"},"等待事件类型统计"):W.map((z)=>iu("span",{key:z.type,className:"data-chip"},`${z.type} ${kl(z.count)}`)))),iu("div",{className:"oa-flow-grid"},iu(l6,{title:"事件表",eyebrow:"oa_events persisted log",className:"oa-flow-wide",loading:y.loading,actions:iu(k_,{title:"OA Event Query",data:{events:y.events,diagnostics:Q},onOpen:f,testId:"raw-oa-events"})},iu(fO,{events:y.events,onRaw:f})),iu(l6,{title:"统计中心",eyebrow:"oa_trace_stats read model",className:"oa-flow-wide",loading:y.loading,actions:iu(k_,{title:"OA Trace Stats",data:y.stats,onOpen:f,testId:"raw-oa-trace-stats"})},iu(lO,{stats:y.stats,onRaw:f}))))}var Mn=Pu(qf(),1);var ru=Pu(aQ(),1),yu=Pu(qf(),1);function Yf(u){if(typeof u==="string"||typeof u==="number")return""+u;let f="";if(Array.isArray(u)){for(let l=0,r;l{}};function dQ(){for(var u=0,f=arguments.length,l={},r;u=0)r=l.slice(n+1),l=l.slice(0,n);if(l&&!f.hasOwnProperty(l))throw Error("unknown type: "+l);return{type:l,name:r}})}_6.prototype=dQ.prototype={constructor:_6,on:function(u,f){var l=this._,r=AO(u+"",l),n,i=-1,y=r.length;if(arguments.length<2){while(++i0)for(var l=Array(n),r=0,n,i;r=0&&(f=u.slice(0,l))!=="xmlns")u=u.slice(l+1);return tA.hasOwnProperty(f)?{space:tA[f],local:u}:u}function AA(u){let f;while(f=u.sourceEvent)u=f;return u}function Kl(u,f){if(u=AA(u),f===void 0)f=u.currentTarget;if(f){var l=f.ownerSVGElement||f;if(l.createSVGPoint){var r=l.createSVGPoint();return r.x=u.clientX,r.y=u.clientY,r=r.matrixTransform(f.getScreenCTM().inverse()),[r.x,r.y]}if(f.getBoundingClientRect){var n=f.getBoundingClientRect();return[u.clientX-n.left-f.clientLeft,u.clientY-n.top-f.clientTop]}}return[u.pageX,u.pageY]}function jO(){}function En(u){return u==null?jO:function(){return this.querySelector(u)}}function cA(u){if(typeof u!=="function")u=En(u);for(var f=this._groups,l=f.length,r=Array(l),n=0;n=q)q=N+1;while(!(z=w[q])&&++q=0;)if(y=r[n]){if(i&&y.compareDocumentPosition(i)^4)i.parentNode.insertBefore(y,i);i=y}return this}function zA(u){if(!u)u=TO;function f(j,F){return j&&F?u(j.__data__,F.__data__):!j-!F}for(var l=this._groups,r=l.length,n=Array(r),i=0;if?1:u>=f?0:NaN}function TA(){var u=arguments[0];return arguments[0]=this,u.apply(null,arguments),this}function EA(){return Array.from(this)}function ZA(){for(var u=this._groups,f=0,l=u.length;f1?this.each((f==null?DO:typeof f==="function"?YO:XO)(u,f,l==null?"":l)):Zn(this.node(),u)}function Zn(u,f){return u.style.getPropertyValue(f)||s_(u).getComputedStyle(u,null).getPropertyValue(f)}function SO(u){return function(){delete this[u]}}function pO(u,f){return function(){this[u]=f}}function mO(u,f){return function(){var l=f.apply(this,arguments);if(l==null)delete this[u];else this[u]=l}}function XA(u,f){return arguments.length>1?this.each((f==null?SO:typeof f==="function"?mO:pO)(u,f)):this.node()[u]}function eQ(u){return u.trim().split(/^|\s+/)}function YA(u){return u.classList||new uq(u)}function uq(u){this._node=u,this._names=eQ(u.getAttribute("class")||"")}uq.prototype={add:function(u){var f=this._names.indexOf(u);if(f<0)this._names.push(u),this._node.setAttribute("class",this._names.join(" "))},remove:function(u){var f=this._names.indexOf(u);if(f>=0)this._names.splice(f,1),this._node.setAttribute("class",this._names.join(" "))},contains:function(u){return this._names.indexOf(u)>=0}};function fq(u,f){var l=YA(u),r=-1,n=f.length;while(++r=0)l=f.slice(r+1),f=f.slice(0,r);return{type:f,name:l}})}function rH(u){return function(){var f=this.__on;if(!f)return;for(var l=0,r=-1,n=f.length,i;l()=>u;function e_(u,{sourceEvent:f,subject:l,target:r,identifier:n,active:i,x:y,y:_,dx:$,dy:A,dispatch:c}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:f,enumerable:!0,configurable:!0},subject:{value:l,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:n,enumerable:!0,configurable:!0},active:{value:i,enumerable:!0,configurable:!0},x:{value:y,enumerable:!0,configurable:!0},y:{value:_,enumerable:!0,configurable:!0},dx:{value:$,enumerable:!0,configurable:!0},dy:{value:A,enumerable:!0,configurable:!0},_:{value:c}})}e_.prototype.on=function(){var u=this._.on.apply(this._,arguments);return u===this._?this:u};function UH(u){return!u.ctrlKey&&!u.button}function QH(){return this.parentNode}function qH(u,f){return f==null?{x:u.x,y:u.y}:f}function NH(){return navigator.maxTouchPoints||"ontouchstart"in this}function u$(){var u=UH,f=QH,l=qH,r=NH,n={},i=z1("start","drag","end"),y=0,_,$,A,c,j=0;function F(W){W.on("mousedown.drag",U).filter(r).on("touchstart.drag",w).on("touchmove.drag",J,iq).on("touchend.drag touchcancel.drag",N).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function U(W,z){if(c||!u.call(this,W,z))return;var Z=q(this,f.call(this,W,z),W,z,"mouse");if(!Z)return;af(W.view).on("mousemove.drag",Q,T1).on("mouseup.drag",L,T1),ki(W.view),A6(W),A=!1,_=W.clientX,$=W.clientY,Z("start",W)}function Q(W){if(m0(W),!A){var z=W.clientX-_,Z=W.clientY-$;A=z*z+Z*Z>j}n.mouse("drag",W)}function L(W){af(W.view).on("mousemove.drag mouseup.drag",null),o_(W.view,A),m0(W),n.mouse("end",W)}function w(W,z){if(!u.call(this,W,z))return;var Z=W.changedTouches,H=f.call(this,W,z),E=Z.length,D,h;for(D=0;D>8&15|f>>4&240,f>>4&15|f&240,(f&15)<<4|f&15,1):l===8?c6(f>>24&255,f>>16&255,f>>8&255,(f&255)/255):l===4?c6(f>>12&15|f>>8&240,f>>8&15|f>>4&240,f>>4&15|f&240,((f&15)<<4|f&15)/255):null):(f=LH.exec(u))?new Il(f[1],f[2],f[3],1):(f=wH.exec(u))?new Il(f[1]*255/100,f[2]*255/100,f[3]*255/100,1):(f=KH.exec(u))?c6(f[1],f[2],f[3],f[4]):(f=GH.exec(u))?c6(f[1]*255/100,f[2]*255/100,f[3]*255/100,f[4]):(f=zH.exec(u))?jq(f[1],f[2]/100,f[3]/100,1):(f=TH.exec(u))?jq(f[1],f[2]/100,f[3]/100,f[4]):yq.hasOwnProperty(u)?tq(yq[u]):u==="transparent"?new Il(NaN,NaN,NaN,0):null}function tq(u){return new Il(u>>16&255,u>>8&255,u&255,1)}function c6(u,f,l,r){if(r<=0)u=f=l=NaN;return new Il(u,f,l,r)}function OH(u){if(!(u instanceof n$))u=vr(u);if(!u)return new Il;return u=u.rgb(),new Il(u.r,u.g,u.b,u.opacity)}function gi(u,f,l,r){return arguments.length===1?OH(u):new Il(u,f,l,r==null?1:r)}function Il(u,f,l,r){this.r=+u,this.g=+f,this.b=+l,this.opacity=+r}f$(Il,gi,sA(n$,{brighter(u){return u=u==null?F6:Math.pow(F6,u),new Il(this.r*u,this.g*u,this.b*u,this.opacity)},darker(u){return u=u==null?l$:Math.pow(l$,u),new Il(this.r*u,this.g*u,this.b*u,this.opacity)},rgb(){return this},clamp(){return new Il(Z1(this.r),Z1(this.g),Z1(this.b),J6(this.opacity))},displayable(){return-0.5<=this.r&&this.r<255.5&&(-0.5<=this.g&&this.g<255.5)&&(-0.5<=this.b&&this.b<255.5)&&(0<=this.opacity&&this.opacity<=1)},hex:Aq,formatHex:Aq,formatHex8:HH,formatRgb:cq,toString:cq}));function Aq(){return`#${E1(this.r)}${E1(this.g)}${E1(this.b)}`}function HH(){return`#${E1(this.r)}${E1(this.g)}${E1(this.b)}${E1((isNaN(this.opacity)?1:this.opacity)*255)}`}function cq(){let u=J6(this.opacity);return`${u===1?"rgb(":"rgba("}${Z1(this.r)}, ${Z1(this.g)}, ${Z1(this.b)}${u===1?")":`, ${u})`}`}function J6(u){return isNaN(u)?1:Math.max(0,Math.min(1,u))}function Z1(u){return Math.max(0,Math.min(255,Math.round(u)||0))}function E1(u){return u=Z1(u),(u<16?"0":"")+u.toString(16)}function jq(u,f,l,r){if(r<=0)u=f=l=NaN;else if(l<=0||l>=1)u=f=NaN;else if(f<=0)u=NaN;return new br(u,f,l,r)}function Jq(u){if(u instanceof br)return new br(u.h,u.s,u.l,u.opacity);if(!(u instanceof n$))u=vr(u);if(!u)return new br;if(u instanceof br)return u;u=u.rgb();var f=u.r/255,l=u.g/255,r=u.b/255,n=Math.min(f,l,r),i=Math.max(f,l,r),y=NaN,_=i-n,$=(i+n)/2;if(_){if(f===i)y=(l-r)/_+(l0&&$<1?0:y;return new br(y,_,$,u.opacity)}function Uq(u,f,l,r){return arguments.length===1?Jq(u):new br(u,f,l,r==null?1:r)}function br(u,f,l,r){this.h=+u,this.s=+f,this.l=+l,this.opacity=+r}f$(br,Uq,sA(n$,{brighter(u){return u=u==null?F6:Math.pow(F6,u),new br(this.h,this.s,this.l*u,this.opacity)},darker(u){return u=u==null?l$:Math.pow(l$,u),new br(this.h,this.s,this.l*u,this.opacity)},rgb(){var u=this.h%360+(this.h<0)*360,f=isNaN(u)||isNaN(this.s)?0:this.s,l=this.l,r=l+(l<0.5?l:1-l)*f,n=2*l-r;return new Il(aA(u>=240?u-240:u+120,n,r),aA(u,n,r),aA(u<120?u+240:u-120,n,r),this.opacity)},clamp(){return new br(Fq(this.h),j6(this.s),j6(this.l),J6(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&(0<=this.l&&this.l<=1)&&(0<=this.opacity&&this.opacity<=1)},formatHsl(){let u=J6(this.opacity);return`${u===1?"hsl(":"hsla("}${Fq(this.h)}, ${j6(this.s)*100}%, ${j6(this.l)*100}%${u===1?")":`, ${u})`}`}}));function Fq(u){return u=(u||0)%360,u<0?u+360:u}function j6(u){return Math.max(0,Math.min(1,u||0))}function aA(u,f,l){return(u<60?f+(l-f)*u/60:u<180?l:u<240?f+(l-f)*(240-u)/60:f)*255}function oA(u,f,l,r,n){var i=u*u,y=i*u;return((1-3*u+3*i-y)*f+(4-6*i+3*y)*l+(1+3*u+3*i-3*y)*r+y*n)/6}function dA(u){var f=u.length-1;return function(l){var r=l<=0?l=0:l>=1?(l=1,f-1):Math.floor(l*f),n=u[r],i=u[r+1],y=r>0?u[r-1]:2*n-i,_=r()=>u;function VH(u,f){return function(l){return u+l*f}}function DH(u,f,l){return u=Math.pow(u,l),f=Math.pow(f,l)-u,l=1/l,function(r){return Math.pow(u+r*f,l)}}function Qq(u){return(u=+u)===1?Q6:function(f,l){return l-f?DH(f,l,u):i$(isNaN(f)?l:f)}}function Q6(u,f){var l=f-u;return l?VH(u,l):i$(isNaN(u)?f:u)}var O1=function u(f){var l=Qq(f);function r(n,i){var y=l((n=gi(n)).r,(i=gi(i)).r),_=l(n.g,i.g),$=l(n.b,i.b),A=Q6(n.opacity,i.opacity);return function(c){return n.r=y(c),n.g=_(c),n.b=$(c),n.opacity=A(c),n+""}}return r.gamma=u,r}(1);function qq(u){return function(f){var l=f.length,r=Array(l),n=Array(l),i=Array(l),y,_;for(y=0;yl)if(i=f.slice(l,i),_[y])_[y]+=i;else _[++y]=i;if((r=r[0])===(n=n[0]))if(_[y])_[y]+=n;else _[++y]=n;else _[++y]=null,$.push({i:y,x:Gl(r,n)});l=rc.lastIndex}if(l180)c+=360;else if(c-A>180)A+=360;F.push({i:j.push(n(j)+"rotate(",null,r)-2,x:Gl(A,c)})}else if(c)j.push(n(j)+"rotate("+c+r)}function _(A,c,j,F){if(A!==c)F.push({i:j.push(n(j)+"skewX(",null,r)-2,x:Gl(A,c)});else if(c)j.push(n(j)+"skewX("+c+r)}function $(A,c,j,F,U,Q){if(A!==j||c!==F){var L=U.push(n(U)+"scale(",null,",",null,")");Q.push({i:L-4,x:Gl(A,j)},{i:L-2,x:Gl(c,F)})}else if(j!==1||F!==1)U.push(n(U)+"scale("+j+","+F+")")}return function(A,c){var j=[],F=[];return A=u(A),c=u(c),i(A.translateX,A.translateY,c.translateX,c.translateY,j,F),y(A.rotate,c.rotate,j,F),_(A.skewX,c.skewX,j,F),$(A.scaleX,A.scaleY,c.scaleX,c.scaleY,j,F),A=c=null,function(U){var Q=-1,L=F.length,w;while(++Q=0)u._call.call(void 0,f);u=u._next}--ai}function Oq(){B1=(w6=t$.now())+K6,ai=_$=0;try{Vq()}finally{ai=0,uB(),B1=0}}function eH(){var u=t$.now(),f=u-w6;if(f>Hq)K6-=f,w6=u}function uB(){var u,f=L6,l,r=1/0;while(f)if(f._call){if(r>f._time)r=f._time;u=f,f=f._next}else l=f._next,f._next=null,f=u?u._next=l:L6=l;$$=u,_c(r)}function _c(u){if(ai)return;if(_$)_$=clearTimeout(_$);var f=u-B1;if(f>24){if(u<1/0)_$=setTimeout(Oq,u-t$.now()-K6);if(y$)y$=clearInterval(y$)}else{if(!y$)w6=t$.now(),y$=setInterval(eH,Hq);ai=1,Bq(Oq)}}function j$(u,f,l){var r=new A$;return f=f==null?0:+f,r.restart((n)=>{r.stop(),u(n+f)},f,l),r}var lB=z1("start","end","cancel","interrupt"),rB=[],Yq=0,Dq=1,T6=2,z6=3,Xq=4,E6=5,F$=6;function P0(u,f,l,r,n,i){var y=u.__transition;if(!y)u.__transition={};else if(l in y)return;nB(u,l,{name:f,index:r,group:n,on:lB,tween:rB,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:Yq})}function J$(u,f){var l=of(u,f);if(l.state>Yq)throw Error("too late; already scheduled");return l}function Fl(u,f){var l=of(u,f);if(l.state>z6)throw Error("too late; already running");return l}function of(u,f){var l=u.__transition;if(!l||!(l=l[f]))throw Error("transition not found");return l}function nB(u,f,l){var r=u.__transition,n;r[f]=l,l.timer=G6(i,0,l.time);function i(A){if(l.state=Dq,l.timer.restart(y,l.delay,l.time),l.delay<=A)y(A-l.delay)}function y(A){var c,j,F,U;if(l.state!==Dq)return $();for(c in r){if(U=r[c],U.name!==l.name)continue;if(U.state===z6)return j$(y);if(U.state===Xq)U.state=F$,U.timer.stop(),U.on.call("interrupt",u,u.__data__,U.index,U.group),delete r[c];else if(+cT6&&r.state=0)f=f.slice(0,l);return!f||f==="start"})}function zB(u,f,l){var r,n,i=GB(f)?J$:Fl;return function(){var y=i(this,u),_=y.on;if(_!==r)(n=(r=_).copy()).on(f,l);y.on=n}}function Nc(u,f){var l=this._id;return arguments.length<2?of(this.node(),l).on.on(u):this.each(zB(l,u,f))}function TB(u){return function(){var f=this.parentNode;for(var l in this.__transition)if(+l!==u)return;if(f)f.removeChild(this)}}function Wc(){return this.on("end.remove",TB(this._id))}function Lc(u){var f=this._name,l=this._id;if(typeof u!=="function")u=En(u);for(var r=this._groups,n=r.length,i=Array(n),y=0;y()=>u;function Bc(u,{sourceEvent:f,target:l,transform:r,dispatch:n}){Object.defineProperties(this,{type:{value:u,enumerable:!0,configurable:!0},sourceEvent:{value:f,enumerable:!0,configurable:!0},target:{value:l,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:n}})}function kr(u,f,l){this.k=u,this.x=f,this.y=l}kr.prototype={constructor:kr,scale:function(u){return u===1?this:new kr(this.k*u,this.x,this.y)},translate:function(u,f){return u===0&f===0?this:new kr(this.k,this.x+this.k*u,this.y+this.k*f)},apply:function(u){return[u[0]*this.k+this.x,u[1]*this.k+this.y]},applyX:function(u){return u*this.k+this.x},applyY:function(u){return u*this.k+this.y},invert:function(u){return[(u[0]-this.x)/this.k,(u[1]-this.y)/this.k]},invertX:function(u){return(u-this.x)/this.k},invertY:function(u){return(u-this.y)/this.k},rescaleX:function(u){return u.copy().domain(u.range().map(this.invertX,this).map(u.invert,u))},rescaleY:function(u){return u.copy().domain(u.range().map(this.invertY,this).map(u.invert,u))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var V1=new kr(1,0,0);q$.prototype=kr.prototype;function q$(u){while(!u.__zoom)if(!(u=u.parentNode))return V1;return u.__zoom}function m6(u){u.stopImmediatePropagation()}function D1(u){u.preventDefault(),u.stopImmediatePropagation()}function RB(u){return(!u.ctrlKey||u.type==="wheel")&&!u.button}function xB(){var u=this;if(u instanceof SVGElement){if(u=u.ownerSVGElement||u,u.hasAttribute("viewBox"))return u=u.viewBox.baseVal,[[u.x,u.y],[u.x+u.width,u.y+u.height]];return[[0,0],[u.width.baseVal.value,u.height.baseVal.value]]}return[[0,0],[u.clientWidth,u.clientHeight]]}function mq(){return this.__zoom||V1}function hB(u){return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*(u.ctrlKey?10:1)}function bB(){return navigator.maxTouchPoints||"ontouchstart"in this}function vB(u,f,l){var r=u.invertX(f[0][0])-l[0][0],n=u.invertX(f[1][0])-l[1][0],i=u.invertY(f[0][1])-l[0][1],y=u.invertY(f[1][1])-l[1][1];return u.translate(n>r?(r+n)/2:Math.min(0,r)||Math.max(0,n),y>i?(i+y)/2:Math.min(0,i)||Math.max(0,y))}function N$(){var u=RB,f=xB,l=vB,r=hB,n=bB,i=[0,1/0],y=[[-1/0,-1/0],[1/0,1/0]],_=250,$=H1,A=z1("start","zoom","end"),c,j,F,U=500,Q=150,L=0,w=10;function J(O){O.property("__zoom",mq).on("wheel.zoom",E,{passive:!1}).on("mousedown.zoom",D).on("dblclick.zoom",h).filter(n).on("touchstart.zoom",V).on("touchmove.zoom",Y).on("touchend.zoom touchcancel.zoom",p).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}J.transform=function(O,m,X,v){var T=O.selection?O.selection():O;if(T.property("__zoom",mq),O!==T)z(O,m,X,v);else T.interrupt().each(function(){Z(this,arguments).event(v).start().zoom(null,typeof m==="function"?m.apply(this,arguments):m).end()})},J.scaleBy=function(O,m,X,v){J.scaleTo(O,function(){var T=this.__zoom.k,S=typeof m==="function"?m.apply(this,arguments):m;return T*S},X,v)},J.scaleTo=function(O,m,X,v){J.transform(O,function(){var T=f.apply(this,arguments),S=this.__zoom,k=X==null?W(T):typeof X==="function"?X.apply(this,arguments):X,I=S.invert(k),b=typeof m==="function"?m.apply(this,arguments):m;return l(q(N(S,b),k,I),T,y)},X,v)},J.translateBy=function(O,m,X,v){J.transform(O,function(){return l(this.__zoom.translate(typeof m==="function"?m.apply(this,arguments):m,typeof X==="function"?X.apply(this,arguments):X),f.apply(this,arguments),y)},null,v)},J.translateTo=function(O,m,X,v,T){J.transform(O,function(){var S=f.apply(this,arguments),k=this.__zoom,I=v==null?W(S):typeof v==="function"?v.apply(this,arguments):v;return l(V1.translate(I[0],I[1]).scale(k.k).translate(typeof m==="function"?-m.apply(this,arguments):-m,typeof X==="function"?-X.apply(this,arguments):-X),S,y)},v,T)};function N(O,m){return m=Math.max(i[0],Math.min(i[1],m)),m===O.k?O:new kr(m,O.x,O.y)}function q(O,m,X){var v=m[0]-X[0]*O.k,T=m[1]-X[1]*O.k;return v===O.x&&T===O.y?O:new kr(O.k,v,T)}function W(O){return[(+O[0][0]+ +O[1][0])/2,(+O[0][1]+ +O[1][1])/2]}function z(O,m,X,v){O.on("start.zoom",function(){Z(this,arguments).event(v).start()}).on("interrupt.zoom end.zoom",function(){Z(this,arguments).event(v).end()}).tween("zoom",function(){var T=this,S=arguments,k=Z(T,S).event(v),I=f.apply(T,S),b=X==null?W(I):typeof X==="function"?X.apply(T,S):X,o=Math.max(I[1][0]-I[0][0],I[1][1]-I[0][1]),s=T.__zoom,x=typeof m==="function"?m.apply(T,S):m,fu=$(s.invert(b).concat(o/s.k),x.invert(b).concat(o/x.k));return function($u){if($u===1)$u=x;else{var tu=fu($u),ju=o/tu[2];$u=new kr(ju,b[0]-tu[0]*ju,b[1]-tu[1]*ju)}k.zoom(null,$u)}})}function Z(O,m,X){return!X&&O.__zooming||new H(O,m)}function H(O,m){this.that=O,this.args=m,this.active=0,this.sourceEvent=null,this.extent=f.apply(O,m),this.taps=0}H.prototype={event:function(O){if(O)this.sourceEvent=O;return this},start:function(){if(++this.active===1)this.that.__zooming=this,this.emit("start");return this},zoom:function(O,m){if(this.mouse&&O!=="mouse")this.mouse[1]=m.invert(this.mouse[0]);if(this.touch0&&O!=="touch")this.touch0[1]=m.invert(this.touch0[0]);if(this.touch1&&O!=="touch")this.touch1[1]=m.invert(this.touch1[0]);return this.that.__zoom=m,this.emit("zoom"),this},end:function(){if(--this.active===0)delete this.that.__zooming,this.emit("end");return this},emit:function(O){var m=af(this.that).datum();A.call(O,this.that,new Bc(O,{sourceEvent:this.sourceEvent,target:J,type:O,transform:this.that.__zoom,dispatch:A}),m)}};function E(O,...m){if(!u.apply(this,arguments))return;var X=Z(this,m).event(O),v=this.__zoom,T=Math.max(i[0],Math.min(i[1],v.k*Math.pow(2,r.apply(this,arguments)))),S=Kl(O);if(X.wheel){if(X.mouse[0][0]!==S[0]||X.mouse[0][1]!==S[1])X.mouse[1]=v.invert(X.mouse[0]=S);clearTimeout(X.wheel)}else if(v.k===T)return;else X.mouse=[S,v.invert(S)],On(this),X.start();D1(O),X.wheel=setTimeout(k,Q),X.zoom("mouse",l(q(N(v,T),X.mouse[0],X.mouse[1]),X.extent,y));function k(){X.wheel=null,X.end()}}function D(O,...m){if(F||!u.apply(this,arguments))return;var X=O.currentTarget,v=Z(this,m,!0).event(O),T=af(O.view).on("mousemove.zoom",b,!0).on("mouseup.zoom",o,!0),S=Kl(O,X),k=O.clientX,I=O.clientY;ki(O.view),m6(O),v.mouse=[S,this.__zoom.invert(S)],On(this),v.start();function b(s){if(D1(s),!v.moved){var x=s.clientX-k,fu=s.clientY-I;v.moved=x*x+fu*fu>L}v.event(s).zoom("mouse",l(q(v.that.__zoom,v.mouse[0]=Kl(s,X),v.mouse[1]),v.extent,y))}function o(s){T.on("mousemove.zoom mouseup.zoom",null),o_(s.view,v.moved),D1(s),v.event(s).end()}}function h(O,...m){if(!u.apply(this,arguments))return;var X=this.__zoom,v=Kl(O.changedTouches?O.changedTouches[0]:O,this),T=X.invert(v),S=X.k*(O.shiftKey?0.5:2),k=l(q(N(X,S),v,T),f.apply(this,m),y);if(D1(O),_>0)af(this).transition().duration(_).call(z,k,v,O);else af(this).call(J.transform,k,v,O)}function V(O,...m){if(!u.apply(this,arguments))return;var X=O.touches,v=X.length,T=Z(this,m,O.changedTouches.length===v).event(O),S,k,I,b;m6(O);for(k=0;k"[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001",error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:(u)=>`Node type "${u}" not found. Using fallback type "default".`,error004:()=>"The React Flow parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:(u)=>`The old edge with id=${u} does not exist.`,error009:(u)=>`Marker type "${u}" doesn't exist.`,error008:(u,{id:f,sourceHandle:l,targetHandle:r})=>`Couldn't create edge for ${u} handle id: "${u==="source"?l:r}", edge id: ${f}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:(u)=>`Edge type "${u}" not found. Using fallback type "default".`,error012:(u)=>`Node with id "${u}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(u="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${u}/dist/style.css' or base.css to make sure everything is working properly.`,error014:()=>"useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.",error015:()=>"It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs."},ly=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],Sc=["Enter"," ","Escape"],pc={"node.a11yDescription.default":"Press enter or space to select a node. Press delete to remove it and escape to cancel.","node.a11yDescription.keyboardDisabled":"Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.","node.a11yDescription.ariaLiveMessage":({direction:u,x:f,y:l})=>`Moved selected node ${u}. New position, x: ${f}, y: ${l}`,"edge.a11yDescription.default":"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.","controls.ariaLabel":"Control Panel","controls.zoomIn.ariaLabel":"Zoom In","controls.zoomOut.ariaLabel":"Zoom Out","controls.fitView.ariaLabel":"Fit View","controls.interactive.ariaLabel":"Toggle Interactivity","minimap.ariaLabel":"Mini Map","handle.ariaLabel":"Handle"},Vn;(function(u){u.Strict="strict",u.Loose="loose"})(Vn||(Vn={}));var C0;(function(u){u.Free="free",u.Vertical="vertical",u.Horizontal="horizontal"})(C0||(C0={}));var X1;(function(u){u.Partial="partial",u.Full="full"})(X1||(X1={}));var mc={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null},$0;(function(u){u.Bezier="default",u.Straight="straight",u.Step="step",u.SmoothStep="smoothstep",u.SimpleBezier="simplebezier"})($0||($0={}));var Dn;(function(u){u.Arrow="arrow",u.ArrowClosed="arrowclosed"})(Dn||(Dn={}));var wu;(function(u){u.Left="left",u.Top="top",u.Right="right",u.Bottom="bottom"})(wu||(wu={}));var Pq={[wu.Left]:wu.Right,[wu.Right]:wu.Left,[wu.Top]:wu.Bottom,[wu.Bottom]:wu.Top};function Pc(u){return u===null?null:u?"valid":"invalid"}var Mc=(u)=>("id"in u)&&("source"in u)&&("target"in u),oq=(u)=>("id"in u)&&("position"in u)&&!("source"in u)&&!("target"in u),Cc=(u)=>("id"in u)&&("internals"in u)&&!("source"in u)&&!("target"in u);var w$=(u,f=[0,0])=>{let{width:l,height:r}=t0(u),n=u.origin??f,i=l*n[0],y=r*n[1];return{x:u.position.x-i,y:u.position.y-y}},Rc=(u,f={nodeOrigin:[0,0]})=>{if(u.length===0)return{x:0,y:0,width:0,height:0};let l=u.reduce((r,n)=>{let i=typeof n==="string",y=!f.nodeLookup&&!i?n:void 0;if(f.nodeLookup)y=i?f.nodeLookup.get(n):!Cc(n)?f.nodeLookup.get(n.id):n;let _=y?C6(y,f.nodeOrigin):{x:0,y:0,x2:0,y2:0};return x6(r,_)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return h6(l)},ry=(u,f={})=>{let l={x:1/0,y:1/0,x2:-1/0,y2:-1/0},r=!1;return u.forEach((n)=>{if(f.filter===void 0||f.filter(n))l=x6(l,C6(n)),r=!0}),r?h6(l):{x:0,y:0,width:0,height:0}},R6=(u,f,[l,r,n]=[0,0,1],i=!1,y=!1)=>{let _={...yy(f,[l,r,n]),width:f.width/n,height:f.height/n},$=[];for(let A of u.values()){let{measured:c,selectable:j=!0,hidden:F=!1}=A;if(y&&!j||F)continue;let U=c.width??A.width??A.initialWidth??null,Q=c.height??A.height??A.initialHeight??null,L=ny(_,S1(A)),w=(U??0)*(Q??0),J=i&&L>0;if(!A.internals.handleBounds||J||L>=w||A.dragging)$.push(A)}return $},dq=(u,f)=>{let l=new Set;return u.forEach((r)=>{l.add(r.id)}),f.filter((r)=>l.has(r.source)||l.has(r.target))};function kB(u,f){let l=new Map,r=f?.nodes?new Set(f.nodes.map((n)=>n.id)):null;return u.forEach((n)=>{if(n.measured.width&&n.measured.height&&(f?.includeHiddenNodes||!n.hidden)&&(!r||r.has(n.id)))l.set(n.id,n)}),l}async function eq({nodes:u,width:f,height:l,panZoom:r,minZoom:n,maxZoom:i},y){if(u.size===0)return Promise.resolve(!0);let _=kB(u,y),$=ry(_),A=K$($,f,l,y?.minZoom??n,y?.maxZoom??i,y?.padding??0.1);return await r.setViewport(A,{duration:y?.duration,ease:y?.ease,interpolate:y?.interpolate}),Promise.resolve(!0)}function xc({nodeId:u,nextPosition:f,nodeLookup:l,nodeOrigin:r=[0,0],nodeExtent:n,onError:i}){let y=l.get(u),_=y.parentId?l.get(y.parentId):void 0,{x:$,y:A}=_?_.internals.positionAbsolute:{x:0,y:0},c=y.origin??r,j=y.extent||n;if(y.extent==="parent"&&!y.expandParent)if(!_)i?.("005",Fr.error005());else{let U=_.measured.width,Q=_.measured.height;if(U&&Q)j=[[$,A],[$+U,A+Q]]}else if(_&&fy(y.extent))j=[[y.extent[0][0]+$,y.extent[0][1]+A],[y.extent[1][0]+$,y.extent[1][1]+A]];let F=fy(j)?Y1(f,j,y.measured):f;if(y.measured.width===void 0||y.measured.height===void 0)i?.("015",Fr.error015());return{position:{x:F.x-$+(y.measured.width??0)*c[0],y:F.y-A+(y.measured.height??0)*c[1]},positionAbsolute:F}}async function uN({nodesToRemove:u=[],edgesToRemove:f=[],nodes:l,edges:r,onBeforeDelete:n}){let i=new Set(u.map((F)=>F.id)),y=[];for(let F of l){if(F.deletable===!1)continue;let U=i.has(F.id),Q=!U&&F.parentId&&y.find((L)=>L.id===F.parentId);if(U||Q)y.push(F)}let _=new Set(f.map((F)=>F.id)),$=r.filter((F)=>F.deletable!==!1),c=dq(y,$);for(let F of $)if(_.has(F.id)&&!c.find((Q)=>Q.id===F.id))c.push(F);if(!n)return{edges:c,nodes:y};let j=await n({nodes:y,edges:c});if(typeof j==="boolean")return j?{edges:c,nodes:y}:{edges:[],nodes:[]};return j}var uy=(u,f=0,l=1)=>Math.min(Math.max(u,f),l),Y1=(u={x:0,y:0},f,l)=>({x:uy(u.x,f[0][0],f[1][0]-(l?.width??0)),y:uy(u.y,f[0][1],f[1][1]-(l?.height??0))});function fN(u,f,l){let{width:r,height:n}=t0(l),{x:i,y}=l.internals.positionAbsolute;return Y1(u,[[i,y],[i+r,y+n]],f)}var Mq=(u,f,l)=>{if(ul)return-uy(Math.abs(u-l),1,f)/f;return 0},lN=(u,f,l=15,r=40)=>{let n=Mq(u.x,r,f.width-r)*l,i=Mq(u.y,r,f.height-r)*l;return[n,i]},x6=(u,f)=>({x:Math.min(u.x,f.x),y:Math.min(u.y,f.y),x2:Math.max(u.x2,f.x2),y2:Math.max(u.y2,f.y2)}),Yc=({x:u,y:f,width:l,height:r})=>({x:u,y:f,x2:u+l,y2:f+r}),h6=({x:u,y:f,x2:l,y2:r})=>({x:u,y:f,width:l-u,height:r-f}),S1=(u,f=[0,0])=>{let{x:l,y:r}=Cc(u)?u.internals.positionAbsolute:w$(u,f);return{x:l,y:r,width:u.measured?.width??u.width??u.initialWidth??0,height:u.measured?.height??u.height??u.initialHeight??0}},C6=(u,f=[0,0])=>{let{x:l,y:r}=Cc(u)?u.internals.positionAbsolute:w$(u,f);return{x:l,y:r,x2:l+(u.measured?.width??u.width??u.initialWidth??0),y2:r+(u.measured?.height??u.height??u.initialHeight??0)}},hc=(u,f)=>h6(x6(Yc(u),Yc(f))),ny=(u,f)=>{let l=Math.max(0,Math.min(u.x+u.width,f.x+f.width)-Math.max(u.x,f.x)),r=Math.max(0,Math.min(u.y+u.height,f.y+f.height)-Math.max(u.y,f.y));return Math.ceil(l*r)},bc=(u)=>Er(u.width)&&Er(u.height)&&Er(u.x)&&Er(u.y),Er=(u)=>!isNaN(u)&&isFinite(u),vc=(u,f)=>{},iy=(u,f=[1,1])=>{return{x:f[0]*Math.round(u.x/f[0]),y:f[1]*Math.round(u.y/f[1])}},yy=({x:u,y:f},[l,r,n],i=!1,y=[1,1])=>{let _={x:(u-l)/n,y:(f-r)/n};return i?iy(_,y):_},L$=({x:u,y:f},[l,r,n])=>{return{x:u*n+l,y:f*n+r}};function di(u,f){if(typeof u==="number")return Math.floor((f-f/(1+u))*0.5);if(typeof u==="string"&&u.endsWith("px")){let l=parseFloat(u);if(!Number.isNaN(l))return Math.floor(l)}if(typeof u==="string"&&u.endsWith("%")){let l=parseFloat(u);if(!Number.isNaN(l))return Math.floor(f*l*0.01)}return console.error(`[React Flow] The padding value "${u}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function IB(u,f,l){if(typeof u==="string"||typeof u==="number"){let r=di(u,l),n=di(u,f);return{top:r,right:n,bottom:r,left:n,x:n*2,y:r*2}}if(typeof u==="object"){let r=di(u.top??u.y??0,l),n=di(u.bottom??u.y??0,l),i=di(u.left??u.x??0,f),y=di(u.right??u.x??0,f);return{top:r,right:y,bottom:n,left:i,x:i+y,y:r+n}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function gB(u,f,l,r,n,i){let{x:y,y:_}=L$(u,[f,l,r]),{x:$,y:A}=L$({x:u.x+u.width,y:u.y+u.height},[f,l,r]),c=n-$,j=i-A;return{left:Math.floor(y),top:Math.floor(_),right:Math.floor(c),bottom:Math.floor(j)}}var K$=(u,f,l,r,n,i)=>{let y=IB(i,f,l),_=(f-y.x)/u.width,$=(l-y.y)/u.height,A=Math.min(_,$),c=uy(A,r,n),j=u.x+u.width/2,F=u.y+u.height/2,U=f/2-j*c,Q=l/2-F*c,L=gB(u,U,Q,c,f,l),w={left:Math.min(L.left-y.left,0),top:Math.min(L.top-y.top,0),right:Math.min(L.right-y.right,0),bottom:Math.min(L.bottom-y.bottom,0)};return{x:U-w.left+w.right,y:Q-w.top+w.bottom,zoom:c}},_y=()=>typeof navigator<"u"&&navigator?.userAgent?.indexOf("Mac")>=0;function fy(u){return u!==void 0&&u!==null&&u!=="parent"}function t0(u){return{width:u.measured?.width??u.width??u.initialWidth??0,height:u.measured?.height??u.height??u.initialHeight??0}}function kc(u){return(u.measured?.width??u.width??u.initialWidth)!==void 0&&(u.measured?.height??u.height??u.initialHeight)!==void 0}function Ic(u,f={width:0,height:0},l,r,n){let i={...u},y=r.get(l);if(y){let _=y.origin||n;i.x+=y.internals.positionAbsolute.x-(f.width??0)*_[0],i.y+=y.internals.positionAbsolute.y-(f.height??0)*_[1]}return i}function gc(u,f){if(u.size!==f.size)return!1;for(let l of u)if(!f.has(l))return!1;return!0}function rN(){let u,f;return{promise:new Promise((r,n)=>{u=r,f=n}),resolve:u,reject:f}}function nN(u){return{...pc,...u||{}}}function W$(u,{snapGrid:f=[0,0],snapToGrid:l=!1,transform:r,containerBounds:n}){let{x:i,y}=Zr(u),_=yy({x:i-(n?.left??0),y:y-(n?.top??0)},r),{x:$,y:A}=l?iy(_,f):_;return{xSnapped:$,ySnapped:A,..._}}var b6=(u)=>({width:u.offsetWidth,height:u.offsetHeight}),sc=(u)=>u?.getRootNode?.()||window?.document,sB=["INPUT","SELECT","TEXTAREA"];function ac(u){let f=u.composedPath?.()?.[0]||u.target;if(f?.nodeType!==1)return!1;return sB.includes(f.nodeName)||f.hasAttribute("contenteditable")||!!f.closest(".nokey")}var oc=(u)=>("clientX"in u),Zr=(u,f)=>{let l=oc(u),r=l?u.clientX:u.touches?.[0].clientX,n=l?u.clientY:u.touches?.[0].clientY;return{x:r-(f?.left??0),y:n-(f?.top??0)}},Cq=(u,f,l,r,n)=>{let i=f.querySelectorAll(`.${u}`);if(!i||!i.length)return null;return Array.from(i).map((y)=>{let _=y.getBoundingClientRect();return{id:y.getAttribute("data-handleid"),type:u,nodeId:n,position:y.getAttribute("data-handlepos"),x:(_.left-l.left)/r,y:(_.top-l.top)/r,...b6(y)}})};function v6({sourceX:u,sourceY:f,targetX:l,targetY:r,sourceControlX:n,sourceControlY:i,targetControlX:y,targetControlY:_}){let $=u*0.125+n*0.375+y*0.375+l*0.125,A=f*0.125+i*0.375+_*0.375+r*0.125,c=Math.abs($-u),j=Math.abs(A-f);return[$,A,c,j]}function P6(u,f){if(u>=0)return 0.5*u;return f*25*Math.sqrt(-u)}function Rq({pos:u,x1:f,y1:l,x2:r,y2:n,c:i}){switch(u){case wu.Left:return[f-P6(f-r,i),l];case wu.Right:return[f+P6(r-f,i),l];case wu.Top:return[f,l-P6(l-n,i)];case wu.Bottom:return[f,l+P6(n-l,i)]}}function k6({sourceX:u,sourceY:f,sourcePosition:l=wu.Bottom,targetX:r,targetY:n,targetPosition:i=wu.Top,curvature:y=0.25}){let[_,$]=Rq({pos:l,x1:u,y1:f,x2:r,y2:n,c:y}),[A,c]=Rq({pos:i,x1:r,y1:n,x2:u,y2:f,c:y}),[j,F,U,Q]=v6({sourceX:u,sourceY:f,targetX:r,targetY:n,sourceControlX:_,sourceControlY:$,targetControlX:A,targetControlY:c});return[`M${u},${f} C${_},${$} ${A},${c} ${r},${n}`,j,F,U,Q]}function dc({sourceX:u,sourceY:f,targetX:l,targetY:r}){let n=Math.abs(l-u)/2,i=l0}var aB=({source:u,sourceHandle:f,target:l,targetHandle:r})=>`xy-edge__${u}${f||""}-${l}${r||""}`,oB=(u,f)=>{return f.some((l)=>l.source===u.source&&l.target===u.target&&(l.sourceHandle===u.sourceHandle||!l.sourceHandle&&!u.sourceHandle)&&(l.targetHandle===u.targetHandle||!l.targetHandle&&!u.targetHandle))},ec=(u,f,l={})=>{if(!u.source||!u.target)return vc("006",Fr.error006()),f;let r=l.getEdgeId||aB,n;if(Mc(u))n={...u};else n={...u,id:r(u)};if(oB(n,f))return f;if(n.sourceHandle===null)delete n.sourceHandle;if(n.targetHandle===null)delete n.targetHandle;return f.concat(n)};function I6({sourceX:u,sourceY:f,targetX:l,targetY:r}){let[n,i,y,_]=dc({sourceX:u,sourceY:f,targetX:l,targetY:r});return[`M ${u},${f}L ${l},${r}`,n,i,y,_]}var xq={[wu.Left]:{x:-1,y:0},[wu.Right]:{x:1,y:0},[wu.Top]:{x:0,y:-1},[wu.Bottom]:{x:0,y:1}},dB=({source:u,sourcePosition:f=wu.Bottom,target:l})=>{if(f===wu.Left||f===wu.Right)return u.xMath.sqrt(Math.pow(f.x-u.x,2)+Math.pow(f.y-u.y,2));function eB({source:u,sourcePosition:f=wu.Bottom,target:l,targetPosition:r=wu.Top,center:n,offset:i,stepPosition:y}){let _=xq[f],$=xq[r],A={x:u.x+_.x*i,y:u.y+_.y*i},c={x:l.x+$.x*i,y:l.y+$.y*i},j=dB({source:A,sourcePosition:f,target:c}),F=j.x!==0?"x":"y",U=j[F],Q=[],L,w,J={x:0,y:0},N={x:0,y:0},[,,q,W]=dc({sourceX:u.x,sourceY:u.y,targetX:l.x,targetY:l.y});if(_[F]*$[F]===-1){if(F==="x")L=n.x??A.x+(c.x-A.x)*y,w=n.y??(A.y+c.y)/2;else L=n.x??(A.x+c.x)/2,w=n.y??A.y+(c.y-A.y)*y;let E=[{x:L,y:A.y},{x:L,y:c.y}],D=[{x:A.x,y:w},{x:c.x,y:w}];if(_[F]===U)Q=F==="x"?E:D;else Q=F==="x"?D:E}else{let E=[{x:A.x,y:c.y}],D=[{x:c.x,y:A.y}];if(F==="x")Q=_.x===U?D:E;else Q=_.y===U?E:D;if(f===r){let O=Math.abs(u[F]-l[F]);if(O<=i){let m=Math.min(i-1,i-O);if(_[F]===U)J[F]=(A[F]>u[F]?-1:1)*m;else N[F]=(c[F]>l[F]?-1:1)*m}}if(f!==r){let O=F==="x"?"y":"x",m=_[F]===$[O],X=A[O]>c[O],v=A[O]=p)L=(h.x+V.x)/2,w=Q[0].y;else L=Q[0].x,w=(h.y+V.y)/2}let z={x:A.x+J.x,y:A.y+J.y},Z={x:c.x+N.x,y:c.y+N.y};return[[u,...z.x!==Q[0].x||z.y!==Q[0].y?[z]:[],...Q,...Z.x!==Q[Q.length-1].x||Z.y!==Q[Q.length-1].y?[Z]:[],l],L,w,q,W]}function uV(u,f,l,r){let n=Math.min(hq(u,f)/2,hq(f,l)/2,r),{x:i,y}=f;if(u.x===i&&i===l.x||u.y===y&&y===l.y)return`L${i} ${y}`;if(u.y===y){let A=u.xl.id===f))||null}function g6(u,f){if(!u)return"";if(typeof u==="string")return u;return`${f?`${f}__`:""}${Object.keys(u).sort().map((r)=>`${r}=${u[r]}`).join("&")}`}function $N(u,{id:f,defaultColor:l,defaultMarkerStart:r,defaultMarkerEnd:n}){let i=new Set;return u.reduce((y,_)=>{return[_.markerStart||r,_.markerEnd||n].forEach(($)=>{if($&&typeof $==="object"){let A=g6($,f);if(!i.has(A))y.push({id:A,color:$.color||l,...$}),i.add(A)}}),y},[]).sort((y,_)=>y.id.localeCompare(_.id))}var tN=1000,fV=10,u9={nodeOrigin:[0,0],nodeExtent:ly,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},lV={...u9,checkEquality:!0};function f9(u,f){let l={...u};for(let r in f)if(f[r]!==void 0)l[r]=f[r];return l}function AN(u,f,l){let r=f9(u9,l);for(let n of u.values())if(n.parentId)r9(n,u,f,r);else{let i=w$(n,r.nodeOrigin),y=fy(n.extent)?n.extent:r.nodeExtent,_=Y1(i,y,t0(n));n.internals.positionAbsolute=_}}function rV(u,f){if(!u.handles)return!u.measured?void 0:f?.internals.handleBounds;let l=[],r=[];for(let n of u.handles){let i={id:n.id,width:n.width??1,height:n.height??1,nodeId:u.id,x:n.x,y:n.y,position:n.position,type:n.type};if(n.type==="source")l.push(i);else if(n.type==="target")r.push(i)}return{source:l,target:r}}function l9(u){return u==="manual"}function s6(u,f,l,r={}){let n=f9(lV,r),i={i:0},y=new Map(f),_=n?.elevateNodesOnSelect&&!l9(n.zIndexMode)?tN:0,$=u.length>0,A=!1;f.clear(),l.clear();for(let c of u){let j=y.get(c.id);if(n.checkEquality&&c===j?.internals.userNode)f.set(c.id,j);else{let F=w$(c,n.nodeOrigin),U=fy(c.extent)?c.extent:n.nodeExtent,Q=Y1(F,U,t0(c));j={...n.defaults,...c,measured:{width:c.measured?.width,height:c.measured?.height},internals:{positionAbsolute:Q,handleBounds:rV(c,j),z:cN(c,_,n.zIndexMode),userNode:c}},f.set(c.id,j)}if((j.measured===void 0||j.measured.width===void 0||j.measured.height===void 0)&&!j.hidden)$=!1;if(c.parentId)r9(j,f,l,r,i);A||=c.selected??!1}return{nodesInitialized:$,hasSelectedNodes:A}}function nV(u,f){if(!u.parentId)return;let l=f.get(u.parentId);if(l)l.set(u.id,u);else f.set(u.parentId,new Map([[u.id,u]]))}function r9(u,f,l,r,n){let{elevateNodesOnSelect:i,nodeOrigin:y,nodeExtent:_,zIndexMode:$}=f9(u9,r),A=u.parentId,c=f.get(A);if(!c){console.warn(`Parent node ${A} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}if(nV(u,l),n&&!c.parentId&&c.internals.rootParentIndex===void 0&&$==="auto")c.internals.rootParentIndex=++n.i,c.internals.z=c.internals.z+n.i*fV;if(n&&c.internals.rootParentIndex!==void 0)n.i=c.internals.rootParentIndex;let j=i&&!l9($)?tN:0,{x:F,y:U,z:Q}=iV(u,c,y,_,j,$),{positionAbsolute:L}=u.internals,w=F!==L.x||U!==L.y;if(w||Q!==u.internals.z)f.set(u.id,{...u,internals:{...u.internals,positionAbsolute:w?{x:F,y:U}:L,z:Q}})}function cN(u,f,l){let r=Er(u.zIndex)?u.zIndex:0;if(l9(l))return r;return r+(u.selected?f:0)}function iV(u,f,l,r,n,i){let{x:y,y:_}=f.internals.positionAbsolute,$=t0(u),A=w$(u,l),c=fy(u.extent)?Y1(A,u.extent,$):A,j=Y1({x:y+c.x,y:_+c.y},r,$);if(u.extent==="parent")j=fN(j,$,f);let F=cN(u,n,i),U=f.internals.z??0;return{x:j.x,y:j.y,z:U>=F?U+1:F}}function a6(u,f,l,r=[0,0]){let n=[],i=new Map;for(let y of u){let _=f.get(y.parentId);if(!_)continue;let $=i.get(y.parentId)?.expandedRect??S1(_),A=hc($,y.rect);i.set(y.parentId,{expandedRect:A,parent:_})}if(i.size>0)i.forEach(({expandedRect:y,parent:_},$)=>{let A=_.internals.positionAbsolute,c=t0(_),j=_.origin??r,F=y.x0||U>0||w||J)n.push({id:$,type:"position",position:{x:_.position.x-F+w,y:_.position.y-U+J}}),l.get($)?.forEach((N)=>{if(!u.some((q)=>q.id===N.id))n.push({id:N.id,type:"position",position:{x:N.position.x+F,y:N.position.y+U}})});if(c.width0){let U=a6(F,f,l,n);A.push(...U)}return{changes:A,updatedInternals:$}}async function FN({delta:u,panZoom:f,transform:l,translateExtent:r,width:n,height:i}){if(!f||!u.x&&!u.y)return Promise.resolve(!1);let y=await f.setViewportConstrained({x:l[0]+u.x,y:l[1]+u.y,zoom:l[2]},[[0,0],[n,i]],r),_=!!y&&(y.x!==l[0]||y.y!==l[1]||y.k!==l[2]);return Promise.resolve(_)}function Iq(u,f,l,r,n,i){let y=n,_=r.get(y)||new Map;r.set(y,_.set(l,f)),y=`${n}-${u}`;let $=r.get(y)||new Map;if(r.set(y,$.set(l,f)),i){y=`${n}-${u}-${i}`;let A=r.get(y)||new Map;r.set(y,A.set(l,f))}}function n9(u,f,l){u.clear(),f.clear();for(let r of l){let{source:n,target:i,sourceHandle:y=null,targetHandle:_=null}=r,$={edgeId:r.id,source:n,target:i,sourceHandle:y,targetHandle:_},A=`${n}-${y}--${i}-${_}`,c=`${i}-${_}--${n}-${y}`;Iq("source",$,c,u,n,y),Iq("target",$,A,u,i,_),f.set(r.id,r)}}function JN(u,f){if(!u.parentId)return!1;let l=f.get(u.parentId);if(!l)return!1;if(l.selected)return!0;return JN(l,f)}function gq(u,f,l){let r=u;do{if(r?.matches?.(f))return!0;if(r===l)return!1;r=r?.parentElement}while(r);return!1}function yV(u,f,l,r){let n=new Map;for(let[i,y]of u)if((y.selected||y.id===r)&&(!y.parentId||!JN(y,u))&&(y.draggable||f&&typeof y.draggable>"u")){let _=u.get(i);if(_)n.set(i,{id:i,position:_.position||{x:0,y:0},distance:{x:l.x-_.internals.positionAbsolute.x,y:l.y-_.internals.positionAbsolute.y},extent:_.extent,parentId:_.parentId,origin:_.origin,expandParent:_.expandParent,internals:{positionAbsolute:_.internals.positionAbsolute||{x:0,y:0}},measured:{width:_.measured.width??0,height:_.measured.height??0}})}return n}function Vc({nodeId:u,dragItems:f,nodeLookup:l,dragging:r=!0}){let n=[];for(let[y,_]of f){let $=l.get(y)?.internals.userNode;if($)n.push({...$,position:_.position,dragging:r})}if(!u)return[n[0],n];let i=l.get(u)?.internals.userNode;return[!i?n[0]:{...i,position:f.get(u)?.position||i.position,dragging:r},n]}function _V({dragItems:u,snapGrid:f,x:l,y:r}){let n=u.values().next().value;if(!n)return null;let i={x:l-n.distance.x,y:r-n.distance.y},y=iy(i,f);return{x:y.x-i.x,y:y.y-i.y}}function UN({onNodeMouseDown:u,getStoreItems:f,onDragStart:l,onDrag:r,onDragStop:n}){let i={x:null,y:null},y=0,_=new Map,$=!1,A={x:0,y:0},c=null,j=!1,F=null,U=!1,Q=!1,L=null;function w({noDragClassName:N,handleSelector:q,domNode:W,isSelectable:z,nodeId:Z,nodeClickDistance:H=0}){F=af(W);function E({x:Y,y:p}){let{nodeLookup:O,nodeExtent:m,snapGrid:X,snapToGrid:v,nodeOrigin:T,onNodeDrag:S,onSelectionDrag:k,onError:I,updateNodePositions:b}=f();i={x:Y,y:p};let o=!1,s=_.size>1,x=s&&m?Yc(ry(_)):null,fu=s&&v?_V({dragItems:_,snapGrid:X,x:Y,y:p}):null;for(let[$u,tu]of _){if(!O.has($u))continue;let ju={x:Y-tu.distance.x,y:p-tu.distance.y};if(v)ju=fu?{x:Math.round(ju.x+fu.x),y:Math.round(ju.y+fu.y)}:iy(ju,X);let Gu=null;if(s&&m&&!tu.extent&&x){let{positionAbsolute:e}=tu.internals,uu=e.x-x.x+m[0][0],Wu=e.x+tu.measured.width-x.x2+m[1][0],g=e.y-x.y+m[0][1],Qu=e.y+tu.measured.height-x.y2+m[1][1];Gu=[[uu,g],[Wu,Qu]]}let{position:qu,positionAbsolute:P}=xc({nodeId:$u,nextPosition:ju,nodeLookup:O,nodeExtent:Gu?Gu:m,nodeOrigin:T,onError:I});o=o||tu.position.x!==qu.x||tu.position.y!==qu.y,tu.position=qu,tu.internals.positionAbsolute=P}if(Q=Q||o,!o)return;if(b(_,!0),L&&(r||S||!Z&&k)){let[$u,tu]=Vc({nodeId:Z,dragItems:_,nodeLookup:O});if(r?.(L,_,$u,tu),S?.(L,$u,tu),!Z)k?.(L,tu)}}async function D(){if(!c)return;let{transform:Y,panBy:p,autoPanSpeed:O,autoPanOnNodeDrag:m}=f();if(!m){$=!1,cancelAnimationFrame(y);return}let[X,v]=lN(A,c,O);if(X!==0||v!==0){if(i.x=(i.x??0)-X/Y[2],i.y=(i.y??0)-v/Y[2],await p({x:X,y:v}))E(i)}y=requestAnimationFrame(D)}function h(Y){let{nodeLookup:p,multiSelectionActive:O,nodesDraggable:m,transform:X,snapGrid:v,snapToGrid:T,selectNodesOnDrag:S,onNodeDragStart:k,onSelectionDragStart:I,unselectNodesAndEdges:b}=f();if(j=!0,(!S||!z)&&!O&&Z){if(!p.get(Z)?.selected)b()}if(z&&S&&Z)u?.(Z);let o=W$(Y.sourceEvent,{transform:X,snapGrid:v,snapToGrid:T,containerBounds:c});if(i=o,_=yV(p,m,o,Z),_.size>0&&(l||k||!Z&&I)){let[s,x]=Vc({nodeId:Z,dragItems:_,nodeLookup:p});if(l?.(Y.sourceEvent,_,s,x),k?.(Y.sourceEvent,s,x),!Z)I?.(Y.sourceEvent,x)}}let V=u$().clickDistance(H).on("start",(Y)=>{let{domNode:p,nodeDragThreshold:O,transform:m,snapGrid:X,snapToGrid:v}=f();if(c=p?.getBoundingClientRect()||null,U=!1,Q=!1,L=Y.sourceEvent,O===0)h(Y);i=W$(Y.sourceEvent,{transform:m,snapGrid:X,snapToGrid:v,containerBounds:c}),A=Zr(Y.sourceEvent,c)}).on("drag",(Y)=>{let{autoPanOnNodeDrag:p,transform:O,snapGrid:m,snapToGrid:X,nodeDragThreshold:v,nodeLookup:T}=f(),S=W$(Y.sourceEvent,{transform:O,snapGrid:m,snapToGrid:X,containerBounds:c});if(L=Y.sourceEvent,Y.sourceEvent.type==="touchmove"&&Y.sourceEvent.touches.length>1||Z&&!T.has(Z))U=!0;if(U)return;if(!$&&p&&j)$=!0,D();if(!j){let k=Zr(Y.sourceEvent,c),I=k.x-A.x,b=k.y-A.y;if(Math.sqrt(I*I+b*b)>v)h(Y)}if((i.x!==S.xSnapped||i.y!==S.ySnapped)&&_&&j)A=Zr(Y.sourceEvent,c),E(S)}).on("end",(Y)=>{if(!j||U)return;if($=!1,j=!1,cancelAnimationFrame(y),_.size>0){let{nodeLookup:p,updateNodePositions:O,onNodeDragStop:m,onSelectionDragStop:X}=f();if(Q)O(_,!1),Q=!1;if(n||m||!Z&&X){let[v,T]=Vc({nodeId:Z,dragItems:_,nodeLookup:p,dragging:!1});if(n?.(Y.sourceEvent,_,v,T),m?.(Y.sourceEvent,v,T),!Z)X?.(Y.sourceEvent,T)}}}).filter((Y)=>{let p=Y.target;return!Y.button&&(!N||!gq(p,`.${N}`,W))&&(!q||gq(p,q,W))});F.call(V)}function J(){F?.on(".drag",null)}return{update:w,destroy:J}}function $V(u,f,l){let r=[],n={x:u.x-l,y:u.y-l,width:l*2,height:l*2};for(let i of f.values())if(ny(n,S1(i))>0)r.push(i);return r}var tV=250;function AV(u,f,l,r){let n=[],i=1/0,y=$V(u,l,f+tV);for(let _ of y){let $=[..._.internals.handleBounds?.source??[],..._.internals.handleBounds?.target??[]];for(let A of $){if(r.nodeId===A.nodeId&&r.type===A.type&&r.id===A.id)continue;let{x:c,y:j}=Xn(_,A,A.position,!0),F=Math.sqrt(Math.pow(c-u.x,2)+Math.pow(j-u.y,2));if(F>f)continue;if(F1){let _=r.type==="source"?"target":"source";return n.find(($)=>$.type===_)??n[0]}return n[0]}function QN(u,f,l,r,n,i=!1){let y=r.get(u);if(!y)return null;let _=n==="strict"?y.internals.handleBounds?.[f]:[...y.internals.handleBounds?.source??[],...y.internals.handleBounds?.target??[]],$=(l?_?.find((A)=>A.id===l):_?.[0])??null;return $&&i?{...$,...Xn(y,$,$.position,!0)}:$}function qN(u,f){if(u)return u;else if(f?.classList.contains("target"))return"target";else if(f?.classList.contains("source"))return"source";return null}function cV(u,f){let l=null;if(f)l=!0;else if(u&&!f)l=!1;return l}var NN=()=>!0;function jV(u,{connectionMode:f,connectionRadius:l,handleId:r,nodeId:n,edgeUpdaterType:i,isTarget:y,domNode:_,nodeLookup:$,lib:A,autoPanOnConnect:c,flowId:j,panBy:F,cancelConnection:U,onConnectStart:Q,onConnect:L,onConnectEnd:w,isValidConnection:J=NN,onReconnectEnd:N,updateConnection:q,getTransform:W,getFromHandle:z,autoPanSpeed:Z,dragThreshold:H=1,handleDomNode:E}){let D=sc(u.target),h=0,V,{x:Y,y:p}=Zr(u),O=qN(i,E),m=_?.getBoundingClientRect(),X=!1;if(!m||!O)return;let v=QN(n,O,r,$,f);if(!v)return;let T=Zr(u,m),S=!1,k=null,I=!1,b=null;function o(){if(!c||!m)return;let[qu,P]=lN(T,m,Z);F({x:qu,y:P}),h=requestAnimationFrame(o)}let s={...v,nodeId:n,type:O,position:v.position},x=$.get(n),$u={inProgress:!0,isValid:null,from:Xn(x,s,wu.Left,!0),fromHandle:s,fromPosition:s.position,fromNode:x,to:T,toHandle:null,toPosition:Pq[s.position],toNode:null,pointer:T};function tu(){X=!0,q($u),Q?.(u,{nodeId:n,handleId:r,handleType:O})}if(H===0)tu();function ju(qu){if(!X){let{x:Qu,y:Tu}=Zr(qu),Zu=Qu-Y,Xu=Tu-p;if(!(Zu*Zu+Xu*Xu>H*H))return;tu()}if(!z()||!s){Gu(qu);return}let P=W();if(T=Zr(qu,m),V=AV(yy(T,P,!1,[1,1]),l,$,s),!S)o(),S=!0;let e=WN(qu,{handle:V,connectionMode:f,fromNodeId:n,fromHandleId:r,fromType:y?"target":"source",isValidConnection:J,doc:D,lib:A,flowId:j,nodeLookup:$});b=e.handleDomNode,k=e.connection,I=cV(!!V,e.isValid);let uu=$.get(n),Wu=uu?Xn(uu,s,wu.Left,!0):$u.from,g={...$u,from:Wu,isValid:I,to:e.toHandle&&I?L$({x:e.toHandle.x,y:e.toHandle.y},P):T,toHandle:e.toHandle,toPosition:I&&e.toHandle?e.toHandle.position:Pq[s.position],toNode:e.toHandle?$.get(e.toHandle.nodeId):null,pointer:T};q(g),$u=g}function Gu(qu){if("touches"in qu&&qu.touches.length>0)return;if(X){if((V||b)&&k&&I)L?.(k);let{inProgress:P,...e}=$u,uu={...e,toPosition:$u.toHandle?$u.toPosition:null};if(w?.(qu,uu),i)N?.(qu,uu)}U(),cancelAnimationFrame(h),S=!1,I=!1,k=null,b=null,D.removeEventListener("mousemove",ju),D.removeEventListener("mouseup",Gu),D.removeEventListener("touchmove",ju),D.removeEventListener("touchend",Gu)}D.addEventListener("mousemove",ju),D.addEventListener("mouseup",Gu),D.addEventListener("touchmove",ju),D.addEventListener("touchend",Gu)}function WN(u,{handle:f,connectionMode:l,fromNodeId:r,fromHandleId:n,fromType:i,doc:y,lib:_,flowId:$,isValidConnection:A=NN,nodeLookup:c}){let j=i==="target",F=f?y.querySelector(`.${_}-flow__handle[data-id="${$}-${f?.nodeId}-${f?.id}-${f?.type}"]`):null,{x:U,y:Q}=Zr(u),L=y.elementFromPoint(U,Q),w=L?.classList.contains(`${_}-flow__handle`)?L:F,J={handleDomNode:w,isValid:!1,connection:null,toHandle:null};if(w){let N=qN(void 0,w),q=w.getAttribute("data-nodeid"),W=w.getAttribute("data-handleid"),z=w.classList.contains("connectable"),Z=w.classList.contains("connectableend");if(!q||!N)return J;let H={source:j?q:r,sourceHandle:j?W:n,target:j?r:q,targetHandle:j?n:W};J.connection=H;let D=z&&Z&&(l===Vn.Strict?j&&N==="source"||!j&&N==="target":q!==r||W!==n);J.isValid=D&&A(H),J.toHandle=QN(q,N,W,c,l,!0)}return J}var o6={onPointerDown:jV,isValid:WN};function LN({domNode:u,panZoom:f,getTransform:l,getViewScale:r}){let n=af(u);function i({translateExtent:_,width:$,height:A,zoomStep:c=1,pannable:j=!0,zoomable:F=!0,inversePan:U=!1}){let Q=(q)=>{if(q.sourceEvent.type!=="wheel"||!f)return;let W=l(),z=q.sourceEvent.ctrlKey&&_y()?10:1,Z=-q.sourceEvent.deltaY*(q.sourceEvent.deltaMode===1?0.05:q.sourceEvent.deltaMode?1:0.002)*c,H=W[2]*Math.pow(2,Z*z);f.scaleTo(H)},L=[0,0],w=(q)=>{if(q.sourceEvent.type==="mousedown"||q.sourceEvent.type==="touchstart")L=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY]},J=(q)=>{let W=l();if(q.sourceEvent.type!=="mousemove"&&q.sourceEvent.type!=="touchmove"||!f)return;let z=[q.sourceEvent.clientX??q.sourceEvent.touches[0].clientX,q.sourceEvent.clientY??q.sourceEvent.touches[0].clientY],Z=[z[0]-L[0],z[1]-L[1]];L=z;let H=r()*Math.max(W[2],Math.log(W[2]))*(U?-1:1),E={x:W[0]-Z[0]*H,y:W[1]-Z[1]*H},D=[[0,0],[$,A]];f.setViewportConstrained({x:E.x,y:E.y,zoom:W[2]},D,_)},N=N$().on("start",w).on("zoom",j?J:null).on("zoom.wheel",F?Q:null);n.call(N,{})}function y(){n.on("zoom",null)}return{update:i,destroy:y,pointer:Kl}}var d6=(u)=>({x:u.x,y:u.y,zoom:u.k}),Dc=({x:u,y:f,zoom:l})=>V1.translate(u,f).scale(l),ei=(u,f)=>u.target.closest(`.${f}`),wN=(u,f)=>f===2&&Array.isArray(u)&&u.includes(2),FV=(u)=>((u*=2)<=1?u*u*u:(u-=2)*u*u+2)/2,Xc=(u,f=0,l=FV,r=()=>{})=>{let n=typeof f==="number"&&f>0;if(!n)r();return n?u.transition().duration(f).ease(l).on("end",r):u},KN=(u)=>{let f=u.ctrlKey&&_y()?10:1;return-u.deltaY*(u.deltaMode===1?0.05:u.deltaMode?1:0.002)*f};function JV({zoomPanValues:u,noWheelClassName:f,d3Selection:l,d3Zoom:r,panOnScrollMode:n,panOnScrollSpeed:i,zoomOnPinch:y,onPanZoomStart:_,onPanZoom:$,onPanZoomEnd:A}){return(c)=>{if(ei(c,f)){if(c.ctrlKey)c.preventDefault();return!1}c.preventDefault(),c.stopImmediatePropagation();let j=l.property("__zoom").k||1;if(c.ctrlKey&&y){let w=Kl(c),J=KN(c),N=j*Math.pow(2,J);r.scaleTo(l,N,w,c);return}let F=c.deltaMode===1?20:1,U=n===C0.Vertical?0:c.deltaX*F,Q=n===C0.Horizontal?0:c.deltaY*F;if(!_y()&&c.shiftKey&&n!==C0.Vertical)U=c.deltaY*F,Q=0;r.translateBy(l,-(U/j)*i,-(Q/j)*i,{internal:!0});let L=d6(l.property("__zoom"));if(clearTimeout(u.panScrollTimeout),!u.isPanScrolling)u.isPanScrolling=!0,_?.(c,L);else $?.(c,L),u.panScrollTimeout=setTimeout(()=>{A?.(c,L),u.isPanScrolling=!1},150)}}function UV({noWheelClassName:u,preventScrolling:f,d3ZoomHandler:l}){return function(r,n){let i=r.type==="wheel",y=!f&&i&&!r.ctrlKey,_=ei(r,u);if(r.ctrlKey&&i&&_)r.preventDefault();if(y||_)return null;r.preventDefault(),l.call(this,r,n)}}function QV({zoomPanValues:u,onDraggingChange:f,onPanZoomStart:l}){return(r)=>{if(r.sourceEvent?.internal)return;let n=d6(r.transform);if(u.mouseButton=r.sourceEvent?.button||0,u.isZoomingOrPanning=!0,u.prevViewport=n,r.sourceEvent?.type==="mousedown")f(!0);if(l)l?.(r.sourceEvent,n)}}function qV({zoomPanValues:u,panOnDrag:f,onPaneContextMenu:l,onTransformChange:r,onPanZoom:n}){return(i)=>{if(u.usedRightMouseButton=!!(l&&wN(f,u.mouseButton??0)),!i.sourceEvent?.sync)r([i.transform.x,i.transform.y,i.transform.k]);if(n&&!i.sourceEvent?.internal)n?.(i.sourceEvent,d6(i.transform))}}function NV({zoomPanValues:u,panOnDrag:f,panOnScroll:l,onDraggingChange:r,onPanZoomEnd:n,onPaneContextMenu:i}){return(y)=>{if(y.sourceEvent?.internal)return;if(u.isZoomingOrPanning=!1,i&&wN(f,u.mouseButton??0)&&!u.usedRightMouseButton&&y.sourceEvent)i(y.sourceEvent);if(u.usedRightMouseButton=!1,r(!1),n){let _=d6(y.transform);u.prevViewport=_,clearTimeout(u.timerId),u.timerId=setTimeout(()=>{n?.(y.sourceEvent,_)},l?150:0)}}}function WV({zoomActivationKeyPressed:u,zoomOnScroll:f,zoomOnPinch:l,panOnDrag:r,panOnScroll:n,zoomOnDoubleClick:i,userSelectionActive:y,noWheelClassName:_,noPanClassName:$,lib:A,connectionInProgress:c}){return(j)=>{let F=u||f,U=l&&j.ctrlKey,Q=j.type==="wheel";if(j.button===1&&j.type==="mousedown"&&(ei(j,`${A}-flow__node`)||ei(j,`${A}-flow__edge`)))return!0;if(!r&&!F&&!n&&!i&&!l)return!1;if(y)return!1;if(c&&!Q)return!1;if(ei(j,_)&&Q)return!1;if(ei(j,$)&&(!Q||n&&Q&&!u))return!1;if(!l&&j.ctrlKey&&Q)return!1;if(!l&&j.type==="touchstart"&&j.touches?.length>1)return j.preventDefault(),!1;if(!F&&!n&&!U&&Q)return!1;if(!r&&(j.type==="mousedown"||j.type==="touchstart"))return!1;if(Array.isArray(r)&&!r.includes(j.button)&&j.type==="mousedown")return!1;let L=Array.isArray(r)&&r.includes(j.button)||!j.button||j.button<=1;return(!j.ctrlKey||Q)&&L}}function GN({domNode:u,minZoom:f,maxZoom:l,translateExtent:r,viewport:n,onPanZoom:i,onPanZoomStart:y,onPanZoomEnd:_,onDraggingChange:$}){let A={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},c=u.getBoundingClientRect(),j=N$().scaleExtent([f,l]).translateExtent(r),F=af(u).call(j);N({x:n.x,y:n.y,zoom:uy(n.zoom,f,l)},[[0,0],[c.width,c.height]],r);let U=F.on("wheel.zoom"),Q=F.on("dblclick.zoom");j.wheelDelta(KN);function L(V,Y){if(F)return new Promise((p)=>{j?.interpolate(Y?.interpolate==="linear"?_0:H1).transform(Xc(F,Y?.duration,Y?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function w({noWheelClassName:V,noPanClassName:Y,onPaneContextMenu:p,userSelectionActive:O,panOnScroll:m,panOnDrag:X,panOnScrollMode:v,panOnScrollSpeed:T,preventScrolling:S,zoomOnPinch:k,zoomOnScroll:I,zoomOnDoubleClick:b,zoomActivationKeyPressed:o,lib:s,onTransformChange:x,connectionInProgress:fu,paneClickDistance:$u,selectionOnDrag:tu}){if(O&&!A.isZoomingOrPanning)J();let ju=m&&!o&&!O;j.clickDistance(tu?1/0:!Er($u)||$u<0?0:$u);let Gu=ju?JV({zoomPanValues:A,noWheelClassName:V,d3Selection:F,d3Zoom:j,panOnScrollMode:v,panOnScrollSpeed:T,zoomOnPinch:k,onPanZoomStart:y,onPanZoom:i,onPanZoomEnd:_}):UV({noWheelClassName:V,preventScrolling:S,d3ZoomHandler:U});if(F.on("wheel.zoom",Gu,{passive:!1}),!O){let P=QV({zoomPanValues:A,onDraggingChange:$,onPanZoomStart:y});j.on("start",P);let e=qV({zoomPanValues:A,panOnDrag:X,onPaneContextMenu:!!p,onPanZoom:i,onTransformChange:x});j.on("zoom",e);let uu=NV({zoomPanValues:A,panOnDrag:X,panOnScroll:m,onPaneContextMenu:p,onPanZoomEnd:_,onDraggingChange:$});j.on("end",uu)}let qu=WV({zoomActivationKeyPressed:o,panOnDrag:X,zoomOnScroll:I,panOnScroll:m,zoomOnDoubleClick:b,zoomOnPinch:k,userSelectionActive:O,noPanClassName:Y,noWheelClassName:V,lib:s,connectionInProgress:fu});if(j.filter(qu),b)F.on("dblclick.zoom",Q);else F.on("dblclick.zoom",null)}function J(){j.on("zoom",null)}async function N(V,Y,p){let O=Dc(V),m=j?.constrain()(O,Y,p);if(m)await L(m);return new Promise((X)=>X(m))}async function q(V,Y){let p=Dc(V);return await L(p,Y),new Promise((O)=>O(p))}function W(V){if(F){let Y=Dc(V),p=F.property("__zoom");if(p.k!==V.zoom||p.x!==V.x||p.y!==V.y)j?.transform(F,Y,null,{sync:!0})}}function z(){let V=F?q$(F.node()):{x:0,y:0,k:1};return{x:V.x,y:V.y,zoom:V.k}}function Z(V,Y){if(F)return new Promise((p)=>{j?.interpolate(Y?.interpolate==="linear"?_0:H1).scaleTo(Xc(F,Y?.duration,Y?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function H(V,Y){if(F)return new Promise((p)=>{j?.interpolate(Y?.interpolate==="linear"?_0:H1).scaleBy(Xc(F,Y?.duration,Y?.ease,()=>p(!0)),V)});return Promise.resolve(!1)}function E(V){j?.scaleExtent(V)}function D(V){j?.translateExtent(V)}function h(V){let Y=!Er(V)||V<0?0:V;j?.clickDistance(Y)}return{update:w,destroy:J,setViewport:q,setViewportConstrained:N,getViewport:z,scaleTo:Z,scaleBy:H,setScaleExtent:E,setTranslateExtent:D,syncViewport:W,setClickDistance:h}}var Yn;(function(u){u.Line="line",u.Handle="handle"})(Yn||(Yn={}));function LV({width:u,prevWidth:f,height:l,prevHeight:r,affectsX:n,affectsY:i}){let y=u-f,_=l-r,$=[y>0?1:y<0?-1:0,_>0?1:_<0?-1:0];if(y&&n)$[0]=$[0]*-1;if(_&&i)$[1]=$[1]*-1;return $}function sq(u){let f=u.includes("right")||u.includes("left"),l=u.includes("bottom")||u.includes("top"),r=u.includes("left"),n=u.includes("top");return{isHorizontal:f,isVertical:l,affectsX:r,affectsY:n}}function Hn(u,f){return Math.max(0,f-u)}function Bn(u,f){return Math.max(0,u-f)}function M6(u,f,l){return Math.max(0,f-u,u-l)}function aq(u,f){return u?!f:f}function wV(u,f,l,r,n,i,y,_){let{affectsX:$,affectsY:A}=f,{isHorizontal:c,isVertical:j}=f,F=c&&j,{xSnapped:U,ySnapped:Q}=l,{minWidth:L,maxWidth:w,minHeight:J,maxHeight:N}=r,{x:q,y:W,width:z,height:Z,aspectRatio:H}=u,E=Math.floor(c?U-u.pointerX:0),D=Math.floor(j?Q-u.pointerY:0),h=z+($?-E:E),V=Z+(A?-D:D),Y=-i[0]*z,p=-i[1]*Z,O=M6(h,L,w),m=M6(V,J,N);if(y){let T=0,S=0;if($&&E<0)T=Hn(q+E+Y,y[0][0]);else if(!$&&E>0)T=Bn(q+h+Y,y[1][0]);if(A&&D<0)S=Hn(W+D+p,y[0][1]);else if(!A&&D>0)S=Bn(W+V+p,y[1][1]);O=Math.max(O,T),m=Math.max(m,S)}if(_){let T=0,S=0;if($&&E>0)T=Bn(q+E,_[0][0]);else if(!$&&E<0)T=Hn(q+h,_[1][0]);if(A&&D>0)S=Bn(W+D,_[0][1]);else if(!A&&D<0)S=Hn(W+V,_[1][1]);O=Math.max(O,T),m=Math.max(m,S)}if(n){if(c){let T=M6(h/H,J,N)*H;if(O=Math.max(O,T),y){let S=0;if(!$&&!A||$&&!A&&F)S=Bn(W+p+h/H,y[1][1])*H;else S=Hn(W+p+($?E:-E)/H,y[0][1])*H;O=Math.max(O,S)}if(_){let S=0;if(!$&&!A||$&&!A&&F)S=Hn(W+h/H,_[1][1])*H;else S=Bn(W+($?E:-E)/H,_[0][1])*H;O=Math.max(O,S)}}if(j){let T=M6(V*H,L,w)/H;if(m=Math.max(m,T),y){let S=0;if(!$&&!A||A&&!$&&F)S=Bn(q+V*H+Y,y[1][0])/H;else S=Hn(q+(A?D:-D)*H+Y,y[0][0])/H;m=Math.max(m,S)}if(_){let S=0;if(!$&&!A||A&&!$&&F)S=Hn(q+V*H,_[1][0])/H;else S=Bn(q+(A?D:-D)*H,_[0][0])/H;m=Math.max(m,S)}}}if(D=D+(D<0?m:-m),E=E+(E<0?O:-O),n)if(F)if(h>V*H)D=(aq($,A)?-E:E)/H;else E=(aq($,A)?-D:D)*H;else if(c)D=E/H,A=$;else E=D*H,$=A;let X=$?q+E:q,v=A?W+D:W;return{width:z+($?-E:E),height:Z+(A?-D:D),x:i[0]*E*(!$?1:-1)+X,y:i[1]*D*(!A?1:-1)+v}}var zN={width:0,height:0,x:0,y:0},KV={...zN,pointerX:0,pointerY:0,aspectRatio:1};function GV(u){return[[0,0],[u.measured.width,u.measured.height]]}function zV(u,f,l){let r=f.position.x+u.position.x,n=f.position.y+u.position.y,i=u.measured.width??0,y=u.measured.height??0,_=l[0]*i,$=l[1]*y;return[[r-_,n-$],[r+i-_,n+y-$]]}function TN({domNode:u,nodeId:f,getStoreItems:l,onChange:r,onEnd:n}){let i=af(u),y={controlDirection:sq("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function _({controlPosition:A,boundaries:c,keepAspectRatio:j,resizeDirection:F,onResizeStart:U,onResize:Q,onResizeEnd:L,shouldResize:w}){let J={...zN},N={...KV};y={boundaries:c,resizeDirection:F,keepAspectRatio:j,controlDirection:sq(A)};let q=void 0,W=null,z=[],Z=void 0,H=void 0,E=void 0,D=!1,h=u$().on("start",(V)=>{let{nodeLookup:Y,transform:p,snapGrid:O,snapToGrid:m,nodeOrigin:X,paneDomNode:v}=l();if(q=Y.get(f),!q)return;W=v?.getBoundingClientRect()??null;let{xSnapped:T,ySnapped:S}=W$(V.sourceEvent,{transform:p,snapGrid:O,snapToGrid:m,containerBounds:W});if(J={width:q.measured.width??0,height:q.measured.height??0,x:q.position.x??0,y:q.position.y??0},N={...J,pointerX:T,pointerY:S,aspectRatio:J.width/J.height},Z=void 0,q.parentId&&(q.extent==="parent"||q.expandParent))Z=Y.get(q.parentId),H=Z&&q.extent==="parent"?GV(Z):void 0;z=[],E=void 0;for(let[k,I]of Y)if(I.parentId===f){if(z.push({id:k,position:{...I.position},extent:I.extent}),I.extent==="parent"||I.expandParent){let b=zV(I,q,I.origin??X);if(E)E=[[Math.min(b[0][0],E[0][0]),Math.min(b[0][1],E[0][1])],[Math.max(b[1][0],E[1][0]),Math.max(b[1][1],E[1][1])]];else E=b}}U?.(V,{...J})}).on("drag",(V)=>{let{transform:Y,snapGrid:p,snapToGrid:O,nodeOrigin:m}=l(),X=W$(V.sourceEvent,{transform:Y,snapGrid:p,snapToGrid:O,containerBounds:W}),v=[];if(!q)return;let{x:T,y:S,width:k,height:I}=J,b={},o=q.origin??m,{width:s,height:x,x:fu,y:$u}=wV(N,y.controlDirection,X,y.boundaries,y.keepAspectRatio,o,H,E),tu=s!==k,ju=x!==I,Gu=fu!==T&&tu,qu=$u!==S&&ju;if(!Gu&&!qu&&!tu&&!ju)return;if(Gu||qu||o[0]===1||o[1]===1){if(b.x=Gu?fu:J.x,b.y=qu?$u:J.y,J.x=b.x,J.y=b.y,z.length>0){let Wu=fu-T,g=$u-S;for(let Qu of z)Qu.position={x:Qu.position.x-Wu+o[0]*(s-k),y:Qu.position.y-g+o[1]*(x-I)},v.push(Qu)}}if(tu||ju)b.width=tu&&(!y.resizeDirection||y.resizeDirection==="horizontal")?s:J.width,b.height=ju&&(!y.resizeDirection||y.resizeDirection==="vertical")?x:J.height,J.width=b.width,J.height=b.height;if(Z&&q.expandParent){let Wu=o[0]*(b.width??0);if(b.x&&b.x{if(!D)return;L?.(V,{...J}),n?.({...J}),D=!1});i.call(h)}function $(){i.on(".drag",null)}return{update:_,destroy:$}}var mN=Pu(qf(),1),PN=Pu(XN(),1);var YN=(u)=>{let f,l=new Set,r=(c,j)=>{let F=typeof c==="function"?c(f):c;if(!Object.is(F,f)){let U=f;f=(j!=null?j:typeof F!=="object"||F===null)?F:Object.assign({},f,F),l.forEach((Q)=>Q(f,U))}},n=()=>f,$={setState:r,getState:n,getInitialState:()=>A,subscribe:(c)=>{return l.add(c),()=>l.delete(c)},destroy:()=>{l.clear()}},A=f=u(r,n,$);return $},SN=(u)=>u?YN(u):YN;var{useDebugValue:xV}=mN.default,{useSyncExternalStoreWithSelector:hV}=PN.default,bV=(u)=>u;function y9(u,f=bV,l){let r=hV(u.subscribe,u.getState,u.getServerState||u.getInitialState,f,l);return xV(r),r}var pN=(u,f)=>{let l=SN(u),r=(n,i=f)=>y9(l,n,i);return Object.assign(r,l),r},MN=(u,f)=>u?pN(u,f):pN;function zf(u,f){if(Object.is(u,f))return!0;if(typeof u!=="object"||u===null||typeof f!=="object"||f===null)return!1;if(u instanceof Map&&f instanceof Map){if(u.size!==f.size)return!1;for(let[r,n]of u)if(!Object.is(n,f.get(r)))return!1;return!0}if(u instanceof Set&&f instanceof Set){if(u.size!==f.size)return!1;for(let r of u)if(!f.has(r))return!1;return!0}let l=Object.keys(u);if(l.length!==Object.keys(f).length)return!1;for(let r of l)if(!Object.prototype.hasOwnProperty.call(f,r)||!Object.is(u[r],f[r]))return!1;return!0}var vV=Pu(j5(),1),r8=yu.createContext(null),kV=r8.Provider,tW=Fr.error001();function eu(u,f){let l=yu.useContext(r8);if(l===null)throw Error(tW);return y9(l,u,f)}function Zf(){let u=yu.useContext(r8);if(u===null)throw Error(tW);return yu.useMemo(()=>({getState:u.getState,setState:u.setState,subscribe:u.subscribe}),[u])}var CN={display:"none"},IV={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},AW="react-flow__node-desc",cW="react-flow__edge-desc",gV="react-flow__aria-live",sV=(u)=>u.ariaLiveMessage,aV=(u)=>u.ariaLabelConfig;function oV({rfId:u}){let f=eu(sV);return ru.jsx("div",{id:`${gV}-${u}`,"aria-live":"assertive","aria-atomic":"true",style:IV,children:f})}function dV({rfId:u,disableKeyboardA11y:f}){let l=eu(aV);return ru.jsxs(ru.Fragment,{children:[ru.jsx("div",{id:`${AW}-${u}`,style:CN,children:f?l["node.a11yDescription.default"]:l["node.a11yDescription.keyboardDisabled"]}),ru.jsx("div",{id:`${cW}-${u}`,style:CN,children:l["edge.a11yDescription.default"]}),!f&&ru.jsx(oV,{rfId:u})]})}var n8=yu.forwardRef(({position:u="top-left",children:f,className:l,style:r,...n},i)=>{let y=`${u}`.split("-");return ru.jsx("div",{className:Yf(["react-flow__panel",l,...y]),style:r,ref:i,...n,children:f})});n8.displayName="Panel";function eV({proOptions:u,position:f="bottom-right"}){if(u?.hideAttribution)return null;return ru.jsx(n8,{position:f,className:"react-flow__attribution","data-message":"Please only hide this attribution when you are subscribed to React Flow Pro: https://pro.reactflow.dev",children:ru.jsx("a",{href:"https://reactflow.dev",target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}var uD=(u)=>{let f=[],l=[];for(let[,r]of u.nodeLookup)if(r.selected)f.push(r.internals.userNode);for(let[,r]of u.edgeLookup)if(r.selected)l.push(r);return{selectedNodes:f,selectedEdges:l}},u8=(u)=>u.id;function fD(u,f){return zf(u.selectedNodes.map(u8),f.selectedNodes.map(u8))&&zf(u.selectedEdges.map(u8),f.selectedEdges.map(u8))}function lD({onSelectionChange:u}){let f=Zf(),{selectedNodes:l,selectedEdges:r}=eu(uD,fD);return yu.useEffect(()=>{let n={nodes:l,edges:r};u?.(n),f.getState().onSelectionChangeHandlers.forEach((i)=>i(n))},[l,r,u]),null}var rD=(u)=>!!u.onSelectionChangeHandlers;function nD({onSelectionChange:u}){let f=eu(rD);if(u||f)return ru.jsx(lD,{onSelectionChange:u});return null}var t9=typeof window<"u"?yu.useLayoutEffect:yu.useEffect,jW=[0,0],iD={x:0,y:0,zoom:1},yD=["nodes","edges","defaultNodes","defaultEdges","onConnect","onConnectStart","onConnectEnd","onClickConnectStart","onClickConnectEnd","nodesDraggable","autoPanOnNodeFocus","nodesConnectable","nodesFocusable","edgesFocusable","edgesReconnectable","elevateNodesOnSelect","elevateEdgesOnSelect","minZoom","maxZoom","nodeExtent","onNodesChange","onEdgesChange","elementsSelectable","connectionMode","snapGrid","snapToGrid","translateExtent","connectOnClick","defaultEdgeOptions","fitView","fitViewOptions","onNodesDelete","onEdgesDelete","onDelete","onNodeDrag","onNodeDragStart","onNodeDragStop","onSelectionDrag","onSelectionDragStart","onSelectionDragStop","onMoveStart","onMove","onMoveEnd","noPanClassName","nodeOrigin","autoPanOnConnect","autoPanOnNodeDrag","onError","connectionRadius","isValidConnection","selectNodesOnDrag","nodeDragThreshold","connectionDragThreshold","onBeforeDelete","debug","autoPanSpeed","ariaLabelConfig","zIndexMode"],RN=[...yD,"rfId"],_D=(u)=>({setNodes:u.setNodes,setEdges:u.setEdges,setMinZoom:u.setMinZoom,setMaxZoom:u.setMaxZoom,setTranslateExtent:u.setTranslateExtent,setNodeExtent:u.setNodeExtent,reset:u.reset,setDefaultNodesAndEdges:u.setDefaultNodesAndEdges}),xN={translateExtent:ly,nodeOrigin:jW,minZoom:0.5,maxZoom:2,elementsSelectable:!0,noPanClassName:"nopan",rfId:"1"};function $D(u){let{setNodes:f,setEdges:l,setMinZoom:r,setMaxZoom:n,setTranslateExtent:i,setNodeExtent:y,reset:_,setDefaultNodesAndEdges:$}=eu(_D,zf),A=Zf();t9(()=>{return $(u.defaultNodes,u.defaultEdges),()=>{c.current=xN,_()}},[]);let c=yu.useRef(xN);return t9(()=>{for(let j of RN){let F=u[j],U=c.current[j];if(F===U)continue;if(typeof u[j]>"u")continue;if(j==="nodes")f(F);else if(j==="edges")l(F);else if(j==="minZoom")r(F);else if(j==="maxZoom")n(F);else if(j==="translateExtent")i(F);else if(j==="nodeExtent")y(F);else if(j==="ariaLabelConfig")A.setState({ariaLabelConfig:nN(F)});else if(j==="fitView")A.setState({fitViewQueued:F});else if(j==="fitViewOptions")A.setState({fitViewOptions:F});else A.setState({[j]:F})}c.current=u},RN.map((j)=>u[j])),null}function hN(){if(typeof window>"u"||!window.matchMedia)return null;return window.matchMedia("(prefers-color-scheme: dark)")}function tD(u){let[f,l]=yu.useState(u==="system"?null:u);return yu.useEffect(()=>{if(u!=="system"){l(u);return}let r=hN(),n=()=>l(r?.matches?"dark":"light");return n(),r?.addEventListener("change",n),()=>{r?.removeEventListener("change",n)}},[u]),f!==null?f:hN()?.matches?"dark":"light"}var bN=typeof document<"u"?document:null;function z$(u=null,f={target:bN,actInsideInputWithModifier:!0}){let[l,r]=yu.useState(!1),n=yu.useRef(!1),i=yu.useRef(new Set([])),[y,_]=yu.useMemo(()=>{if(u!==null){let A=(Array.isArray(u)?u:[u]).filter((j)=>typeof j==="string").map((j)=>j.replace("+",` `).replace(` `,` +`).split(` -`)),A=c.reduce((j,F)=>j.concat(...F),[]);return[c,A]}return[[],[]]},[u]);return yu.useEffect(()=>{let $=f?.target??MN,c=f?.actInsideInputWithModifier??!0;if(u!==null){let A=(U)=>{if(n.current=U.ctrlKey||U.metaKey||U.shiftKey||U.altKey,(!n.current||n.current&&!c)&&gA(U))return!1;let w=RN(U.code,_);if(i.current.add(U[w]),CN(y,i.current,!1)){let L=U.composedPath?.()?.[0]||U.target,J=L?.nodeName==="BUTTON"||L?.nodeName==="A";if(f.preventDefault!==!1&&(n.current||!J))U.preventDefault();r(!0)}},j=(U)=>{let Q=RN(U.code,_);if(CN(y,i.current,!0))r(!1),i.current.clear();else i.current.delete(U[Q]);if(U.key==="Meta")i.current.clear();n.current=!1},F=()=>{i.current.clear(),r(!1)};return $?.addEventListener("keydown",A),$?.addEventListener("keyup",j),window.addEventListener("blur",F),window.addEventListener("contextmenu",F),()=>{$?.removeEventListener("keydown",A),$?.removeEventListener("keyup",j),window.removeEventListener("blur",F),window.removeEventListener("contextmenu",F)}}},[u,r]),l}function CN(u,f,l){return u.filter((r)=>l||r.length===f.size).some((r)=>r.every((n)=>f.has(n)))}function RN(u,f){return f.includes(u)?"code":"key"}var uD=()=>{let u=Tf();return yu.useMemo(()=>{return{zoomIn:(f)=>{let{panZoom:l}=u.getState();return l?l.scaleBy(1.2,f):Promise.resolve(!1)},zoomOut:(f)=>{let{panZoom:l}=u.getState();return l?l.scaleBy(0.8333333333333334,f):Promise.resolve(!1)},zoomTo:(f,l)=>{let{panZoom:r}=u.getState();return r?r.scaleTo(f,l):Promise.resolve(!1)},getZoom:()=>u.getState().transform[2],setViewport:async(f,l)=>{let{transform:[r,n,i],panZoom:y}=u.getState();if(!y)return Promise.resolve(!1);return await y.setViewport({x:f.x??r,y:f.y??n,zoom:f.zoom??i},l),Promise.resolve(!0)},getViewport:()=>{let[f,l,r]=u.getState().transform;return{x:f,y:l,zoom:r}},setCenter:async(f,l,r)=>{return u.getState().setCenter(f,l,r)},fitBounds:async(f,l)=>{let{width:r,height:n,minZoom:i,maxZoom:y,panZoom:_}=u.getState(),$=K$(f,r,n,i,y,l?.padding??0.1);if(!_)return Promise.resolve(!1);return await _.setViewport($,{duration:l?.duration,ease:l?.ease,interpolate:l?.interpolate}),Promise.resolve(!0)},screenToFlowPosition:(f,l={})=>{let{transform:r,snapGrid:n,snapToGrid:i,domNode:y}=u.getState();if(!y)return f;let{x:_,y:$}=y.getBoundingClientRect(),c={x:f.x-_,y:f.y-$},A=l.snapGrid??n,j=l.snapToGrid??i;return yy(c,r,j,A)},flowToScreenPosition:(f)=>{let{transform:l,domNode:r}=u.getState();if(!r)return f;let{x:n,y:i}=r.getBoundingClientRect(),y=w$(f,l);return{x:y.x+n,y:y.y+i}}}},[])};function $W(u,f){let l=[],r=new Map,n=[];for(let i of u)if(i.type==="add"){n.push(i);continue}else if(i.type==="remove"||i.type==="replace")r.set(i.id,[i]);else{let y=r.get(i.id);if(y)y.push(i);else r.set(i.id,[i])}for(let i of f){let y=r.get(i.id);if(!y){l.push(i);continue}if(y[0].type==="remove")continue;if(y[0].type==="replace"){l.push({...y[0].item});continue}let _={...i};for(let $ of y)fD($,_);l.push(_)}if(n.length)n.forEach((i)=>{if(i.index!==void 0)l.splice(i.index,0,{...i.item});else l.push({...i.item})});return l}function fD(u,f){switch(u.type){case"select":{f.selected=u.selected;break}case"position":{if(typeof u.position<"u")f.position=u.position;if(typeof u.dragging<"u")f.dragging=u.dragging;break}case"dimensions":{if(typeof u.dimensions<"u"){if(f.measured={...u.dimensions},u.setAttributes){if(u.setAttributes===!0||u.setAttributes==="width")f.width=u.dimensions.width;if(u.setAttributes===!0||u.setAttributes==="height")f.height=u.dimensions.height}}if(typeof u.resizing==="boolean")f.resizing=u.resizing;break}}}function lD(u,f){return $W(u,f)}function rD(u,f){return $W(u,f)}function P1(u,f){return{id:u,type:"select",selected:f}}function ty(u,f=new Set,l=!1){let r=[];for(let[n,i]of u){let y=f.has(n);if(!(i.selected===void 0&&!y)&&i.selected!==y){if(l)i.selected=y;r.push(P1(i.id,y))}}return r}function xN({items:u=[],lookup:f}){let l=[],r=new Map(u.map((n)=>[n.id,n]));for(let[n,i]of u.entries()){let y=f.get(i.id),_=y?.internals?.userNode??y;if(_!==void 0&&_!==i)l.push({id:i.id,item:i,type:"replace"});if(_===void 0)l.push({item:i,type:"add",index:n})}for(let[n]of f)if(r.get(n)===void 0)l.push({id:n,type:"remove"});return l}function hN(u){return{id:u.id,type:"remove"}}var bN=(u)=>kq(u),nD=(u)=>pA(u);function tW(u){return yu.forwardRef(u)}function vN(u){let[f,l]=yu.useState(BigInt(0)),[r]=yu.useState(()=>iD(()=>l((n)=>n+BigInt(1))));return _9(()=>{let n=r.get();if(n.length)u(n),r.reset()},[f]),r}function iD(u){let f=[];return{get:()=>f,reset:()=>{f=[]},push:(l)=>{f.push(l),u()}}}var cW=yu.createContext(null);function yD({children:u}){let f=Tf(),l=yu.useCallback((_)=>{let{nodes:$=[],setNodes:c,hasDefaultNodes:A,onNodesChange:j,nodeLookup:F,fitViewQueued:U,onNodesChangeMiddlewareMap:Q}=f.getState(),w=$;for(let J of _)w=typeof J==="function"?J(w):J;let L=xN({items:w,lookup:F});for(let J of Q.values())L=J(L);if(A)c(w);if(L.length>0)j?.(L);else if(U)window.requestAnimationFrame(()=>{let{fitViewQueued:J,nodes:N,setNodes:q}=f.getState();if(J)q(N)})},[]),r=vN(l),n=yu.useCallback((_)=>{let{edges:$=[],setEdges:c,hasDefaultEdges:A,onEdgesChange:j,edgeLookup:F}=f.getState(),U=$;for(let Q of _)U=typeof Q==="function"?Q(U):Q;if(A)c(U);else if(j)j(xN({items:U,lookup:F}))},[]),i=vN(n),y=yu.useMemo(()=>({nodeQueue:r,edgeQueue:i}),[]);return ru.jsx(cW.Provider,{value:y,children:u})}function _D(){let u=yu.useContext(cW);if(!u)throw Error("useBatchContext must be used within a BatchProvider");return u}var $D=(u)=>!!u.panZoom;function t9(){let u=uD(),f=Tf(),l=_D(),r=uf($D),n=yu.useMemo(()=>{let i=(j)=>f.getState().nodeLookup.get(j),y=(j)=>{l.nodeQueue.push(j)},_=(j)=>{l.edgeQueue.push(j)},$=(j)=>{let{nodeLookup:F,nodeOrigin:U}=f.getState(),Q=bN(j)?j:F.get(j.id),w=Q.parentId?vA(Q.position,Q.measured,Q.parentId,F,U):Q.position,L={...Q,position:w,width:Q.measured?.width??Q.width,height:Q.measured?.height??Q.height};return p1(L)},c=(j,F,U={replace:!1})=>{y((Q)=>Q.map((w)=>{if(w.id===j){let L=typeof F==="function"?F(w):F;return U.replace&&bN(L)?L:{...w,...L}}return w}))},A=(j,F,U={replace:!1})=>{_((Q)=>Q.map((w)=>{if(w.id===j){let L=typeof F==="function"?F(w):F;return U.replace&&nD(L)?L:{...w,...L}}return w}))};return{getNodes:()=>f.getState().nodes.map((j)=>({...j})),getNode:(j)=>i(j)?.internals.userNode,getInternalNode:i,getEdges:()=>{let{edges:j=[]}=f.getState();return j.map((F)=>({...F}))},getEdge:(j)=>f.getState().edgeLookup.get(j),setNodes:y,setEdges:_,addNodes:(j)=>{let F=Array.isArray(j)?j:[j];l.nodeQueue.push((U)=>[...U,...F])},addEdges:(j)=>{let F=Array.isArray(j)?j:[j];l.edgeQueue.push((U)=>[...U,...F])},toObject:()=>{let{nodes:j=[],edges:F=[],transform:U}=f.getState(),[Q,w,L]=U;return{nodes:j.map((J)=>({...J})),edges:F.map((J)=>({...J})),viewport:{x:Q,y:w,zoom:L}}},deleteElements:async({nodes:j=[],edges:F=[]})=>{let{nodes:U,edges:Q,onNodesDelete:w,onEdgesDelete:L,triggerNodeChanges:J,triggerEdgeChanges:N,onDelete:q,onBeforeDelete:W}=f.getState(),{nodes:z,edges:Z}=await sq({nodesToRemove:j,edgesToRemove:F,nodes:U,edges:Q,onBeforeDelete:W}),H=Z.length>0,E=z.length>0;if(H){let D=Z.map(hN);L?.(Z),N(D)}if(E){let D=z.map(hN);w?.(z),J(D)}if(E||H)q?.({nodes:z,edges:Z});return{deletedNodes:z,deletedEdges:Z}},getIntersectingNodes:(j,F=!0,U)=>{let Q=xA(j),w=Q?j:$(j),L=U!==void 0;if(!w)return[];return(U||f.getState().nodes).filter((J)=>{let N=f.getState().nodeLookup.get(J.id);if(N&&!Q&&(J.id===j.id||!N.internals.positionAbsolute))return!1;let q=p1(L?J:N),W=ny(q,w);return F&&W>0||W>=q.width*q.height||W>=w.width*w.height})},isNodeIntersecting:(j,F,U=!0)=>{let w=xA(j)?j:$(j);if(!w)return!1;let L=ny(w,F);return U&&L>0||L>=F.width*F.height||L>=w.width*w.height},updateNode:c,updateNodeData:(j,F,U={replace:!1})=>{c(j,(Q)=>{let w=typeof F==="function"?F(Q):F;return U.replace?{...Q,data:w}:{...Q,data:{...Q.data,...w}}},U)},updateEdge:A,updateEdgeData:(j,F,U={replace:!1})=>{A(j,(Q)=>{let w=typeof F==="function"?F(Q):F;return U.replace?{...Q,data:w}:{...Q,data:{...Q.data,...w}}},U)},getNodesBounds:(j)=>{let{nodeLookup:F,nodeOrigin:U}=f.getState();return MA(j,{nodeLookup:F,nodeOrigin:U})},getHandleConnections:({type:j,id:F,nodeId:U})=>Array.from(f.getState().connectionLookup.get(`${U}-${j}${F?`-${F}`:""}`)?.values()??[]),getNodeConnections:({type:j,handleId:F,nodeId:U})=>Array.from(f.getState().connectionLookup.get(`${U}${j?F?`-${j}-${F}`:`-${j}`:""}`)?.values()??[]),fitView:async(j)=>{let F=f.getState().fitViewResolver??dq();return f.setState({fitViewQueued:!0,fitViewOptions:j,fitViewResolver:F}),l.nodeQueue.push((U)=>[...U]),F.promise}}},[]);return yu.useMemo(()=>{return{...n,...u,viewportInitialized:r}},[r])}var kN=(u)=>u.selected,tD=typeof window<"u"?window:void 0;function cD({deleteKeyCode:u,multiSelectionKeyCode:f}){let l=Tf(),{deleteElements:r}=t9(),n=z$(u,{actInsideInputWithModifier:!1}),i=z$(f,{target:tD});yu.useEffect(()=>{if(n){let{edges:y,nodes:_}=l.getState();r({nodes:_.filter(kN),edges:y.filter(kN)}),l.setState({nodesSelectionActive:!1})}},[n]),yu.useEffect(()=>{l.setState({multiSelectionActive:i})},[i])}function AD(u){let f=Tf();yu.useEffect(()=>{let l=()=>{if(!u.current||!(u.current.checkVisibility?.()??!0))return!1;let r=b6(u.current);if(r.height===0||r.width===0)f.getState().onError?.("004",tr.error004());f.setState({width:r.width||500,height:r.height||500})};if(u.current){l(),window.addEventListener("resize",l);let r=new ResizeObserver(()=>l());return r.observe(u.current),()=>{if(window.removeEventListener("resize",l),r&&u.current)r.unobserve(u.current)}}},[])}var i8={position:"absolute",width:"100%",height:"100%",top:0,left:0},jD=(u)=>({userSelectionActive:u.userSelectionActive,lib:u.lib,connectionInProgress:u.connection.inProgress});function FD({onPaneContextMenu:u,zoomOnScroll:f=!0,zoomOnPinch:l=!0,panOnScroll:r=!1,panOnScrollSpeed:n=0.5,panOnScrollMode:i=C0.Free,zoomOnDoubleClick:y=!0,panOnDrag:_=!0,defaultViewport:$,translateExtent:c,minZoom:A,maxZoom:j,zoomActivationKeyCode:F,preventScrolling:U=!0,children:Q,noWheelClassName:w,noPanClassName:L,onViewportChange:J,isControlledViewport:N,paneClickDistance:q,selectionOnDrag:W}){let z=Tf(),Z=yu.useRef(null),{userSelectionActive:H,lib:E,connectionInProgress:D}=uf(jD,Kf),h=z$(F),B=yu.useRef();AD(Z);let X=yu.useCallback((m)=>{if(J?.({x:m[0],y:m[1],zoom:m[2]}),!N)z.setState({transform:m})},[J,N]);return yu.useEffect(()=>{if(Z.current){B.current=NN({domNode:Z.current,minZoom:A,maxZoom:j,translateExtent:c,viewport:$,onDraggingChange:(Y)=>z.setState((v)=>v.paneDragging===Y?v:{paneDragging:Y}),onPanZoomStart:(Y,v)=>{let{onViewportChangeStart:T,onMoveStart:S}=z.getState();S?.(Y,v),T?.(v)},onPanZoom:(Y,v)=>{let{onViewportChange:T,onMove:S}=z.getState();S?.(Y,v),T?.(v)},onPanZoomEnd:(Y,v)=>{let{onViewportChangeEnd:T,onMoveEnd:S}=z.getState();S?.(Y,v),T?.(v)}});let{x:m,y:O,zoom:p}=B.current.getViewport();return z.setState({panZoom:B.current,transform:[m,O,p],domNode:Z.current.closest(".react-flow")}),()=>{B.current?.destroy()}}},[]),yu.useEffect(()=>{B.current?.update({onPaneContextMenu:u,zoomOnScroll:f,zoomOnPinch:l,panOnScroll:r,panOnScrollSpeed:n,panOnScrollMode:i,zoomOnDoubleClick:y,panOnDrag:_,zoomActivationKeyPressed:h,preventScrolling:U,noPanClassName:L,userSelectionActive:H,noWheelClassName:w,lib:E,onTransformChange:X,connectionInProgress:D,selectionOnDrag:W,paneClickDistance:q})},[u,f,l,r,n,i,y,_,h,U,L,H,w,E,X,D,W,q]),ru.jsx("div",{className:"react-flow__renderer",ref:Z,style:i8,children:Q})}var JD=(u)=>({userSelectionActive:u.userSelectionActive,userSelectionRect:u.userSelectionRect});function UD(){let{userSelectionActive:u,userSelectionRect:f}=uf(JD,Kf);if(!(u&&f))return null;return ru.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:f.width,height:f.height,transform:`translate(${f.x}px, ${f.y}px)`}})}var i9=(u,f)=>{return(l)=>{if(l.target!==f.current)return;u?.(l)}},QD=(u)=>({userSelectionActive:u.userSelectionActive,elementsSelectable:u.elementsSelectable,connectionInProgress:u.connection.inProgress,dragging:u.paneDragging});function qD({isSelecting:u,selectionKeyPressed:f,selectionMode:l=S1.Full,panOnDrag:r,paneClickDistance:n,selectionOnDrag:i,onSelectionStart:y,onSelectionEnd:_,onPaneClick:$,onPaneContextMenu:c,onPaneScroll:A,onPaneMouseEnter:j,onPaneMouseMove:F,onPaneMouseLeave:U,children:Q}){let w=Tf(),{userSelectionActive:L,elementsSelectable:J,dragging:N,connectionInProgress:q}=uf(QD,Kf),W=J&&(u||L),z=yu.useRef(null),Z=yu.useRef(),H=yu.useRef(new Set),E=yu.useRef(new Set),D=yu.useRef(!1),h=(T)=>{if(D.current||q){D.current=!1;return}$?.(T),w.getState().resetSelectedElements(),w.setState({nodesSelectionActive:!1})},B=(T)=>{if(Array.isArray(r)&&r?.includes(2)){T.preventDefault();return}c?.(T)},X=A?(T)=>A(T):void 0,m=(T)=>{if(D.current)T.stopPropagation(),D.current=!1},O=(T)=>{let{domNode:S}=w.getState();if(Z.current=S?.getBoundingClientRect(),!Z.current)return;let k=T.target===z.current;if(!k&&!!T.target.closest(".nokey")||!u||!(i&&k||f)||T.button!==0||!T.isPrimary)return;T.target?.setPointerCapture?.(T.pointerId),D.current=!1;let{x:o,y:s}=zr(T.nativeEvent,Z.current);if(w.setState({userSelectionRect:{width:0,height:0,startX:o,startY:s,x:o,y:s}}),!k)T.stopPropagation(),T.preventDefault()},p=(T)=>{let{userSelectionRect:S,transform:k,nodeLookup:I,edgeLookup:b,connectionLookup:o,triggerNodeChanges:s,triggerEdgeChanges:x,defaultEdgeOptions:fu,resetSelectedElements:$u}=w.getState();if(!Z.current||!S)return;let{x:tu,y:ju}=zr(T.nativeEvent,Z.current),{startX:Gu,startY:qu}=S;if(!D.current){let g=f?0:n;if(Math.hypot(tu-Gu,ju-qu)<=g)return;$u(),y?.(T)}D.current=!0;let P={startX:Gu,startY:qu,x:tug.id)),E.current=new Set;let Wu=fu?.selectable??!0;for(let g of H.current){let Qu=o.get(g);if(!Qu)continue;for(let{edgeId:Tu}of Qu.values()){let Zu=b.get(Tu);if(Zu&&(Zu.selectable??Wu))E.current.add(Tu)}}if(!kA(e,H.current)){let g=ty(I,H.current,!0);s(g)}if(!kA(uu,E.current)){let g=ty(b,E.current);x(g)}w.setState({userSelectionRect:P,userSelectionActive:!0,nodesSelectionActive:!1})},Y=(T)=>{if(T.button!==0)return;if(T.target?.releasePointerCapture?.(T.pointerId),!L&&T.target===z.current&&w.getState().userSelectionRect)h?.(T);if(w.setState({userSelectionActive:!1,userSelectionRect:null}),D.current)_?.(T),w.setState({nodesSelectionActive:H.current.size>0})},v=r===!0||Array.isArray(r)&&r.includes(0);return ru.jsxs("div",{className:Xf(["react-flow__pane",{draggable:v,dragging:N,selection:u}]),onClick:W?void 0:i9(h,z),onContextMenu:i9(B,z),onWheel:i9(X,z),onPointerEnter:W?void 0:j,onPointerMove:W?p:F,onPointerUp:W?Y:void 0,onPointerDownCapture:W?O:void 0,onClickCapture:W?m:void 0,onPointerLeave:U,ref:z,style:i8,children:[Q,ru.jsx(UD,{})]})}function $9({id:u,store:f,unselect:l=!1,nodeRef:r}){let{addSelectedNodes:n,unselectNodesAndEdges:i,multiSelectionActive:y,nodeLookup:_,onError:$}=f.getState(),c=_.get(u);if(!c){$?.("012",tr.error012(u));return}if(f.setState({nodesSelectionActive:!1}),!c.selected)n([u]);else if(l||c.selected&&y)i({nodes:[c],edges:[]}),requestAnimationFrame(()=>r?.current?.blur())}function AW({nodeRef:u,disabled:f=!1,noDragClassName:l,handleSelector:r,nodeId:n,isSelectable:i,nodeClickDistance:y}){let _=Tf(),[$,c]=yu.useState(!1),A=yu.useRef();return yu.useEffect(()=>{A.current=cN({getStoreItems:()=>_.getState(),onNodeMouseDown:(j)=>{$9({id:j,store:_,nodeRef:u})},onDragStart:()=>{c(!0)},onDragStop:()=>{c(!1)}})},[]),yu.useEffect(()=>{if(f||!u.current||!A.current)return;return A.current.update({noDragClassName:l,handleSelector:r,domNode:u.current,isSelectable:i,nodeId:n,nodeClickDistance:y}),()=>{A.current?.destroy()}},[l,r,f,i,u,n,y]),$}var ND=(u)=>(f)=>f.selected&&(f.draggable||u&&typeof f.draggable>"u");function jW(){let u=Tf();return yu.useCallback((l)=>{let{nodeExtent:r,snapToGrid:n,snapGrid:i,nodesDraggable:y,onError:_,updateNodePositions:$,nodeLookup:c,nodeOrigin:A}=u.getState(),j=new Map,F=ND(y),U=n?i[0]:5,Q=n?i[1]:5,w=l.direction.x*U*l.factor,L=l.direction.y*Q*l.factor;for(let[,J]of c){if(!F(J))continue;let N={x:J.internals.positionAbsolute.x+w,y:J.internals.positionAbsolute.y+L};if(n)N=iy(N,i);let{position:q,positionAbsolute:W}=CA({nodeId:J.id,nextPosition:N,nodeLookup:c,nodeExtent:r,nodeOrigin:A,onError:_});J.position=q,J.internals.positionAbsolute=W,j.set(J.id,J)}$(j)},[])}var c9=yu.createContext(null),WD=c9.Provider;c9.Consumer;var FW=()=>{return yu.useContext(c9)},wD=(u)=>({connectOnClick:u.connectOnClick,noPanClassName:u.noPanClassName,rfId:u.rfId}),LD=(u,f,l)=>(r)=>{let{connectionClickStartHandle:n,connectionMode:i,connection:y}=r,{fromHandle:_,toHandle:$,isValid:c}=y,A=$?.nodeId===u&&$?.id===f&&$?.type===l;return{connectingFrom:_?.nodeId===u&&_?.id===f&&_?.type===l,connectingTo:A,clickConnecting:n?.nodeId===u&&n?.id===f&&n?.type===l,isPossibleEndHandle:i===Xn.Strict?_?.type!==l:u!==_?.nodeId||f!==_?.id,connectionInProcess:!!_,clickConnectionInProcess:!!n,valid:A&&c}};function KD({type:u="source",position:f=Lu.Top,isValidConnection:l,isConnectable:r=!0,isConnectableStart:n=!0,isConnectableEnd:i=!0,id:y,onConnect:_,children:$,className:c,onMouseDown:A,onTouchStart:j,...F},U){let Q=y||null,w=u==="target",L=Tf(),J=FW(),{connectOnClick:N,noPanClassName:q,rfId:W}=uf(wD,Kf),{connectingFrom:z,connectingTo:Z,clickConnecting:H,isPossibleEndHandle:E,connectionInProcess:D,clickConnectionInProcess:h,valid:B}=uf(LD(J,Q,u),Kf);if(!J)L.getState().onError?.("010",tr.error010());let X=(p)=>{let{defaultEdgeOptions:Y,onConnect:v,hasDefaultEdges:T}=L.getState(),S={...Y,...p};if(T){let{edges:k,setEdges:I}=L.getState();I(oA(S,k))}v?.(S),_?.(S)},m=(p)=>{if(!J)return;let Y=sA(p.nativeEvent);if(n&&(Y&&p.button===0||!Y)){let v=L.getState();o6.onPointerDown(p.nativeEvent,{handleDomNode:p.currentTarget,autoPanOnConnect:v.autoPanOnConnect,connectionMode:v.connectionMode,connectionRadius:v.connectionRadius,domNode:v.domNode,nodeLookup:v.nodeLookup,lib:v.lib,isTarget:w,handleId:Q,nodeId:J,flowId:v.rfId,panBy:v.panBy,cancelConnection:v.cancelConnection,onConnectStart:v.onConnectStart,onConnectEnd:(...T)=>L.getState().onConnectEnd?.(...T),updateConnection:v.updateConnection,onConnect:X,isValidConnection:l||((...T)=>L.getState().isValidConnection?.(...T)??!0),getTransform:()=>L.getState().transform,getFromHandle:()=>L.getState().connection.fromHandle,autoPanSpeed:v.autoPanSpeed,dragThreshold:v.connectionDragThreshold})}if(Y)A?.(p);else j?.(p)},O=(p)=>{let{onClickConnectStart:Y,onClickConnectEnd:v,connectionClickStartHandle:T,connectionMode:S,isValidConnection:k,lib:I,rfId:b,nodeLookup:o,connection:s}=L.getState();if(!J||!T&&!n)return;if(!T){Y?.(p.nativeEvent,{nodeId:J,handleId:Q,handleType:u}),L.setState({connectionClickStartHandle:{nodeId:J,type:u,id:Q}});return}let x=IA(p.target),fu=l||k,{connection:$u,isValid:tu}=o6.isValid(p.nativeEvent,{handle:{nodeId:J,id:Q,type:u},connectionMode:S,fromNodeId:T.nodeId,fromHandleId:T.id||null,fromType:T.type,isValidConnection:fu,flowId:b,doc:x,lib:I,nodeLookup:o});if(tu&&$u)X($u);let ju=structuredClone(s);delete ju.inProgress,ju.toPosition=ju.toHandle?ju.toHandle.position:null,v?.(p,ju),L.setState({connectionClickStartHandle:null})};return ru.jsx("div",{"data-handleid":Q,"data-nodeid":J,"data-handlepos":f,"data-id":`${W}-${J}-${Q}-${u}`,className:Xf(["react-flow__handle",`react-flow__handle-${f}`,"nodrag",q,c,{source:!w,target:w,connectable:r,connectablestart:n,connectableend:i,clickconnecting:H,connectingfrom:z,connectingto:Z,valid:B,connectionindicator:r&&(!D||E)&&(D||h?i:n)}]),onMouseDown:m,onTouchStart:m,onClick:N?O:void 0,ref:U,...F,children:$})}var M1=yu.memo(tW(KD));function GD({data:u,isConnectable:f,sourcePosition:l=Lu.Bottom}){return ru.jsxs(ru.Fragment,{children:[u?.label,ru.jsx(M1,{type:"source",position:l,isConnectable:f})]})}function zD({data:u,isConnectable:f,targetPosition:l=Lu.Top,sourcePosition:r=Lu.Bottom}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(M1,{type:"target",position:l,isConnectable:f}),u?.label,ru.jsx(M1,{type:"source",position:r,isConnectable:f})]})}function TD(){return null}function ED({data:u,isConnectable:f,targetPosition:l=Lu.Top}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(M1,{type:"target",position:l,isConnectable:f}),u?.label]})}var l8={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},IN={input:GD,default:zD,output:ED,group:TD};function ZD(u){if(u.internals.handleBounds===void 0)return{width:u.width??u.initialWidth??u.style?.width,height:u.height??u.initialHeight??u.style?.height};return{width:u.width??u.style?.width,height:u.height??u.style?.height}}var OD=(u)=>{let{width:f,height:l,x:r,y:n}=ry(u.nodeLookup,{filter:(i)=>!!i.selected});return{width:Gr(f)?f:null,height:Gr(l)?l:null,userSelectionActive:u.userSelectionActive,transformString:`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]}) translate(${r}px,${n}px)`}};function HD({onSelectionContextMenu:u,noPanClassName:f,disableKeyboardA11y:l}){let r=Tf(),{width:n,height:i,transformString:y,userSelectionActive:_}=uf(OD,Kf),$=jW(),c=yu.useRef(null);yu.useEffect(()=>{if(!l)c.current?.focus({preventScroll:!0})},[l]);let A=!_&&n!==null&&i!==null;if(AW({nodeRef:c,disabled:!A}),!A)return null;let j=u?(U)=>{let Q=r.getState().nodes.filter((w)=>w.selected);u(U,Q)}:void 0,F=(U)=>{if(Object.prototype.hasOwnProperty.call(l8,U.key))U.preventDefault(),$({direction:l8[U.key],factor:U.shiftKey?4:1})};return ru.jsx("div",{className:Xf(["react-flow__nodesselection","react-flow__container",f]),style:{transform:y},children:ru.jsx("div",{ref:c,className:"react-flow__nodesselection-rect",onContextMenu:j,tabIndex:l?void 0:-1,onKeyDown:l?void 0:F,style:{width:n,height:i}})})}var gN=typeof window<"u"?window:void 0,BD=(u)=>{return{nodesSelectionActive:u.nodesSelectionActive,userSelectionActive:u.userSelectionActive}};function JW({children:u,onPaneClick:f,onPaneMouseEnter:l,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,paneClickDistance:_,deleteKeyCode:$,selectionKeyCode:c,selectionOnDrag:A,selectionMode:j,onSelectionStart:F,onSelectionEnd:U,multiSelectionKeyCode:Q,panActivationKeyCode:w,zoomActivationKeyCode:L,elementsSelectable:J,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:W,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:E,defaultViewport:D,translateExtent:h,minZoom:B,maxZoom:X,preventScrolling:m,onSelectionContextMenu:O,noWheelClassName:p,noPanClassName:Y,disableKeyboardA11y:v,onViewportChange:T,isControlledViewport:S}){let{nodesSelectionActive:k,userSelectionActive:I}=uf(BD,Kf),b=z$(c,{target:gN}),o=z$(w,{target:gN}),s=o||E,x=o||W,fu=A&&s!==!0,$u=b||I||fu;return cD({deleteKeyCode:$,multiSelectionKeyCode:Q}),ru.jsx(FD,{onPaneContextMenu:i,elementsSelectable:J,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:x,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:!b&&s,defaultViewport:D,translateExtent:h,minZoom:B,maxZoom:X,zoomActivationKeyCode:L,preventScrolling:m,noWheelClassName:p,noPanClassName:Y,onViewportChange:T,isControlledViewport:S,paneClickDistance:_,selectionOnDrag:fu,children:ru.jsxs(qD,{onSelectionStart:F,onSelectionEnd:U,onPaneClick:f,onPaneMouseEnter:l,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,panOnDrag:s,isSelecting:!!$u,selectionMode:j,selectionKeyPressed:b,paneClickDistance:_,selectionOnDrag:fu,children:[u,k&&ru.jsx(HD,{onSelectionContextMenu:O,noPanClassName:Y,disableKeyboardA11y:v})]})})}JW.displayName="FlowRenderer";var VD=yu.memo(JW),DD=(u)=>(f)=>{return u?R6(f.nodeLookup,{x:0,y:0,width:f.width,height:f.height},f.transform,!0).map((l)=>l.id):Array.from(f.nodeLookup.keys())};function XD(u){return uf(yu.useCallback(DD(u),[u]),Kf)}var YD=(u)=>u.updateNodeInternals;function SD(){let u=uf(YD),[f]=yu.useState(()=>{if(typeof ResizeObserver>"u")return null;return new ResizeObserver((l)=>{let r=new Map;l.forEach((n)=>{let i=n.target.getAttribute("data-id");r.set(i,{id:i,nodeElement:n.target,force:!0})}),u(r)})});return yu.useEffect(()=>{return()=>{f?.disconnect()}},[f]),f}function mD({node:u,nodeType:f,hasDimensions:l,resizeObserver:r}){let n=Tf(),i=yu.useRef(null),y=yu.useRef(null),_=yu.useRef(u.sourcePosition),$=yu.useRef(u.targetPosition),c=yu.useRef(f),A=l&&!!u.internals.handleBounds;return yu.useEffect(()=>{if(i.current&&!u.hidden&&(!A||y.current!==i.current)){if(y.current)r?.unobserve(y.current);r?.observe(i.current),y.current=i.current}},[A,u.hidden]),yu.useEffect(()=>{return()=>{if(y.current)r?.unobserve(y.current),y.current=null}},[]),yu.useEffect(()=>{if(i.current){let j=c.current!==f,F=_.current!==u.sourcePosition,U=$.current!==u.targetPosition;if(j||F||U)c.current=f,_.current=u.sourcePosition,$.current=u.targetPosition,n.getState().updateNodeInternals(new Map([[u.id,{id:u.id,nodeElement:i.current,force:!0}]]))}},[u.id,f,u.sourcePosition,u.targetPosition]),i}function pD({id:u,onClick:f,onMouseEnter:l,onMouseMove:r,onMouseLeave:n,onContextMenu:i,onDoubleClick:y,nodesDraggable:_,elementsSelectable:$,nodesConnectable:c,nodesFocusable:A,resizeObserver:j,noDragClassName:F,noPanClassName:U,disableKeyboardA11y:Q,rfId:w,nodeTypes:L,nodeClickDistance:J,onError:N}){let{node:q,internals:W,isParent:z}=uf((tu)=>{let ju=tu.nodeLookup.get(u),Gu=tu.parentLookup.has(u);return{node:ju,internals:ju.internals,isParent:Gu}},Kf),Z=q.type||"default",H=L?.[Z]||IN[Z];if(H===void 0)N?.("003",tr.error003(Z)),Z="default",H=L?.default||IN.default;let E=!!(q.draggable||_&&typeof q.draggable>"u"),D=!!(q.selectable||$&&typeof q.selectable>"u"),h=!!(q.connectable||c&&typeof q.connectable>"u"),B=!!(q.focusable||A&&typeof q.focusable>"u"),X=Tf(),m=bA(q),O=mD({node:q,nodeType:Z,hasDimensions:m,resizeObserver:j}),p=AW({nodeRef:O,disabled:q.hidden||!E,noDragClassName:F,handleSelector:q.dragHandle,nodeId:u,isSelectable:D,nodeClickDistance:J}),Y=jW();if(q.hidden)return null;let v=$0(q),T=ZD(q),S=D||E||f||l||r||n,k=l?(tu)=>l(tu,{...W.userNode}):void 0,I=r?(tu)=>r(tu,{...W.userNode}):void 0,b=n?(tu)=>n(tu,{...W.userNode}):void 0,o=i?(tu)=>i(tu,{...W.userNode}):void 0,s=y?(tu)=>y(tu,{...W.userNode}):void 0,x=(tu)=>{let{selectNodesOnDrag:ju,nodeDragThreshold:Gu}=X.getState();if(D&&(!ju||!E||Gu>0))$9({id:u,store:X,nodeRef:O});if(f)f(tu,{...W.userNode})},fu=(tu)=>{if(gA(tu.nativeEvent)||Q)return;if(XA.includes(tu.key)&&D){let ju=tu.key==="Escape";$9({id:u,store:X,unselect:ju,nodeRef:O})}else if(E&&q.selected&&Object.prototype.hasOwnProperty.call(l8,tu.key)){tu.preventDefault();let{ariaLabelConfig:ju}=X.getState();X.setState({ariaLiveMessage:ju["node.a11yDescription.ariaLiveMessage"]({direction:tu.key.replace("Arrow","").toLowerCase(),x:~~W.positionAbsolute.x,y:~~W.positionAbsolute.y})}),Y({direction:l8[tu.key],factor:tu.shiftKey?4:1})}},$u=()=>{if(Q||!O.current?.matches(":focus-visible"))return;let{transform:tu,width:ju,height:Gu,autoPanOnNodeFocus:qu,setCenter:P}=X.getState();if(!qu)return;if(!(R6(new Map([[u,q]]),{x:0,y:0,width:ju,height:Gu},tu,!0).length>0))P(q.position.x+v.width/2,q.position.y+v.height/2,{zoom:tu[2]})};return ru.jsx("div",{className:Xf(["react-flow__node",`react-flow__node-${Z}`,{[U]:E},q.className,{selected:q.selected,selectable:D,parent:z,draggable:E,dragging:p}]),ref:O,style:{zIndex:W.z,transform:`translate(${W.positionAbsolute.x}px,${W.positionAbsolute.y}px)`,pointerEvents:S?"all":"none",visibility:m?"visible":"hidden",...q.style,...T},"data-id":u,"data-testid":`rf__node-${u}`,onMouseEnter:k,onMouseMove:I,onMouseLeave:b,onContextMenu:o,onClick:x,onDoubleClick:s,onKeyDown:B?fu:void 0,tabIndex:B?0:void 0,onFocus:B?$u:void 0,role:q.ariaRole??(B?"group":void 0),"aria-roledescription":"node","aria-describedby":Q?void 0:`${iW}-${w}`,"aria-label":q.ariaLabel,...q.domAttributes,children:ru.jsx(WD,{value:u,children:ru.jsx(H,{id:u,data:q.data,type:Z,positionAbsoluteX:W.positionAbsolute.x,positionAbsoluteY:W.positionAbsolute.y,selected:q.selected??!1,selectable:D,draggable:E,deletable:q.deletable??!0,isConnectable:h,sourcePosition:q.sourcePosition,targetPosition:q.targetPosition,dragging:p,dragHandle:q.dragHandle,zIndex:W.z,parentId:q.parentId,...v})})})}var PD=yu.memo(pD),MD=(u)=>({nodesDraggable:u.nodesDraggable,nodesConnectable:u.nodesConnectable,nodesFocusable:u.nodesFocusable,elementsSelectable:u.elementsSelectable,onError:u.onError});function UW(u){let{nodesDraggable:f,nodesConnectable:l,nodesFocusable:r,elementsSelectable:n,onError:i}=uf(MD,Kf),y=XD(u.onlyRenderVisibleElements),_=SD();return ru.jsx("div",{className:"react-flow__nodes",style:i8,children:y.map(($)=>{return ru.jsx(PD,{id:$,nodeTypes:u.nodeTypes,nodeExtent:u.nodeExtent,onClick:u.onNodeClick,onMouseEnter:u.onNodeMouseEnter,onMouseMove:u.onNodeMouseMove,onMouseLeave:u.onNodeMouseLeave,onContextMenu:u.onNodeContextMenu,onDoubleClick:u.onNodeDoubleClick,noDragClassName:u.noDragClassName,noPanClassName:u.noPanClassName,rfId:u.rfId,disableKeyboardA11y:u.disableKeyboardA11y,resizeObserver:_,nodesDraggable:f,nodesConnectable:l,nodesFocusable:r,elementsSelectable:n,nodeClickDistance:u.nodeClickDistance,onError:i},$)})})}UW.displayName="NodeRenderer";var CD=yu.memo(UW);function RD(u){return uf(yu.useCallback((l)=>{if(!u)return l.edges.map((n)=>n.id);let r=[];if(l.width&&l.height)for(let n of l.edges){let i=l.nodeLookup.get(n.source),y=l.nodeLookup.get(n.target);if(i&&y&&fN({sourceNode:i,targetNode:y,width:l.width,height:l.height,transform:l.transform}))r.push(n.id)}return r},[u]),Kf)}var xD=({color:u="none",strokeWidth:f=1})=>{let l={strokeWidth:f,...u&&{stroke:u}};return ru.jsx("polyline",{className:"arrow",style:l,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},hD=({color:u="none",strokeWidth:f=1})=>{let l={strokeWidth:f,...u&&{stroke:u,fill:u}};return ru.jsx("polyline",{className:"arrowclosed",style:l,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},sN={[Yn.Arrow]:xD,[Yn.ArrowClosed]:hD};function bD(u){let f=Tf();return yu.useMemo(()=>{if(!Object.prototype.hasOwnProperty.call(sN,u))return f.getState().onError?.("009",tr.error009(u)),null;return sN[u]},[u])}var vD=({id:u,type:f,color:l,width:r=12.5,height:n=12.5,markerUnits:i="strokeWidth",strokeWidth:y,orient:_="auto-start-reverse"})=>{let $=bD(f);if(!$)return null;return ru.jsx("marker",{className:"react-flow__arrowhead",id:u,markerWidth:`${r}`,markerHeight:`${n}`,viewBox:"-10 -10 20 20",markerUnits:i,orient:_,refX:"0",refY:"0",children:ru.jsx($,{color:l,strokeWidth:y})})},QW=({defaultColor:u,rfId:f})=>{let l=uf((i)=>i.edges),r=uf((i)=>i.defaultEdgeOptions),n=yu.useMemo(()=>{return rN(l,{id:f,defaultColor:u,defaultMarkerStart:r?.markerStart,defaultMarkerEnd:r?.markerEnd})},[l,r,f,u]);if(!n.length)return null;return ru.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:ru.jsx("defs",{children:n.map((i)=>ru.jsx(vD,{id:i.id,type:i.type,color:i.color,width:i.width,height:i.height,markerUnits:i.markerUnits,strokeWidth:i.strokeWidth,orient:i.orient},i.id))})})};QW.displayName="MarkerDefinitions";var kD=yu.memo(QW);function qW({x:u,y:f,label:l,labelStyle:r,labelShowBg:n=!0,labelBgStyle:i,labelBgPadding:y=[2,4],labelBgBorderRadius:_=2,children:$,className:c,...A}){let[j,F]=yu.useState({x:1,y:0,width:0,height:0}),U=Xf(["react-flow__edge-textwrapper",c]),Q=yu.useRef(null);if(yu.useEffect(()=>{if(Q.current){let w=Q.current.getBBox();F({x:w.x,y:w.y,width:w.width,height:w.height})}},[l]),!l)return null;return ru.jsxs("g",{transform:`translate(${u-j.width/2} ${f-j.height/2})`,className:U,visibility:j.width?"visible":"hidden",...A,children:[n&&ru.jsx("rect",{width:j.width+2*y[0],x:-y[0],y:-y[1],height:j.height+2*y[1],className:"react-flow__edge-textbg",style:i,rx:_,ry:_}),ru.jsx("text",{className:"react-flow__edge-text",y:j.height/2,dy:"0.3em",ref:Q,style:r,children:l}),$]})}qW.displayName="EdgeText";var ID=yu.memo(qW);function cy({path:u,labelX:f,labelY:l,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:_,labelBgBorderRadius:$,interactionWidth:c=20,...A}){return ru.jsxs(ru.Fragment,{children:[ru.jsx("path",{...A,d:u,fill:"none",className:Xf(["react-flow__edge-path",A.className])}),c?ru.jsx("path",{d:u,fill:"none",strokeOpacity:0,strokeWidth:c,className:"react-flow__edge-interaction"}):null,r&&Gr(f)&&Gr(l)?ru.jsx(ID,{x:f,y:l,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:_,labelBgBorderRadius:$}):null]})}function aN({pos:u,x1:f,y1:l,x2:r,y2:n}){if(u===Lu.Left||u===Lu.Right)return[0.5*(f+r),l];return[f,0.5*(l+n)]}function NW({sourceX:u,sourceY:f,sourcePosition:l=Lu.Bottom,targetX:r,targetY:n,targetPosition:i=Lu.Top}){let[y,_]=aN({pos:l,x1:u,y1:f,x2:r,y2:n}),[$,c]=aN({pos:i,x1:r,y1:n,x2:u,y2:f}),[A,j,F,U]=v6({sourceX:u,sourceY:f,targetX:r,targetY:n,sourceControlX:y,sourceControlY:_,targetControlX:$,targetControlY:c});return[`M${u},${f} C${y},${_} ${$},${c} ${r},${n}`,A,j,F,U]}function WW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,sourcePosition:y,targetPosition:_,label:$,labelStyle:c,labelShowBg:A,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:w,markerStart:L,interactionWidth:J})=>{let[N,q,W]=NW({sourceX:l,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:_}),z=u.isInternal?void 0:f;return ru.jsx(cy,{id:z,path:N,labelX:q,labelY:W,label:$,labelStyle:c,labelShowBg:A,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:w,markerStart:L,interactionWidth:J})})}var gD=WW({isInternal:!1}),wW=WW({isInternal:!0});gD.displayName="SimpleBezierEdge";wW.displayName="SimpleBezierEdgeInternal";function LW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:c,labelBgPadding:A,labelBgBorderRadius:j,style:F,sourcePosition:U=Lu.Bottom,targetPosition:Q=Lu.Top,markerEnd:w,markerStart:L,pathOptions:J,interactionWidth:N})=>{let[q,W,z]=G$({sourceX:l,sourceY:r,sourcePosition:U,targetX:n,targetY:i,targetPosition:Q,borderRadius:J?.borderRadius,offset:J?.offset,stepPosition:J?.stepPosition}),Z=u.isInternal?void 0:f;return ru.jsx(cy,{id:Z,path:q,labelX:W,labelY:z,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:c,labelBgPadding:A,labelBgBorderRadius:j,style:F,markerEnd:w,markerStart:L,interactionWidth:N})})}var KW=LW({isInternal:!1}),GW=LW({isInternal:!0});KW.displayName="SmoothStepEdge";GW.displayName="SmoothStepEdgeInternal";function zW(u){return yu.memo(({id:f,...l})=>{let r=u.isInternal?void 0:f;return ru.jsx(KW,{...l,id:r,pathOptions:yu.useMemo(()=>({borderRadius:0,offset:l.pathOptions?.offset}),[l.pathOptions?.offset])})})}var sD=zW({isInternal:!1}),TW=zW({isInternal:!0});sD.displayName="StepEdge";TW.displayName="StepEdgeInternal";function EW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:c,labelBgPadding:A,labelBgBorderRadius:j,style:F,markerEnd:U,markerStart:Q,interactionWidth:w})=>{let[L,J,N]=I6({sourceX:l,sourceY:r,targetX:n,targetY:i}),q=u.isInternal?void 0:f;return ru.jsx(cy,{id:q,path:L,labelX:J,labelY:N,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:c,labelBgPadding:A,labelBgBorderRadius:j,style:F,markerEnd:U,markerStart:Q,interactionWidth:w})})}var aD=EW({isInternal:!1}),ZW=EW({isInternal:!0});aD.displayName="StraightEdge";ZW.displayName="StraightEdgeInternal";function OW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,sourcePosition:y=Lu.Bottom,targetPosition:_=Lu.Top,label:$,labelStyle:c,labelShowBg:A,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:w,markerStart:L,pathOptions:J,interactionWidth:N})=>{let[q,W,z]=k6({sourceX:l,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:_,curvature:J?.curvature}),Z=u.isInternal?void 0:f;return ru.jsx(cy,{id:Z,path:q,labelX:W,labelY:z,label:$,labelStyle:c,labelShowBg:A,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:w,markerStart:L,interactionWidth:N})})}var oD=OW({isInternal:!1}),HW=OW({isInternal:!0});oD.displayName="BezierEdge";HW.displayName="BezierEdgeInternal";var oN={default:HW,straight:ZW,step:TW,smoothstep:GW,simplebezier:wW},dN={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null},dD=(u,f,l)=>{if(l===Lu.Left)return u-f;if(l===Lu.Right)return u+f;return u},eD=(u,f,l)=>{if(l===Lu.Top)return u-f;if(l===Lu.Bottom)return u+f;return u},eN="react-flow__edgeupdater";function uW({position:u,centerX:f,centerY:l,radius:r=10,onMouseDown:n,onMouseEnter:i,onMouseOut:y,type:_}){return ru.jsx("circle",{onMouseDown:n,onMouseEnter:i,onMouseOut:y,className:Xf([eN,`${eN}-${_}`]),cx:dD(f,r,u),cy:eD(l,r,u),r,stroke:"transparent",fill:"transparent"})}function uX({isReconnectable:u,reconnectRadius:f,edge:l,sourceX:r,sourceY:n,targetX:i,targetY:y,sourcePosition:_,targetPosition:$,onReconnect:c,onReconnectStart:A,onReconnectEnd:j,setReconnecting:F,setUpdateHover:U}){let Q=Tf(),w=(W,z)=>{if(W.button!==0)return;let{autoPanOnConnect:Z,domNode:H,connectionMode:E,connectionRadius:D,lib:h,onConnectStart:B,cancelConnection:X,nodeLookup:m,rfId:O,panBy:p,updateConnection:Y}=Q.getState(),v=z.type==="target",T=(I,b)=>{F(!1),j?.(I,l,z.type,b)},S=(I)=>c?.(l,I),k=(I,b)=>{F(!0),A?.(W,l,z.type),B?.(I,b)};o6.onPointerDown(W.nativeEvent,{autoPanOnConnect:Z,connectionMode:E,connectionRadius:D,domNode:H,handleId:z.id,nodeId:z.nodeId,nodeLookup:m,isTarget:v,edgeUpdaterType:z.type,lib:h,flowId:O,cancelConnection:X,panBy:p,isValidConnection:(...I)=>Q.getState().isValidConnection?.(...I)??!0,onConnect:S,onConnectStart:k,onConnectEnd:(...I)=>Q.getState().onConnectEnd?.(...I),onReconnectEnd:T,updateConnection:Y,getTransform:()=>Q.getState().transform,getFromHandle:()=>Q.getState().connection.fromHandle,dragThreshold:Q.getState().connectionDragThreshold,handleDomNode:W.currentTarget})},L=(W)=>w(W,{nodeId:l.target,id:l.targetHandle??null,type:"target"}),J=(W)=>w(W,{nodeId:l.source,id:l.sourceHandle??null,type:"source"}),N=()=>U(!0),q=()=>U(!1);return ru.jsxs(ru.Fragment,{children:[(u===!0||u==="source")&&ru.jsx(uW,{position:_,centerX:r,centerY:n,radius:f,onMouseDown:L,onMouseEnter:N,onMouseOut:q,type:"source"}),(u===!0||u==="target")&&ru.jsx(uW,{position:$,centerX:i,centerY:y,radius:f,onMouseDown:J,onMouseEnter:N,onMouseOut:q,type:"target"})]})}function fX({id:u,edgesFocusable:f,edgesReconnectable:l,elementsSelectable:r,onClick:n,onDoubleClick:i,onContextMenu:y,onMouseEnter:_,onMouseMove:$,onMouseLeave:c,reconnectRadius:A,onReconnect:j,onReconnectStart:F,onReconnectEnd:U,rfId:Q,edgeTypes:w,noPanClassName:L,onError:J,disableKeyboardA11y:N}){let q=uf((P)=>P.edgeLookup.get(u)),W=uf((P)=>P.defaultEdgeOptions);q=W?{...W,...q}:q;let z=q.type||"default",Z=w?.[z]||oN[z];if(Z===void 0)J?.("011",tr.error011(z)),z="default",Z=w?.default||oN.default;let H=!!(q.focusable||f&&typeof q.focusable>"u"),E=typeof j<"u"&&(q.reconnectable||l&&typeof q.reconnectable>"u"),D=!!(q.selectable||r&&typeof q.selectable>"u"),h=yu.useRef(null),[B,X]=yu.useState(!1),[m,O]=yu.useState(!1),p=Tf(),{zIndex:Y,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b}=uf(yu.useCallback((P)=>{let e=P.nodeLookup.get(q.source),uu=P.nodeLookup.get(q.target);if(!e||!uu)return{zIndex:q.zIndex,...dN};let Wu=lN({id:u,sourceNode:e,targetNode:uu,sourceHandle:q.sourceHandle||null,targetHandle:q.targetHandle||null,connectionMode:P.connectionMode,onError:J});return{zIndex:uN({selected:q.selected,zIndex:q.zIndex,sourceNode:e,targetNode:uu,elevateOnSelect:P.elevateEdgesOnSelect,zIndexMode:P.zIndexMode}),...Wu||dN}},[q.source,q.target,q.sourceHandle,q.targetHandle,q.selected,q.zIndex]),Kf),o=yu.useMemo(()=>q.markerStart?`url('#${g6(q.markerStart,Q)}')`:void 0,[q.markerStart,Q]),s=yu.useMemo(()=>q.markerEnd?`url('#${g6(q.markerEnd,Q)}')`:void 0,[q.markerEnd,Q]);if(q.hidden||v===null||T===null||S===null||k===null)return null;let x=(P)=>{let{addSelectedEdges:e,unselectNodesAndEdges:uu,multiSelectionActive:Wu}=p.getState();if(D)if(p.setState({nodesSelectionActive:!1}),q.selected&&Wu)uu({nodes:[],edges:[q]}),h.current?.blur();else e([u]);if(n)n(P,q)},fu=i?(P)=>{i(P,{...q})}:void 0,$u=y?(P)=>{y(P,{...q})}:void 0,tu=_?(P)=>{_(P,{...q})}:void 0,ju=$?(P)=>{$(P,{...q})}:void 0,Gu=c?(P)=>{c(P,{...q})}:void 0,qu=(P)=>{if(!N&&XA.includes(P.key)&&D){let{unselectNodesAndEdges:e,addSelectedEdges:uu}=p.getState();if(P.key==="Escape")h.current?.blur(),e({edges:[q]});else uu([u])}};return ru.jsx("svg",{style:{zIndex:Y},children:ru.jsxs("g",{className:Xf(["react-flow__edge",`react-flow__edge-${z}`,q.className,L,{selected:q.selected,animated:q.animated,inactive:!D&&!n,updating:B,selectable:D}]),onClick:x,onDoubleClick:fu,onContextMenu:$u,onMouseEnter:tu,onMouseMove:ju,onMouseLeave:Gu,onKeyDown:H?qu:void 0,tabIndex:H?0:void 0,role:q.ariaRole??(H?"group":"img"),"aria-roledescription":"edge","data-id":u,"data-testid":`rf__edge-${u}`,"aria-label":q.ariaLabel===null?void 0:q.ariaLabel||`Edge from ${q.source} to ${q.target}`,"aria-describedby":H?`${yW}-${Q}`:void 0,ref:h,...q.domAttributes,children:[!m&&ru.jsx(Z,{id:u,source:q.source,target:q.target,type:q.type,selected:q.selected,animated:q.animated,selectable:D,deletable:q.deletable??!0,label:q.label,labelStyle:q.labelStyle,labelShowBg:q.labelShowBg,labelBgStyle:q.labelBgStyle,labelBgPadding:q.labelBgPadding,labelBgBorderRadius:q.labelBgBorderRadius,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b,data:q.data,style:q.style,sourceHandleId:q.sourceHandle,targetHandleId:q.targetHandle,markerStart:o,markerEnd:s,pathOptions:"pathOptions"in q?q.pathOptions:void 0,interactionWidth:q.interactionWidth}),E&&ru.jsx(uX,{edge:q,isReconnectable:E,reconnectRadius:A,onReconnect:j,onReconnectStart:F,onReconnectEnd:U,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b,setUpdateHover:X,setReconnecting:O})]})})}var lX=yu.memo(fX),rX=(u)=>({edgesFocusable:u.edgesFocusable,edgesReconnectable:u.edgesReconnectable,elementsSelectable:u.elementsSelectable,connectionMode:u.connectionMode,onError:u.onError});function BW({defaultMarkerColor:u,onlyRenderVisibleElements:f,rfId:l,edgeTypes:r,noPanClassName:n,onReconnect:i,onEdgeContextMenu:y,onEdgeMouseEnter:_,onEdgeMouseMove:$,onEdgeMouseLeave:c,onEdgeClick:A,reconnectRadius:j,onEdgeDoubleClick:F,onReconnectStart:U,onReconnectEnd:Q,disableKeyboardA11y:w}){let{edgesFocusable:L,edgesReconnectable:J,elementsSelectable:N,onError:q}=uf(rX,Kf),W=RD(f);return ru.jsxs("div",{className:"react-flow__edges",children:[ru.jsx(kD,{defaultColor:u,rfId:l}),W.map((z)=>{return ru.jsx(lX,{id:z,edgesFocusable:L,edgesReconnectable:J,elementsSelectable:N,noPanClassName:n,onReconnect:i,onContextMenu:y,onMouseEnter:_,onMouseMove:$,onMouseLeave:c,onClick:A,reconnectRadius:j,onDoubleClick:F,onReconnectStart:U,onReconnectEnd:Q,rfId:l,onError:q,edgeTypes:r,disableKeyboardA11y:w},z)})]})}BW.displayName="EdgeRenderer";var nX=yu.memo(BW),iX=(u)=>`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]})`;function yX({children:u}){let f=uf(iX);return ru.jsx("div",{className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:f},children:u})}function _X(u){let f=t9(),l=yu.useRef(!1);yu.useEffect(()=>{if(!l.current&&f.viewportInitialized&&u)setTimeout(()=>u(f),1),l.current=!0},[u,f.viewportInitialized])}var $X=(u)=>u.panZoom?.syncViewport;function tX(u){let f=uf($X),l=Tf();return yu.useEffect(()=>{if(u)f?.(u),l.setState({transform:[u.x,u.y,u.zoom]})},[u,f]),null}function fW(u){return u.connection.inProgress?{...u.connection,to:yy(u.connection.to,u.transform)}:{...u.connection}}function cX(u){if(u)return(l)=>{let r=fW(l);return u(r)};return fW}function AX(u){let f=cX(u);return uf(f,Kf)}var jX=(u)=>({nodesConnectable:u.nodesConnectable,isValid:u.connection.isValid,inProgress:u.connection.inProgress,width:u.width,height:u.height});function FX({containerStyle:u,style:f,type:l,component:r}){let{nodesConnectable:n,width:i,height:y,isValid:_,inProgress:$}=uf(jX,Kf);if(!(i&&n&&$))return null;return ru.jsx("svg",{style:u,width:i,height:y,className:"react-flow__connectionline react-flow__container",children:ru.jsx("g",{className:Xf(["react-flow__connection",mA(_)]),children:ru.jsx(VW,{style:f,type:l,CustomComponent:r,isValid:_})})})}var VW=({style:u,type:f=_0.Bezier,CustomComponent:l,isValid:r})=>{let{inProgress:n,from:i,fromNode:y,fromHandle:_,fromPosition:$,to:c,toNode:A,toHandle:j,toPosition:F,pointer:U}=AX();if(!n)return;if(l)return ru.jsx(l,{connectionLineType:f,connectionLineStyle:u,fromNode:y,fromHandle:_,fromX:i.x,fromY:i.y,toX:c.x,toY:c.y,fromPosition:$,toPosition:F,connectionStatus:mA(r),toNode:A,toHandle:j,pointer:U});let Q="",w={sourceX:i.x,sourceY:i.y,sourcePosition:$,targetX:c.x,targetY:c.y,targetPosition:F};switch(f){case _0.Bezier:[Q]=k6(w);break;case _0.SimpleBezier:[Q]=NW(w);break;case _0.Step:[Q]=G$({...w,borderRadius:0});break;case _0.SmoothStep:[Q]=G$(w);break;default:[Q]=I6(w)}return ru.jsx("path",{d:Q,fill:"none",className:"react-flow__connection-path",style:u})};VW.displayName="ConnectionLine";var JX={};function lW(u=JX){let f=yu.useRef(u),l=Tf();yu.useEffect(()=>{},[u])}function UX(){let u=Tf(),f=yu.useRef(!1);yu.useEffect(()=>{},[])}function DW({nodeTypes:u,edgeTypes:f,onInit:l,onNodeClick:r,onEdgeClick:n,onNodeDoubleClick:i,onEdgeDoubleClick:y,onNodeMouseEnter:_,onNodeMouseMove:$,onNodeMouseLeave:c,onNodeContextMenu:A,onSelectionContextMenu:j,onSelectionStart:F,onSelectionEnd:U,connectionLineType:Q,connectionLineStyle:w,connectionLineComponent:L,connectionLineContainerStyle:J,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,deleteKeyCode:E,onlyRenderVisibleElements:D,elementsSelectable:h,defaultViewport:B,translateExtent:X,minZoom:m,maxZoom:O,preventScrolling:p,defaultMarkerColor:Y,zoomOnScroll:v,zoomOnPinch:T,panOnScroll:S,panOnScrollSpeed:k,panOnScrollMode:I,zoomOnDoubleClick:b,panOnDrag:o,onPaneClick:s,onPaneMouseEnter:x,onPaneMouseMove:fu,onPaneMouseLeave:$u,onPaneScroll:tu,onPaneContextMenu:ju,paneClickDistance:Gu,nodeClickDistance:qu,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:Wu,reconnectRadius:g,onReconnect:Qu,onReconnectStart:Tu,onReconnectEnd:Zu,noDragClassName:Xu,noWheelClassName:ff,noPanClassName:_f,disableKeyboardA11y:Jf,nodeExtent:mf,rfId:Yl,viewport:Al,onViewportChange:jl}){return lW(u),lW(f),UX(),_X(l),tX(Al),ru.jsx(VD,{onPaneClick:s,onPaneMouseEnter:x,onPaneMouseMove:fu,onPaneMouseLeave:$u,onPaneContextMenu:ju,onPaneScroll:tu,paneClickDistance:Gu,deleteKeyCode:E,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,onSelectionStart:F,onSelectionEnd:U,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,elementsSelectable:h,zoomOnScroll:v,zoomOnPinch:T,zoomOnDoubleClick:b,panOnScroll:S,panOnScrollSpeed:k,panOnScrollMode:I,panOnDrag:o,defaultViewport:B,translateExtent:X,minZoom:m,maxZoom:O,onSelectionContextMenu:j,preventScrolling:p,noDragClassName:Xu,noWheelClassName:ff,noPanClassName:_f,disableKeyboardA11y:Jf,onViewportChange:jl,isControlledViewport:!!Al,children:ru.jsxs(yX,{children:[ru.jsx(nX,{edgeTypes:f,onEdgeClick:n,onEdgeDoubleClick:y,onReconnect:Qu,onReconnectStart:Tu,onReconnectEnd:Zu,onlyRenderVisibleElements:D,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:Wu,reconnectRadius:g,defaultMarkerColor:Y,noPanClassName:_f,disableKeyboardA11y:Jf,rfId:Yl}),ru.jsx(FX,{style:w,type:Q,component:L,containerStyle:J}),ru.jsx("div",{className:"react-flow__edgelabel-renderer"}),ru.jsx(CD,{nodeTypes:u,onNodeClick:r,onNodeDoubleClick:i,onNodeMouseEnter:_,onNodeMouseMove:$,onNodeMouseLeave:c,onNodeContextMenu:A,nodeClickDistance:qu,onlyRenderVisibleElements:D,noPanClassName:_f,noDragClassName:Xu,disableKeyboardA11y:Jf,nodeExtent:mf,rfId:Yl}),ru.jsx("div",{className:"react-flow__viewport-portal"})]})})}DW.displayName="GraphView";var QX=yu.memo(DW),rW=({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$=0.5,maxZoom:c=2,nodeOrigin:A,nodeExtent:j,zIndexMode:F="basic"}={})=>{let U=new Map,Q=new Map,w=new Map,L=new Map,J=r??f??[],N=l??u??[],q=A??[0,0],W=j??ly;l9(w,L,J);let{nodesInitialized:z}=s6(N,U,Q,{nodeOrigin:q,nodeExtent:W,zIndexMode:F}),Z=[0,0,1];if(y&&n&&i){let H=ry(U,{filter:(B)=>!!((B.width||B.initialWidth)&&(B.height||B.initialHeight))}),{x:E,y:D,zoom:h}=K$(H,n,i,$,c,_?.padding??0.1);Z=[E,D,h]}return{rfId:"1",width:n??0,height:i??0,transform:Z,nodes:N,nodesInitialized:z,nodeLookup:U,parentLookup:Q,edges:J,edgeLookup:L,connectionLookup:w,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:l!==void 0,hasDefaultEdges:r!==void 0,panZoom:null,minZoom:$,maxZoom:c,translateExtent:ly,nodeExtent:W,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:Xn.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:q,nodeDragThreshold:1,connectionDragThreshold:1,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesReconnectable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,elevateEdgesOnSelect:!0,selectNodesOnDrag:!0,multiSelectionActive:!1,fitViewQueued:y??!1,fitViewOptions:_,fitViewResolver:null,connection:{...SA},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:hA,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:YA,zIndexMode:F,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},qX=({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$,maxZoom:c,nodeOrigin:A,nodeExtent:j,zIndexMode:F})=>YN((U,Q)=>{async function w(){let{nodeLookup:L,panZoom:J,fitViewOptions:N,fitViewResolver:q,width:W,height:z,minZoom:Z,maxZoom:H}=Q();if(!J)return;await gq({nodes:L,width:W,height:z,panZoom:J,minZoom:Z,maxZoom:H},N),q?.resolve(!0),U({fitViewResolver:null})}return{...rW({nodes:u,edges:f,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$,maxZoom:c,nodeOrigin:A,nodeExtent:j,defaultNodes:l,defaultEdges:r,zIndexMode:F}),setNodes:(L)=>{let{nodeLookup:J,parentLookup:N,nodeOrigin:q,elevateNodesOnSelect:W,fitViewQueued:z,zIndexMode:Z,nodesSelectionActive:H}=Q(),{nodesInitialized:E,hasSelectedNodes:D}=s6(L,J,N,{nodeOrigin:q,nodeExtent:j,elevateNodesOnSelect:W,checkEquality:!0,zIndexMode:Z}),h=H&&D;if(z&&E)w(),U({nodes:L,nodesInitialized:E,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:h});else U({nodes:L,nodesInitialized:E,nodesSelectionActive:h})},setEdges:(L)=>{let{connectionLookup:J,edgeLookup:N}=Q();l9(J,N,L),U({edges:L})},setDefaultNodesAndEdges:(L,J)=>{if(L){let{setNodes:N}=Q();N(L),U({hasDefaultNodes:!0})}if(J){let{setEdges:N}=Q();N(J),U({hasDefaultEdges:!0})}},updateNodeInternals:(L)=>{let{triggerNodeChanges:J,nodeLookup:N,parentLookup:q,domNode:W,nodeOrigin:z,nodeExtent:Z,debug:H,fitViewQueued:E,zIndexMode:D}=Q(),{changes:h,updatedInternals:B}=_N(L,N,q,W,z,Z,D);if(!B)return;if(iN(N,q,{nodeOrigin:z,nodeExtent:Z,zIndexMode:D}),E)w(),U({fitViewQueued:!1,fitViewOptions:void 0});else U({});if(h?.length>0){if(H)console.log("React Flow: trigger node changes",h);J?.(h)}},updateNodePositions:(L,J=!1)=>{let N=[],q=[],{nodeLookup:W,triggerNodeChanges:z,connection:Z,updateConnection:H,onNodesChangeMiddlewareMap:E}=Q();for(let[D,h]of L){let B=W.get(D),X=!!(B?.expandParent&&B?.parentId&&h?.position),m={id:D,type:"position",position:X?{x:Math.max(0,h.position.x),y:Math.max(0,h.position.y)}:h.position,dragging:J};if(B&&Z.inProgress&&Z.fromNode.id===B.id){let O=Sn(B,Z.fromHandle,Lu.Left,!0);H({...Z,from:O})}if(X&&B.parentId)N.push({id:D,parentId:B.parentId,rect:{...h.internals.positionAbsolute,width:h.measured.width??0,height:h.measured.height??0}});q.push(m)}if(N.length>0){let{parentLookup:D,nodeOrigin:h}=Q(),B=a6(N,W,D,h);q.push(...B)}for(let D of E.values())q=D(q);z(q)},triggerNodeChanges:(L)=>{let{onNodesChange:J,setNodes:N,nodes:q,hasDefaultNodes:W,debug:z}=Q();if(L?.length){if(W){let Z=lD(L,q);N(Z)}if(z)console.log("React Flow: trigger node changes",L);J?.(L)}},triggerEdgeChanges:(L)=>{let{onEdgesChange:J,setEdges:N,edges:q,hasDefaultEdges:W,debug:z}=Q();if(L?.length){if(W){let Z=rD(L,q);N(Z)}if(z)console.log("React Flow: trigger edge changes",L);J?.(L)}},addSelectedNodes:(L)=>{let{multiSelectionActive:J,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(J){let Z=L.map((H)=>P1(H,!0));W(Z);return}W(ty(q,new Set([...L]),!0)),z(ty(N))},addSelectedEdges:(L)=>{let{multiSelectionActive:J,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(J){let Z=L.map((H)=>P1(H,!0));z(Z);return}z(ty(N,new Set([...L]))),W(ty(q,new Set,!0))},unselectNodesAndEdges:({nodes:L,edges:J}={})=>{let{edges:N,nodes:q,nodeLookup:W,triggerNodeChanges:z,triggerEdgeChanges:Z}=Q(),H=L?L:q,E=J?J:N,D=[];for(let B of H){if(!B.selected)continue;let X=W.get(B.id);if(X)X.selected=!1;D.push(P1(B.id,!1))}let h=[];for(let B of E){if(!B.selected)continue;h.push(P1(B.id,!1))}z(D),Z(h)},setMinZoom:(L)=>{let{panZoom:J,maxZoom:N}=Q();J?.setScaleExtent([L,N]),U({minZoom:L})},setMaxZoom:(L)=>{let{panZoom:J,minZoom:N}=Q();J?.setScaleExtent([N,L]),U({maxZoom:L})},setTranslateExtent:(L)=>{Q().panZoom?.setTranslateExtent(L),U({translateExtent:L})},resetSelectedElements:()=>{let{edges:L,nodes:J,triggerNodeChanges:N,triggerEdgeChanges:q,elementsSelectable:W}=Q();if(!W)return;let z=J.reduce((H,E)=>E.selected?[...H,P1(E.id,!1)]:H,[]),Z=L.reduce((H,E)=>E.selected?[...H,P1(E.id,!1)]:H,[]);N(z),q(Z)},setNodeExtent:(L)=>{let{nodes:J,nodeLookup:N,parentLookup:q,nodeOrigin:W,elevateNodesOnSelect:z,nodeExtent:Z,zIndexMode:H}=Q();if(L[0][0]===Z[0][0]&&L[0][1]===Z[0][1]&&L[1][0]===Z[1][0]&&L[1][1]===Z[1][1])return;s6(J,N,q,{nodeOrigin:W,nodeExtent:L,elevateNodesOnSelect:z,checkEquality:!1,zIndexMode:H}),U({nodeExtent:L})},panBy:(L)=>{let{transform:J,width:N,height:q,panZoom:W,translateExtent:z}=Q();return $N({delta:L,panZoom:W,transform:J,translateExtent:z,width:N,height:q})},setCenter:async(L,J,N)=>{let{width:q,height:W,maxZoom:z,panZoom:Z}=Q();if(!Z)return Promise.resolve(!1);let H=typeof N?.zoom<"u"?N.zoom:z;return await Z.setViewport({x:q/2-L*H,y:W/2-J*H,zoom:H},{duration:N?.duration,ease:N?.ease,interpolate:N?.interpolate}),Promise.resolve(!0)},cancelConnection:()=>{U({connection:{...SA}})},updateConnection:(L)=>{U({connection:L})},reset:()=>U({...rW()})}},Object.is);function NX({initialNodes:u,initialEdges:f,defaultNodes:l,defaultEdges:r,initialWidth:n,initialHeight:i,initialMinZoom:y,initialMaxZoom:_,initialFitViewOptions:$,fitView:c,nodeOrigin:A,nodeExtent:j,zIndexMode:F,children:U}){let[Q]=yu.useState(()=>qX({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:c,minZoom:y,maxZoom:_,fitViewOptions:$,nodeOrigin:A,nodeExtent:j,zIndexMode:F}));return ru.jsx(mV,{value:Q,children:ru.jsx(yD,{children:U})})}function WX({children:u,nodes:f,edges:l,defaultNodes:r,defaultEdges:n,width:i,height:y,fitView:_,fitViewOptions:$,minZoom:c,maxZoom:A,nodeOrigin:j,nodeExtent:F,zIndexMode:U}){if(yu.useContext(r8))return ru.jsx(ru.Fragment,{children:u});return ru.jsx(NX,{initialNodes:f,initialEdges:l,defaultNodes:r,defaultEdges:n,initialWidth:i,initialHeight:y,fitView:_,initialFitViewOptions:$,initialMinZoom:c,initialMaxZoom:A,nodeOrigin:j,nodeExtent:F,zIndexMode:U,children:u})}var wX={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function LX({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,className:n,nodeTypes:i,edgeTypes:y,onNodeClick:_,onEdgeClick:$,onInit:c,onMove:A,onMoveStart:j,onMoveEnd:F,onConnect:U,onConnectStart:Q,onConnectEnd:w,onClickConnectStart:L,onClickConnectEnd:J,onNodeMouseEnter:N,onNodeMouseMove:q,onNodeMouseLeave:W,onNodeContextMenu:z,onNodeDoubleClick:Z,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onNodesDelete:h,onEdgesDelete:B,onDelete:X,onSelectionChange:m,onSelectionDragStart:O,onSelectionDrag:p,onSelectionDragStop:Y,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:S,onBeforeDelete:k,connectionMode:I,connectionLineType:b=_0.Bezier,connectionLineStyle:o,connectionLineComponent:s,connectionLineContainerStyle:x,deleteKeyCode:fu="Backspace",selectionKeyCode:$u="Shift",selectionOnDrag:tu=!1,selectionMode:ju=S1.Full,panActivationKeyCode:Gu="Space",multiSelectionKeyCode:qu=_y()?"Meta":"Control",zoomActivationKeyCode:P=_y()?"Meta":"Control",snapToGrid:e,snapGrid:uu,onlyRenderVisibleElements:Wu=!1,selectNodesOnDrag:g,nodesDraggable:Qu,autoPanOnNodeFocus:Tu,nodesConnectable:Zu,nodesFocusable:Xu,nodeOrigin:ff=_W,edgesFocusable:_f,edgesReconnectable:Jf,elementsSelectable:mf=!0,defaultViewport:Yl=sV,minZoom:Al=0.5,maxZoom:jl=2,translateExtent:Hr=ly,preventScrolling:al=!0,nodeExtent:Au,defaultMarkerColor:vu="#b1b1b7",zoomOnScroll:Kl=!0,zoomOnPinch:Su=!0,panOnScroll:pf=!1,panOnScrollSpeed:Gl=0.5,panOnScrollMode:zl=C0.Free,zoomOnDoubleClick:Pf=!0,panOnDrag:rf=!0,onPaneClick:Ir,onPaneMouseEnter:Fr,onPaneMouseMove:x1,onPaneMouseLeave:gn,onPaneScroll:b0,onPaneContextMenu:lu,paneClickDistance:Ou=1,nodeClickDistance:mu=0,children:ou,onReconnect:Af,onReconnectStart:vf,onReconnectEnd:pu,onEdgeContextMenu:ll,onEdgeDoubleClick:J0,onEdgeMouseEnter:Gf,onEdgeMouseMove:d9,onEdgeMouseLeave:kf,reconnectRadius:ol=10,onNodesChange:Wy,onEdgesChange:C$,noDragClassName:wy="nodrag",noWheelClassName:R$="nowheel",noPanClassName:h1="nopan",fitView:Ly,fitViewOptions:Tl,connectOnClick:gr,attributionPosition:x$,proOptions:h$,defaultEdgeOptions:Ky,elevateNodesOnSelect:b$=!0,elevateEdgesOnSelect:sr=!1,disableKeyboardA11y:Gy=!1,autoPanOnConnect:If,autoPanOnNodeDrag:V8,autoPanSpeed:v$,connectionRadius:Br,isValidConnection:sn,onError:an,style:b1,id:v0,nodeDragThreshold:zy,connectionDragThreshold:e9,viewport:v1,onViewportChange:u7,width:k$,height:D8,colorMode:X8="light",debug:Y8,onScroll:U0,ariaLabelConfig:k1,zIndexMode:k0="basic",...Sl},I$){let on=v0||"1",Jr=eV(X8),g$=yu.useCallback((s$)=>{s$.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),U0?.(s$)},[U0]);return ru.jsx("div",{"data-testid":"rf__wrapper",...Sl,onScroll:g$,style:{...b1,...wX},ref:I$,className:Xf(["react-flow",n,Jr]),id:v0,role:"application",children:ru.jsxs(WX,{nodes:u,edges:f,width:k$,height:D8,fitView:Ly,fitViewOptions:Tl,minZoom:Al,maxZoom:jl,nodeOrigin:ff,nodeExtent:Au,zIndexMode:k0,children:[ru.jsx(dV,{nodes:u,edges:f,defaultNodes:l,defaultEdges:r,onConnect:U,onConnectStart:Q,onConnectEnd:w,onClickConnectStart:L,onClickConnectEnd:J,nodesDraggable:Qu,autoPanOnNodeFocus:Tu,nodesConnectable:Zu,nodesFocusable:Xu,edgesFocusable:_f,edgesReconnectable:Jf,elementsSelectable:mf,elevateNodesOnSelect:b$,elevateEdgesOnSelect:sr,minZoom:Al,maxZoom:jl,nodeExtent:Au,onNodesChange:Wy,onEdgesChange:C$,snapToGrid:e,snapGrid:uu,connectionMode:I,translateExtent:Hr,connectOnClick:gr,defaultEdgeOptions:Ky,fitView:Ly,fitViewOptions:Tl,onNodesDelete:h,onEdgesDelete:B,onDelete:X,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onSelectionDrag:p,onSelectionDragStart:O,onSelectionDragStop:Y,onMove:A,onMoveStart:j,onMoveEnd:F,noPanClassName:h1,nodeOrigin:ff,rfId:on,autoPanOnConnect:If,autoPanOnNodeDrag:V8,autoPanSpeed:v$,onError:an,connectionRadius:Br,isValidConnection:sn,selectNodesOnDrag:g,nodeDragThreshold:zy,connectionDragThreshold:e9,onBeforeDelete:k,debug:Y8,ariaLabelConfig:k1,zIndexMode:k0}),ru.jsx(QX,{onInit:c,onNodeClick:_,onEdgeClick:$,onNodeMouseEnter:N,onNodeMouseMove:q,onNodeMouseLeave:W,onNodeContextMenu:z,onNodeDoubleClick:Z,nodeTypes:i,edgeTypes:y,connectionLineType:b,connectionLineStyle:o,connectionLineComponent:s,connectionLineContainerStyle:x,selectionKeyCode:$u,selectionOnDrag:tu,selectionMode:ju,deleteKeyCode:fu,multiSelectionKeyCode:qu,panActivationKeyCode:Gu,zoomActivationKeyCode:P,onlyRenderVisibleElements:Wu,defaultViewport:Yl,translateExtent:Hr,minZoom:Al,maxZoom:jl,preventScrolling:al,zoomOnScroll:Kl,zoomOnPinch:Su,zoomOnDoubleClick:Pf,panOnScroll:pf,panOnScrollSpeed:Gl,panOnScrollMode:zl,panOnDrag:rf,onPaneClick:Ir,onPaneMouseEnter:Fr,onPaneMouseMove:x1,onPaneMouseLeave:gn,onPaneScroll:b0,onPaneContextMenu:lu,paneClickDistance:Ou,nodeClickDistance:mu,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:S,onReconnect:Af,onReconnectStart:vf,onReconnectEnd:pu,onEdgeContextMenu:ll,onEdgeDoubleClick:J0,onEdgeMouseEnter:Gf,onEdgeMouseMove:d9,onEdgeMouseLeave:kf,reconnectRadius:ol,defaultMarkerColor:vu,noDragClassName:wy,noWheelClassName:R$,noPanClassName:h1,rfId:on,disableKeyboardA11y:Gy,nodeExtent:Au,viewport:v1,onViewportChange:u7}),ru.jsx(gV,{onSelectionChange:m}),ou,ru.jsx(hV,{proOptions:h$,position:x$}),ru.jsx(xV,{rfId:on,disableKeyboardA11y:Gy})]})})}var XW=tW(LX);var fb=tr.error014();function KX({dimensions:u,lineWidth:f,variant:l,className:r}){return ru.jsx("path",{strokeWidth:f,d:`M${u[0]/2} 0 V${u[1]} M0 ${u[1]/2} H${u[0]}`,className:Xf(["react-flow__background-pattern",l,r])})}function GX({radius:u,className:f}){return ru.jsx("circle",{cx:u,cy:u,r:u,className:Xf(["react-flow__background-pattern","dots",f])})}var pn;(function(u){u.Lines="lines",u.Dots="dots",u.Cross="cross"})(pn||(pn={}));var zX={[pn.Dots]:1,[pn.Lines]:1,[pn.Cross]:6},TX=(u)=>({transform:u.transform,patternId:`pattern-${u.rfId}`});function YW({id:u,variant:f=pn.Dots,gap:l=20,size:r,lineWidth:n=1,offset:i=0,color:y,bgColor:_,style:$,className:c,patternClassName:A}){let j=yu.useRef(null),{transform:F,patternId:U}=uf(TX,Kf),Q=r||zX[f],w=f===pn.Dots,L=f===pn.Cross,J=Array.isArray(l)?l:[l,l],N=[J[0]*F[2]||1,J[1]*F[2]||1],q=Q*F[2],W=Array.isArray(i)?i:[i,i],z=L?[q,q]:N,Z=[W[0]*F[2]||1+z[0]/2,W[1]*F[2]||1+z[1]/2],H=`${U}${u?u:""}`;return ru.jsxs("svg",{className:Xf(["react-flow__background",c]),style:{...$,...i8,"--xy-background-color-props":_,"--xy-background-pattern-color-props":y},ref:j,"data-testid":"rf__background",children:[ru.jsx("pattern",{id:H,x:F[0]%N[0],y:F[1]%N[1],width:N[0],height:N[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${Z[0]},-${Z[1]})`,children:w?ru.jsx(GX,{radius:q/2,className:A}):ru.jsx(KX,{dimensions:z,lineWidth:n,variant:f,className:A})}),ru.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${H})`})]})}YW.displayName="Background";var SW=yu.memo(YW);function EX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:ru.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function ZX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:ru.jsx("path",{d:"M0 0h32v4.2H0z"})})}function OX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:ru.jsx("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"})})}function HX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:ru.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"})})}function BX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:ru.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"})})}function f8({children:u,className:f,...l}){return ru.jsx("button",{type:"button",className:Xf(["react-flow__controls-button",f]),...l,children:u})}var VX=(u)=>({isInteractive:u.nodesDraggable||u.nodesConnectable||u.elementsSelectable,minZoomReached:u.transform[2]<=u.minZoom,maxZoomReached:u.transform[2]>=u.maxZoom,ariaLabelConfig:u.ariaLabelConfig});function mW({style:u,showZoom:f=!0,showFitView:l=!0,showInteractive:r=!0,fitViewOptions:n,onZoomIn:i,onZoomOut:y,onFitView:_,onInteractiveChange:$,className:c,children:A,position:j="bottom-left",orientation:F="vertical","aria-label":U}){let Q=Tf(),{isInteractive:w,minZoomReached:L,maxZoomReached:J,ariaLabelConfig:N}=uf(VX,Kf),{zoomIn:q,zoomOut:W,fitView:z}=t9(),Z=()=>{q(),i?.()},H=()=>{W(),y?.()},E=()=>{z(n),_?.()},D=()=>{Q.setState({nodesDraggable:!w,nodesConnectable:!w,elementsSelectable:!w}),$?.(!w)};return ru.jsxs(n8,{className:Xf(["react-flow__controls",F==="horizontal"?"horizontal":"vertical",c]),position:j,style:u,"data-testid":"rf__controls","aria-label":U??N["controls.ariaLabel"],children:[f&&ru.jsxs(ru.Fragment,{children:[ru.jsx(f8,{onClick:Z,className:"react-flow__controls-zoomin",title:N["controls.zoomIn.ariaLabel"],"aria-label":N["controls.zoomIn.ariaLabel"],disabled:J,children:ru.jsx(EX,{})}),ru.jsx(f8,{onClick:H,className:"react-flow__controls-zoomout",title:N["controls.zoomOut.ariaLabel"],"aria-label":N["controls.zoomOut.ariaLabel"],disabled:L,children:ru.jsx(ZX,{})})]}),l&&ru.jsx(f8,{className:"react-flow__controls-fitview",onClick:E,title:N["controls.fitView.ariaLabel"],"aria-label":N["controls.fitView.ariaLabel"],children:ru.jsx(OX,{})}),r&&ru.jsx(f8,{className:"react-flow__controls-interactive",onClick:D,title:N["controls.interactive.ariaLabel"],"aria-label":N["controls.interactive.ariaLabel"],children:w?ru.jsx(BX,{}):ru.jsx(HX,{})}),A]})}mW.displayName="Controls";var pW=yu.memo(mW);function DX({id:u,x:f,y:l,width:r,height:n,style:i,color:y,strokeColor:_,strokeWidth:$,className:c,borderRadius:A,shapeRendering:j,selected:F,onClick:U}){let{background:Q,backgroundColor:w}=i||{},L=y||Q||w;return ru.jsx("rect",{className:Xf(["react-flow__minimap-node",{selected:F},c]),x:f,y:l,rx:A,ry:A,width:r,height:n,style:{fill:L,stroke:_,strokeWidth:$},shapeRendering:j,onClick:U?(J)=>U(J,u):void 0})}var XX=yu.memo(DX),YX=(u)=>u.nodes.map((f)=>f.id),y9=(u)=>u instanceof Function?u:()=>u;function SX({nodeStrokeColor:u,nodeColor:f,nodeClassName:l="",nodeBorderRadius:r=5,nodeStrokeWidth:n,nodeComponent:i=XX,onClick:y}){let _=uf(YX,Kf),$=y9(f),c=y9(u),A=y9(l),j=typeof window>"u"||!!window.chrome?"crispEdges":"geometricPrecision";return ru.jsx(ru.Fragment,{children:_.map((F)=>ru.jsx(pX,{id:F,nodeColorFunc:$,nodeStrokeColorFunc:c,nodeClassNameFunc:A,nodeBorderRadius:r,nodeStrokeWidth:n,NodeComponent:i,onClick:y,shapeRendering:j},F))})}function mX({id:u,nodeColorFunc:f,nodeStrokeColorFunc:l,nodeClassNameFunc:r,nodeBorderRadius:n,nodeStrokeWidth:i,shapeRendering:y,NodeComponent:_,onClick:$}){let{node:c,x:A,y:j,width:F,height:U}=uf((Q)=>{let w=Q.nodeLookup.get(u);if(!w)return{node:void 0,x:0,y:0,width:0,height:0};let L=w.internals.userNode,{x:J,y:N}=w.internals.positionAbsolute,{width:q,height:W}=$0(L);return{node:L,x:J,y:N,width:q,height:W}},Kf);if(!c||c.hidden||!bA(c))return null;return ru.jsx(_,{x:A,y:j,width:F,height:U,style:c.style,selected:!!c.selected,className:r(c),color:f(c),borderRadius:n,strokeColor:l(c),strokeWidth:i,shapeRendering:y,onClick:$,id:c.id})}var pX=yu.memo(mX),PX=yu.memo(SX),MX=200,CX=150,RX=(u)=>!u.hidden,xX=(u)=>{let f={x:-u.transform[0]/u.transform[2],y:-u.transform[1]/u.transform[2],width:u.width/u.transform[2],height:u.height/u.transform[2]};return{viewBB:f,boundingRect:u.nodeLookup.size>0?RA(ry(u.nodeLookup,{filter:RX}),f):f,rfId:u.rfId,panZoom:u.panZoom,translateExtent:u.translateExtent,flowWidth:u.width,flowHeight:u.height,ariaLabelConfig:u.ariaLabelConfig}},hX="react-flow__minimap-desc";function PW({style:u,className:f,nodeStrokeColor:l,nodeColor:r,nodeClassName:n="",nodeBorderRadius:i=5,nodeStrokeWidth:y,nodeComponent:_,bgColor:$,maskColor:c,maskStrokeColor:A,maskStrokeWidth:j,position:F="bottom-right",onClick:U,onNodeClick:Q,pannable:w=!1,zoomable:L=!1,ariaLabel:J,inversePan:N,zoomStep:q=1,offsetScale:W=5}){let z=Tf(),Z=yu.useRef(null),{boundingRect:H,viewBB:E,rfId:D,panZoom:h,translateExtent:B,flowWidth:X,flowHeight:m,ariaLabelConfig:O}=uf(xX,Kf),p=u?.width??MX,Y=u?.height??CX,v=H.width/p,T=H.height/Y,S=Math.max(v,T),k=S*p,I=S*Y,b=W*S,o=H.x-(k-H.width)/2-b,s=H.y-(I-H.height)/2-b,x=k+b*2,fu=I+b*2,$u=`${hX}-${D}`,tu=yu.useRef(0),ju=yu.useRef();tu.current=S,yu.useEffect(()=>{if(Z.current&&h)return ju.current=UN({domNode:Z.current,panZoom:h,getTransform:()=>z.getState().transform,getViewScale:()=>tu.current}),()=>{ju.current?.destroy()}},[h]),yu.useEffect(()=>{ju.current?.update({translateExtent:B,width:X,height:m,inversePan:N,pannable:w,zoomStep:q,zoomable:L})},[w,L,N,q,B,X,m]);let Gu=U?(e)=>{let[uu,Wu]=ju.current?.pointer(e)||[0,0];U(e,{x:uu,y:Wu})}:void 0,qu=Q?yu.useCallback((e,uu)=>{let Wu=z.getState().nodeLookup.get(uu).internals.userNode;Q(e,Wu)},[]):void 0,P=J??O["minimap.ariaLabel"];return ru.jsx(n8,{position:F,style:{...u,"--xy-minimap-background-color-props":typeof $==="string"?$:void 0,"--xy-minimap-mask-background-color-props":typeof c==="string"?c:void 0,"--xy-minimap-mask-stroke-color-props":typeof A==="string"?A:void 0,"--xy-minimap-mask-stroke-width-props":typeof j==="number"?j*S:void 0,"--xy-minimap-node-background-color-props":typeof r==="string"?r:void 0,"--xy-minimap-node-stroke-color-props":typeof l==="string"?l:void 0,"--xy-minimap-node-stroke-width-props":typeof y==="number"?y:void 0},className:Xf(["react-flow__minimap",f]),"data-testid":"rf__minimap",children:ru.jsxs("svg",{width:p,height:Y,viewBox:`${o} ${s} ${x} ${fu}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":$u,ref:Z,onClick:Gu,children:[P&&ru.jsx("title",{id:$u,children:P}),ru.jsx(PX,{onClick:qu,nodeColor:r,nodeStrokeColor:l,nodeBorderRadius:i,nodeClassName:n,nodeStrokeWidth:y,nodeComponent:_}),ru.jsx("path",{className:"react-flow__minimap-mask",d:`M${o-b},${s-b}h${x+b*2}v${fu+b*2}h${-x-b*2}z - M${E.x},${E.y}h${E.width}v${E.height}h${-E.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}PW.displayName="MiniMap";var lb=yu.memo(PW),bX=(u)=>(f)=>u?`${Math.max(1/f.transform[2],1)}`:void 0,vX={[mn.Line]:"right",[mn.Handle]:"bottom-right"};function kX({nodeId:u,position:f,variant:l=mn.Handle,className:r,style:n=void 0,children:i,color:y,minWidth:_=10,minHeight:$=10,maxWidth:c=Number.MAX_VALUE,maxHeight:A=Number.MAX_VALUE,keepAspectRatio:j=!1,resizeDirection:F,autoScale:U=!0,shouldResize:Q,onResizeStart:w,onResize:L,onResizeEnd:J}){let N=FW(),q=typeof u==="string"?u:N,W=Tf(),z=yu.useRef(null),Z=l===mn.Handle,H=uf(yu.useCallback(bX(Z&&U),[Z,U]),Kf),E=yu.useRef(null),D=f??vX[l];yu.useEffect(()=>{if(!z.current||!q)return;if(!E.current)E.current=wN({domNode:z.current,nodeId:q,getStoreItems:()=>{let{nodeLookup:B,transform:X,snapGrid:m,snapToGrid:O,nodeOrigin:p,domNode:Y}=W.getState();return{nodeLookup:B,transform:X,snapGrid:m,snapToGrid:O,nodeOrigin:p,paneDomNode:Y}},onChange:(B,X)=>{let{triggerNodeChanges:m,nodeLookup:O,parentLookup:p,nodeOrigin:Y}=W.getState(),v=[],T={x:B.x,y:B.y},S=O.get(q);if(S&&S.expandParent&&S.parentId){let k=S.origin??Y,I=B.width??S.measured.width??0,b=B.height??S.measured.height??0,o={id:S.id,parentId:S.parentId,rect:{width:I,height:b,...vA({x:B.x??S.position.x,y:B.y??S.position.y},{width:I,height:b},S.parentId,O,k)}},s=a6([o],O,p,Y);v.push(...s),T.x=B.x?Math.max(k[0]*I,B.x):void 0,T.y=B.y?Math.max(k[1]*b,B.y):void 0}if(T.x!==void 0&&T.y!==void 0){let k={id:q,type:"position",position:{...T}};v.push(k)}if(B.width!==void 0&&B.height!==void 0){let I={id:q,type:"dimensions",resizing:!0,setAttributes:!F?!0:F==="horizontal"?"width":"height",dimensions:{width:B.width,height:B.height}};v.push(I)}for(let k of X){let I={...k,type:"position"};v.push(I)}m(v)},onEnd:({width:B,height:X})=>{let m={id:q,type:"dimensions",resizing:!1,dimensions:{width:B,height:X}};W.getState().triggerNodeChanges([m])}});return E.current.update({controlPosition:D,boundaries:{minWidth:_,minHeight:$,maxWidth:c,maxHeight:A},keepAspectRatio:j,resizeDirection:F,onResizeStart:w,onResize:L,onResizeEnd:J,shouldResize:Q}),()=>{E.current?.destroy()}},[D,_,$,c,A,j,w,L,J,Q]);let h=D.split("-");return ru.jsx("div",{className:Xf(["react-flow__resize-control","nodrag",...h,l,r]),ref:z,style:{...n,scale:H,...y&&{[Z?"backgroundColor":"borderColor"]:y}},children:i})}var rb=yu.memo(kX);var G=Rn.default.createElement,{useEffect:A0}=Rn.default,kl=Rn.default.useState,Cn=Rn.default.useRef,B$=[{id:"in-left",side:"left",position:Lu.Left,style:{top:"50%"}},{id:"in-top-left",side:"top",slot:"left",slotIndex:-1,position:Lu.Top,style:{left:"28%"}},{id:"in-top-mid",side:"top",slot:"mid",slotIndex:0,position:Lu.Top,style:{left:"50%"}},{id:"in-top-right",side:"top",slot:"right",slotIndex:1,position:Lu.Top,style:{left:"72%"}},{id:"in-bottom-left",side:"bottom",slot:"left",slotIndex:-1,position:Lu.Bottom,style:{left:"28%"}},{id:"in-bottom-mid",side:"bottom",slot:"mid",slotIndex:0,position:Lu.Bottom,style:{left:"50%"}},{id:"in-bottom-right",side:"bottom",slot:"right",slotIndex:1,position:Lu.Bottom,style:{left:"72%"}}],Z$=[{id:"out-right",position:Lu.Right,style:{top:"50%"}}],MW=["#4eb7a8","#d7a13a","#69aee8","#e0835f","#b7d86b","#d98bd2","#5fc6bf"],jy=236,Fy=88,CW=15000,IX=10,A9=96,t0=72,j9=64,RW=12;function y8(){return typeof document>"u"||document.visibilityState!=="hidden"}function xW(u,f){let l=Number.parseFloat(String(u||""));return Number.isFinite(l)?l/100:f}function gX(u,f,l){let r=String(u.side||"");if(r!=="top"&&r!=="bottom")return 0;let n=Number(u.slotIndex||0),i=r==="top"?"in-top-mid":"in-bottom-mid",y=f.get(u.id)||0,_=f.get(i)||0;if(n===0)return _===0?-26:28+y*74;let $=l===0?Math.abs(n)*2:Math.sign(l)===Math.sign(n)?-3:3;if(_>0&&y===0)return-14+$;return 8+y*74+$}function _8(u){let f=u.filter((i,y)=>{let _=u[y-1];return!_||Math.abs(_.x-i.x)>0.5||Math.abs(_.y-i.y)>0.5});if(f.length<2)return"";let l=`M ${f[0].x},${f[0].y}`,r=f[0];for(let i=1;i0.5||Math.abs(F.y-r.y)>0.5)l+=` L ${F.x},${F.y}`;l+=` Q ${_.x},${_.y} ${U.x},${U.y}`,r=U}let n=f[f.length-1];return`${l} L ${n.x},${n.y}`}function yw(u,f,l,r,n,i,y=""){let _=l>=u,$=Math.max(1,Math.abs(l-u)),c=Math.abs(r-f),A=Math.max(34,Math.min(118,$*0.26)),j=Math.min(280,Math.abs(i));if(_&&n===Lu.Left&&j<4&&c<28&&$<420)return`M ${u},${f} C ${u+A},${f} ${l-A},${r} ${l},${r}`;if(_&&n===Lu.Left&&(y==="direct-forward-left"||$<=260&&c<=210)){let J=Math.max(42,Math.min(140,$*0.48)),N=Math.max(-28,Math.min(28,i*0.18));return`M ${u},${f} C ${u+J},${f+N} ${l-J},${r} ${l},${r}`}if(_){let J=u+A;if(n===Lu.Top||n===Lu.Bottom){let W=n===Lu.Top?-1:1,z=r+W*(54+j*0.42);return _8([{x:u,y:f},{x:J,y:f},{x:J+Math.min(120,$*0.18),y:z},{x:l,y:z},{x:l,y:r+W*34},{x:l,y:r}])}let N=l-A,q=(f+r)/2+i;return _8([{x:u,y:f},{x:J,y:f},{x:J+Math.min(110,$*0.16),y:q},{x:N-Math.min(90,$*0.12),y:q},{x:N,y:r},{x:l,y:r}])}let Q=n===Lu.Bottom?1:n===Lu.Top?-1:i>=0?1:-1,w=Math.max(u,l)+92+Math.min(180,j*0.52),L=Q<0?Math.min(f,r)-84-j*0.62:Math.max(f,r)+84+j*0.62;if(n===Lu.Top||n===Lu.Bottom)return _8([{x:u,y:f},{x:u+A,y:f},{x:w,y:L},{x:l,y:L},{x:l,y:r+Q*38},{x:l,y:r}]);return _8([{x:u,y:f},{x:u+A,y:f},{x:w,y:L},{x:l-A,y:L},{x:l-A,y:r},{x:l,y:r}])}function sX({data:u}){return G("div",{className:"pipeline-flow-node-body"},B$.map((f)=>G(M1,{key:f.id,id:f.id,type:"target",position:f.position,isConnectable:!1,className:`pipeline-flow-handle input ${f.side} slot-${f.slot||"mid"}`,style:f.style})),Z$.map((f)=>G(M1,{key:f.id,id:f.id,type:"source",position:f.position,isConnectable:!1,className:"pipeline-flow-handle output right",style:f.style})),u?.label)}function aX({id:u,sourceX:f,sourceY:l,targetX:r,targetY:n,targetPosition:i,markerEnd:y,markerStart:_,style:$,data:c}){let A=Number(c?.laneOffset||0),j=yw(f,l,r,n,i,A,String(c?.routeMode||""));return G(cy,{id:u,path:j,markerEnd:y,markerStart:_,style:$,interactionWidth:28})}var oX={pipelineCurve:aX},dX={pipelineNode:sX};function A8(u){if(!u)return"--";let f=new Date(u);if(Number.isNaN(f.getTime()))return"--";return $f(f)}function Er(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.round(f/1000);if(l<60)return`${l}s`;if(l<3600)return`${Math.floor(l/60)}m ${l%60}s`;return`${Math.floor(l/3600)}h ${Math.floor(l%3600/60)}m`}function F9(u){let f=Number(u);if(!Number.isFinite(f))return"--";return f.toLocaleString("zh-CN")}function hW(u){let f=Number(u);if(!Number.isFinite(f))return"--";return`${Math.round(Math.max(0,Math.min(1,f))*100)}%`}function Du(u){return typeof u==="object"&&u!==null&&!Array.isArray(u)}function Vu(u){return Array.isArray(u)?u:[]}function ku(u){if(!u)return null;let f=new Date(u);return Number.isNaN(f.getTime())?null:f.getTime()}function V$(u){return Number.isFinite(Number(u))?new Date(Number(u)).toISOString():""}function Y$(...u){for(let f of u){let l=ku(f);if(l!==null)return new Date(l).toISOString()}return""}function O9(...u){let f=u.map(ku).filter((l)=>l!==null);return f.length>0?new Date(Math.max(...f)).toISOString():""}function H9(u){return["succeeded","failed","skipped","cancelled","canceled","completed"].includes(String(u||"").toLowerCase())}function _w(u){let f=cw(u).toLowerCase();return["running","active","in-progress","in_progress"].includes(f)}function bW(u,f="status"){return u.reduce((l,r)=>{let n=String(r?.[f]||"unknown").toLowerCase();return l[n]=(l[n]||0)+1,l},{})}function $w(u){if(!u||typeof u!=="string")return null;try{let f=JSON.parse(u);return Du(f)?f:null}catch{return null}}function J9(u){let f=u.map($w).filter((i)=>Boolean(i)),l=f.flatMap((i)=>[i.timestamp,i.createdAt,i.updatedAt]).filter(Boolean),r=O9(...l),n=Array.from(new Set(f.map((i)=>String(i.event||i.action||i.type||"")).filter(Boolean))).slice(0,3);return{total:u.length,parsed:f.length,lastAt:r,eventKinds:n}}function j8(u){if(u===null||u===void 0)return"--";if(typeof u==="boolean")return u?"是":"否";if(typeof u==="number")return String(u);if(typeof u==="string")return u.length>80?`${u.slice(0,77)}...`:u;if(Array.isArray(u))return`${u.length} 项`;if(typeof u==="object")return`${Object.keys(u).length} 字段`;return String(u)}function tw(u,f=280){if(u===null||u===void 0)return"";let r=(typeof u==="string"?u:String(u)).replace(/\r\n/gu,` -`).trim();return r.length>f?`${r.slice(0,Math.max(0,f-1))}...`:r}function cw(u){if(typeof u==="string")return u;if(Du(u))return String(u.status||u.state||u.phase||"unknown");return"unknown"}function eX(u){return u.filter((f)=>f&&f.value!==void 0&&f.value!==null&&String(f.value)!=="")}function w9({items:u}){let f=eX(Vu(u));return G("div",{className:"pipeline-kv-grid"},f.map((l)=>G("span",{key:l.label},G("b",null,l.label),G("span",null,l.value))))}function B9({items:u}){let f=Vu(u).map((l)=>String(l||"")).filter(Boolean);if(f.length===0)return null;return G("div",{className:"pipeline-chip-row"},f.map((l,r)=>G("span",{key:`${r}-${l}`},l)))}function L9(u,f){let l=String(f?.procedureRunId||""),r=Vu(u?.procedureRuns);return r.find((n)=>String(Zr(n))===l)||r.at(-1)||null}function uY(u,f){let l=String(f||"");if(!l)return null;return Vu(u?.procedureRuns).find((r)=>Zr(r)===l)||null}function U9(u){return Vu(u?.attempts).length}function vW(u){return Vu(u?.attempts).reduce((f,l)=>f+W8(l).length,0)}function W8(u){return Vu(u?.opencodeMessages?.steps).filter(Du)}function Aw(u){let f=String(u?.status||"").toLowerCase();if(["error","failed","failure"].includes(f))return"failed";if(["completed","succeeded","success"].includes(f))return"succeeded";if(["running","started","in_progress"].includes(f))return"running";return"unknown"}function fY(u,f){let l=G9(u.map((i)=>i?.agent)).slice(0,3),r=G9(u.map((i)=>i?.model)).slice(0,3),n=f.length<=2?f.map((i)=>`session ${i}`):[`sessions ${f.length}`,...f.slice(0,2).map((i)=>`session ${i}`)];return[...l.map((i)=>`agent ${i}`),...r.map((i)=>`model ${i}`),...n]}function O$(u,f=0){return String(u?.messageId||u?.index||"")||`step-${f}`}function lY({steps:u,sessionIds:f,sessionFacts:l,matchedStepKey:r}){let n=Vu(u),i=n.findIndex((L,J)=>O$(L,J)===r),y=i>=0?n[i]:null,_=n.flatMap((L)=>[ku(L?.createdAt),ku(L?.completedAt)]).filter((L)=>L!==null),$=_.length>0?Math.min(..._):null,c=_.length>0?Math.max(..._):null,A=$!==null&&c!==null?Math.max(0,c-$):null,j=n.reduce((L,J)=>L+Vu(J?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool").length,0),F=n.reduce((L,J)=>L+Vu(J?.parts).filter((N)=>["text","reasoning"].includes(String(N?.type||"").toLowerCase())).length,0),U=n.reduce((L,J)=>L+Vu(J?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool"&&Aw(N)==="failed").length,0),Q=[`${n.length} steps`,`${f.length} sessions`,`${F} messages`,`${j} tools`,A!==null?`duration ${Er(A)}`:"",U>0?`${U} failed tools`:""].filter(Boolean),w=y?[`Step ${y?.index??i+1}`,String(y?.role||"role --"),y?.model?`model ${y.model}`:"",y?.finish?`finish ${y.finish}`:"",y?.durationMs!==void 0&&y?.durationMs!==null?`duration ${Er(y.durationMs)}`:""].filter(Boolean):[];return G("section",{className:"pipeline-trace-timeline","data-testid":"pipeline-step-timeline"},G("div",{className:"pipeline-trace-head"},G("div",null,G("b",null,"OpenCode Trace"),G("span",null,"Trace 使用 Code Queue 统一样式展示完整 agent loop;Pipeline 旧 step/message/tool 卡片样式已废弃。")),G("div",{className:"pipeline-trace-session-head","data-testid":"pipeline-step-timeline-session"},G("span",null,Q.join(" / ")||"Trace"),l.length>0?G(B9,{items:l}):null)),y?G("div",{className:"pipeline-trace-focus","data-testid":"pipeline-trace-matched-step"},G("span",{className:"codex-output-channel"},"Matched"),G("strong",null,`Gantt selection -> ${w.join(" / ")}`),G("time",null,`${A8(y?.createdAt)} -> ${A8(y?.completedAt)}`)):null,G(Y3,{port:YU,input:n,className:"codex-transcript pipeline-trace",testId:"pipeline-opencode-step-trace",emptyText:"暂无 OpenCode Trace 输出",keepRecentToolCalls:3}))}function K9(u){return Vu(u).flatMap((f)=>{if(Du(f))return[f];let l=$w(f);return l?[l]:[]})}function vr(u){return String(u?.event||u?.action||u?.requestedAction||u?.type||"").toLowerCase()}function Ay(u){return Y$(u?.timestamp,u?.createdAt,u?.updatedAt,u?.startedAt,u?.finishedAt)}function rY(u){return ku(Ay(u))}function w8(u){return String(u?.attempt||u?.id||"")}function G9(u){let f=new Set,l=[];for(let r of u){let n=String(r||"");if(!n||f.has(n))continue;f.add(n),l.push(n)}return l}function kW(u){switch(String(u||"").toLowerCase()){case"monitor":return"monitor";case"webui":return"webui";case"cli":return"cli";case"system":return"runner";default:return String(u||"--")}}function C1(u){return String(u?.requestedAction||u?.action||"").toLowerCase()}function H$(u){switch(C1(u)){case"guide":return"引导";case"modify":return"修改";case"approve":return"审核通过";case"restart":return"重启";case"redo":return"重做";default:return String(u?.requestedAction||u?.action||"控制")}}function IW(u){switch(vr(u)){case"initial-prompt-delivered":return"初始 prompt";case"append-prompt-delivered":return"追加 prompt";case"append-prompt-queued":return"追加 prompt 已排队";case"monitor-prompt-delivered":return"Monitor prompt";case"node-long-running-observation":return"长任务观察";case"node-finished":return"节点完成";case"oa-policy-downstream-evaluated":return"OA 下游策略";case"control-command-queued":return`${H$(u)} 已发起`;case"control-command-applied":return`${H$(u)} 已生效`;case"control-command-ignored":return`${H$(u)} 已忽略`;default:return String(u?.event||u?.action||u?.requestedAction||"event")}}function gW(u){return tw(u?.promptPreview||u?.reasonPreview||u?.prompt||u?.reason||"",240)}function nY(u){let f=String(u?.prompt||""),l=String(u?.reason||u?.restartReason||""),r=f?"":String(u?.promptPreview||""),n=l?"":String(u?.reasonPreview||"");return[f||r?{label:f?"prompt":"prompt preview",value:f||r}:null,l||n?{label:l?"reason":"reason preview",value:l||n}:null,Vu(u?.resetNodeIds).length>0?{label:"reset nodes",value:Vu(u.resetNodeIds).join(", ")}:null,Vu(u?.runningResetNodeIds).length>0?{label:"interrupted running nodes",value:Vu(u.runningResetNodeIds).join(", ")}:null,Vu(u?.interruptedProcedureRunIds).length>0?{label:"interrupted procedures",value:Vu(u.interruptedProcedureRunIds).join(", ")}:null,u?.interruptedProcedureRunId?{label:"interrupted procedure",value:String(u.interruptedProcedureRunId)}:null].filter(Boolean)}function Q9(u){let f=W8(u),l=f.map(($)=>ku($?.createdAt)).filter(($)=>$!==null),r=f.map(($)=>ku($?.completedAt)??ku($?.createdAt)).filter(($)=>$!==null),n=K9(u?.controlEventRecords).map(($)=>rY($)).filter(($)=>$!==null),i=Vu(u?.assistantOutputs).map(($)=>ku($?.updatedAt)).filter(($)=>$!==null),y=l[0]??n[0]??i[0]??null,_=r.at(-1)??n.at(-1)??i.at(-1)??y;return{startMs:y,endMs:_}}function iY(u,f,l,r,n=""){let i=Vu(u?.procedureRuns).filter((_)=>L8(_,f)===l);if(i.length===0)return null;if(n){let _=i.find(($)=>Zr($)===n);if(_)return _}if(r===null)return i.at(-1)||null;let y=i.find((_)=>{let $=ku($8(_,u)),c=ku(t8(_,u))??$;return $!==null&&c!==null&&r>=$-1000&&r<=c+1000});if(y)return y;return i.slice().sort((_,$)=>{let c=ku($8(_,u))??r,A=ku(t8(_,u))??c,j=ku($8($,u))??r,F=ku(t8($,u))??j,U=Math.min(Math.abs(c-r),Math.abs(A-r)),Q=Math.min(Math.abs(j-r),Math.abs(F-r));return U-Q})[0]||null}function jw(u,f){let l=Vu(u?.attempts).filter(Du);if(l.length===0)return null;let r=String(f?.attempt||"");if(r){let y=l.find((_)=>w8(_)===r);if(y)return y}let n=Number.isFinite(Number(f?.ms))?Number(f.ms):null;if(n===null)return l.at(-1)||null;let i=l.find((y)=>{let _=Q9(y);return Number.isFinite(_.startMs)&&Number.isFinite(_.endMs)&&n>=Number(_.startMs)-1000&&n<=Number(_.endMs)+1000});if(i)return i;return l.slice().sort((y,_)=>{let $=Q9(y),c=Q9(_),A=Math.min(Math.abs(Number($.startMs??n)-n),Math.abs(Number($.endMs??n)-n)),j=Math.min(Math.abs(Number(c.startMs??n)-n),Math.abs(Number(c.endMs??n)-n));return A-j})[0]||l.at(-1)||null}function Fw(u,f){let l=W8(u);if(l.length===0)return{step:null,stepIndex:-1,stepKey:""};if(f===null){let i=l[0];return{step:i,stepIndex:0,stepKey:O$(i,0)}}for(let i=0;i=_-1000&&f<=$+1000)return{step:y,stepIndex:i,stepKey:O$(y,i)}}let r=l.findIndex((i)=>{let y=ku(i?.createdAt)??ku(i?.completedAt);return y!==null&&y>=f});if(r>=0){let i=l[r];return{step:i,stepIndex:r,stepKey:O$(i,r)}}let n=Math.max(0,l.length-1);return{step:l[n],stepIndex:n,stepKey:O$(l[n],n)}}function yY(u,f){let l=String(f?.runId||u?.runId||"");if(String(f?.mode||"")==="interval"){let c=f?.interval||{},A=L9(u,c)||c.raw||{};return{mode:"interval",runId:l,interval:c,marker:null,nodeId:String(c?.nodeId||L8(A,l)||""),procedure:A,attempt:null,matchedStep:null,matchedStepIndex:-1,matchedStepKey:""}}let r=Du(f?.marker)?f.marker:{},n=Number.isFinite(Number(r?.ms))?Number(r.ms):null,i=String(r?.nodeId||""),y=i?iY(u,l,i,n,String(r?.procedureRunId||"")):null,_=y?jw(y,r):null,$=_?Fw(_,n):{step:null,stepIndex:-1,stepKey:""};return{mode:"event",runId:l,interval:null,marker:r,nodeId:i,procedure:y,attempt:_,matchedStep:$.step,matchedStepIndex:$.stepIndex,matchedStepKey:$.stepKey}}function _Y({procedure:u,matchedStepKey:f="",matchedAttemptId:l=""}){let r=Vu(u?.attempts);if(r.length===0)return G(Ar,{title:"暂无 attempt 详情",text:"当前 procedure 还没有可展示的 attempt / OpenCode Trace;若刚点击甘特线,请等待 node 详情抓取完成。"});return r.map((n,i)=>{let y=n?.opencodeMessages||{},_=W8(n),$=Vu(y.sessionIds).map((F)=>String(F)).filter(Boolean),c=fY(_,$),A=w8(n)||`attempt-${i+1}`,j=_.reduce((F,U)=>F+Vu(U?.parts).filter((Q)=>String(Q?.type||"").toLowerCase()==="tool"&&Aw(Q)==="failed").length,0);return G("article",{key:A,className:`pipeline-attempt-card ${l===A?"matched":""}`},G("div",{className:"pipeline-attempt-head"},G("div",null,G("strong",null,A),G("span",null,y.source||"opencode")),G("div",{className:"pipeline-attempt-badges"},G("span",null,`${_.length} steps`),G("span",null,`${y.toolCallCount??"--"} tools`),j>0?G("span",{className:"danger"},`${j} failed`):null)),G(w9,{items:[{label:"messages",value:y.messageCount??"--"},{label:"steps",value:y.stepCount??"--"},{label:"tools",value:y.toolCallCount??"--"},{label:"updated",value:Nu(y.updatedAt)},{label:"sessions",value:$.join(", ")||"--"}]}),_.length===0?G("p",{className:"muted paragraph"},"当前 attempt 尚未返回 OpenCode Trace;请确认 D601 pipeline-control 已重建并重新抓取。"):G(lY,{steps:_,sessionIds:$,sessionFacts:c,matchedStepKey:f}))})}function q9(u,f){return`${u}::${f}`}function F8(u,f,l){if(!Du(u))return null;return String(u.runId||"")===f&&String(u.nodeId||"")===l?u:null}function $Y(u,f){let l=Du(u)?u:{};if(!Du(f))return l;let r=Vu(f.attempts),n=Vu(l.attempts);return{...l,...f,attempts:r.length>0?r:n}}function tY(u,f,l,r){if(!F8(f,l,r))return u;let n=Vu(f.procedureRuns),i=Du(u)?u:{};return{...i,...f,controlEvents:Vu(f.controlEvents).length>0?f.controlEvents:i.controlEvents,procedureRuns:n.length>0?n:i.procedureRuns}}function cY({selection:u,runDetails:f,nodeDetails:l,nodeDetailsState:r,onRaw:n,onCollapse:i}){if(!u?.mode)return G("aside",{className:"pipeline-gantt-detail-panel empty","data-testid":"pipeline-gantt-detail-panel"},G("div",{className:"pipeline-gantt-detail-head"},G("div",null,G("span",{className:"panel-eyebrow"},"Gantt Detail"),G(nf,{title:"未选择元素",level:3})),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起")),G(Ar,{title:"选择一条执行线或一个控制点",text:"点击甘特图中的 node 执行线、prompt 点或控制点,在这里查看结构化过程和 OpenCode step。"}));let y=String(u?.runId||""),_=String(u?.interval?.nodeId||u?.marker?.nodeId||""),$=f?.runId===y?f.details:null,c=F8(l,y,_),A=String(r?.runId||"")===y&&String(r?.nodeId||"")===_,j=tY($,c,y,_),F=(String(f?.runId||"")!==y||Boolean(f?.loading))&&!j,U=String(f?.runId||"")===y?String(f?.error||""):"",Q=A?String(r?.error||""):"",w=j?yY(j,u):null,L=w?.interval||u?.interval||null,J=w?.marker||u?.marker||null,N=String(L?.procedureRunId||J?.procedureRunId||""),q=c?uY(c,N)||L9(c,L||{procedureRunId:N}):null,W=w?.procedure||(j?L9(j,L||{procedureRunId:N}):null)||L?.raw||{};if(q&&(U9(W)===0||vW(q)>=vW(W)))W=$Y(W,q);let z=w?.attempt||null,Z=String(w?.matchedStepKey||"");if(!z&&J&&U9(W)>0)z=jw(W,J),Z=String(Fw(z,Number.isFinite(Number(J?.ms))?Number(J.ms):null).stepKey||"");let H=w8(z),E=U9(W)>0,D=A&&Boolean(r?.loading)&&!E,h=Boolean(F||D),B=[E?"":U,Q].filter(Boolean).join(" / "),X=A&&r?.fetchedAt?r.fetchedAt:f?.fetchedAt,m=cw(W?.status||L?.status||J?.status||J?.event),O=u?.mode==="event"?J?.label||IW(J?.raw||J)||"event":w?.nodeId||L?.nodeId||"node",p=J?nY(J?.raw||J):[],Y=J?[vr(J?.raw||J)?`event ${vr(J?.raw||J)}`:"",J?.promptEvent?`prompt ${J.promptEvent}`:"",J?.action?`action ${J.action}`:"",J?.sourceKind?`source ${kW(J.sourceKind)}`:"",J?.sourceNodeId?`from ${J.sourceNodeId}`:"",J?.targetNodeId?`to ${J.targetNodeId}`:"",J?.snapReason?`draw ${J.snapReason}`:""].filter(Boolean):[];return G("aside",{className:"pipeline-gantt-detail-panel","data-testid":"pipeline-gantt-detail-panel"},G("div",{className:"pipeline-gantt-detail-head"},G("div",null,G("span",{className:"panel-eyebrow"},u?.mode==="event"?"Gantt Event Detail":"Gantt Line Detail"),G(nf,{title:O,level:3,loading:h})),G("div",{className:"pipeline-gantt-detail-head-actions"},G(xn,{status:m},m),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起"))),J?G("article",{className:"pipeline-event-card"},G("div",{className:"pipeline-event-card-head"},G("strong",null,J?.label||IW(J?.raw||J)),G(B9,{items:Y})),G(w9,{items:[{label:"event time",value:Nu(J?.timestampIso||J?.timestamp||"--")},J?.snapped?{label:"drawn time",value:Nu(J?.renderedTimestampIso||J?.ms)}:null,{label:"node",value:J?.nodeId||"--"},{label:"procedure",value:J?.procedureRunId||Zr(W)||"--"},{label:"attempt",value:J?.attempt||H||"--"},{label:"source kind",value:J?.sourceKind?kW(J.sourceKind):"--"},{label:"source node",value:J?.sourceNodeId||"--"},{label:"target node",value:J?.targetNodeId||"--"},{label:"command",value:J?.commandId||J?.eventId||"--"},J?.snapReason?{label:"placement",value:J.snapReason}:null]}),p.length>0?G("div",{className:"pipeline-event-blocks"},p.map((v,T)=>G("section",{key:`${v.label}-${T}`,className:"pipeline-event-text-block"},G("b",null,v.label),G("p",null,v.value)))):null,gW(J?.raw||J)?G("p",{className:"pipeline-text-preview"},gW(J?.raw||J)):null):null,G(w9,{items:[{label:"epoch",value:y||L?.runId||"--"},{label:"node",value:w?.nodeId||L?.nodeId||J?.nodeId||"--"},{label:"procedure",value:L?.procedureRunId||J?.procedureRunId||Zr(W)||"--"},{label:"started",value:Nu(L?.startedAt||W?.startedAt)},{label:"finished",value:Nu(L?.finishedAt||W?.finishedAt)},{label:"duration",value:Er(L?.durationMs||W?.durationMs)},{label:"fetched",value:X?$f(X):"--"},w?.matchedStep?{label:"matched step",value:`Step ${w.matchedStep.index??w.matchedStepIndex+1}`}:null]}),G(yf,{error:B}),G("div",{className:"pipeline-gantt-detail-actions"},G(kr,{title:`Procedure ${L?.procedureRunId||J?.procedureRunId||w?.nodeId||"node"}`,data:W,onOpen:n,testId:"raw-pipeline-gantt-procedure"}),J?G(kr,{title:`Pipeline event ${J?.id||J?.commandId||J?.eventId||w?.nodeId||"event"}`,data:J?.raw||J,onOpen:n,testId:"raw-pipeline-gantt-event"}):null,j?G(kr,{title:`Pipeline run ${y||"--"}`,data:j,onOpen:n,testId:"raw-pipeline-gantt-node-details"}):null),!h&&!Zr(W)&&!J?G(Ar,{title:"暂无过程详情",text:"当前选择还没有可匹配的 procedure 运行记录。"}):null,!h&&Zr(W)?G(_Y,{procedure:W,matchedStepKey:Z,matchedAttemptId:H}):null)}function AY({value:u}){let l=String(u||"--").split(/([_-])/u);return G(Rn.default.Fragment,null,l.map((r,n)=>r==="-"||r==="_"?G(Rn.default.Fragment,{key:n},r,G("wbr",null)):G(Rn.default.Fragment,{key:n},r)))}async function Pn(u,f={}){return Eu(u,{invalidJsonPrefix:"Pipeline 返回了无效 JSON",...f})}function xn({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return G("span",{className:`status-badge ${l}`},f||u||"unknown")}function Xl({label:u,value:f,hint:l,tone:r}){return G("article",{className:`metric-card ${r||""}`},G("div",{className:"metric-label"},u),G("div",{className:"metric-value"},f),G("div",{className:"metric-hint"},l))}function c0({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return G("section",{className:`panel ${n||""}`},G("div",{className:"panel-head"},G("div",null,f?G("p",{className:"panel-eyebrow"},f):null,G(nf,{title:u,loading:i})),l?G("div",{className:"panel-actions"},l):null),G("div",{className:"panel-body"},r))}function kr({title:u,data:f,onOpen:l,testId:r}){return G("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function Tr({title:u,subtitle:f,facts:l,data:r,onRaw:n,testId:i}){let y=Vu(l).map((_)=>String(_||"")).filter(Boolean);return G("article",{className:"pipeline-evidence-row"},G("div",{className:"pipeline-evidence-main"},G("strong",null,u),f?G("span",null,f):null),G("div",{className:"pipeline-evidence-facts"},y.map((_,$)=>G("span",{key:`${$}-${_.slice(0,16)}`},_))),r!==void 0?G(kr,{title:u,data:r,onOpen:n,testId:i}):null)}function Ar({title:u,text:f}){return G("div",{className:"empty-state"},G("strong",null,u),G("span",null,f))}function jY(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function FY(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function JY(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function UY(u){return{components:Array.isArray(u?.registry?.components)?u.registry.components:[],pipelines:Array.isArray(u?.pipelines)?u.pipelines:[],runs:Array.isArray(u?.runs)?u.runs:[]}}function sW(u,f,l){let r=u?._unidesk?.arrayLimits?.[f],n=Number(r?.originalLength);return Number.isFinite(n)?n:l}function Jw(u){if(!u||typeof u!=="object"||Array.isArray(u))return"--";return`${u.componentClass||"--"}/${u.id||"--"}`}function J8(u){if(!u||typeof u!=="object"||Array.isArray(u))return"";let f=String(u.componentClass||"").trim(),l=String(u.id||"").trim();return f&&l?`${f}/${l}`:""}function V9(u){return u?.config&&typeof u.config==="object"&&!Array.isArray(u.config)?u.config:{}}function Uw(u){let f=V9(u),l=Array.isArray(f.nodes)?f.nodes:Array.isArray(u?.nodes)?u.nodes:[],r=new Map;for(let y of l){let _=String(y?.id||y?.nodeId||"");if(_)r.set(_,{...y,id:_})}let n=D9(u),i=(y)=>{if(y&&!r.has(y))r.set(y,{id:y})};for(let y of X9(u))D$(y).forEach(i);for(let y of n)i(String(y?.from||y?.source||"")),i(String(y?.to||y?.target||""));return Array.from(r.values())}function D9(u){let f=V9(u);return Array.isArray(f.edges)?f.edges:Array.isArray(u?.edges)?u.edges:[]}function X9(u){let f=V9(u);return Array.isArray(f.topologicalBatches)?f.topologicalBatches:Array.isArray(u?.topologicalBatches)?u.topologicalBatches:[]}function QY(u){let f=new Map;for(let l of u){let r=J8(l);if(r)f.set(r,l);let n=Array.isArray(l?.refs)?l.refs:[];for(let i of n){let y=J8(i);if(y)f.set(y,l)}}return f}function aW(u,f){let l=f.get(J8(u?.componentRef));if(l)return l;let r=J8({componentClass:u?.kind,id:u?.id});return r?f.get(r)||null:null}function oW(u,f){let l=Qw(u,f);return String(l?.status||"pending")}function Qw(u,f){return(Array.isArray(u?.nodes)?u.nodes:[]).find((r)=>r?.nodeId===f||r?.id===f)||null}function qY(u){return u.reduce((f,l)=>{let r=String(l?.status||"unknown").toLowerCase();return f[r]=(f[r]||0)+1,f},{})}function NY(u){if(Array.isArray(u?.scorers))return u.scorers.filter(Du);if(Array.isArray(u?.summary?.scorers))return u.summary.scorers.filter(Du);if(Array.isArray(u?.artifact?.summary?.scorers))return u.artifact.summary.scorers.filter(Du);return[]}function WY(u){if(Du(u?.run))return u.run;if(Du(u?.runSummary))return u.runSummary;return null}function wY(u,f){if(!Du(u)&&!Du(f))return null;if(!Du(u))return f;if(!Du(f))return u;return{...u,...f,request:Du(u.request)||Du(f.request)?{...Du(u.request)?u.request:{},...Du(f.request)?f.request:{}}:f.request??u.request,artifact:Du(u.artifact)||Du(f.artifact)?{...Du(u.artifact)?u.artifact:{},...Du(f.artifact)?f.artifact:{}}:f.artifact??u.artifact,summary:Du(u.summary)||Du(f.summary)?{...Du(u.summary)?u.summary:{},...Du(f.summary)?f.summary:{}}:f.summary??u.summary}}function U8(u){let f=NY(u),l=f.find((A)=>Du(A?.score))||f[0]||null,r=Du(l?.score)?l.score:{},n=Number(r.passed),i=Number(r.total),y=Number(r.ratio),_=Number.isFinite(y)?y:Number.isFinite(n)&&Number.isFinite(i)&&i>0?n/i:null,$=_===null?null:Math.round(Math.max(0,Math.min(100,_<=1?_*100:_))),c=String(r.text||(Number.isFinite(n)&&Number.isFinite(i)?`${n}/${i}`:""));return{scorer:l,scorers:f,score:r,passed:Number.isFinite(n)?n:null,total:Number.isFinite(i)?i:null,percent:$,text:c}}function z9(u){let f=U8(u);return f.text||(f.scorers.length>0?String(f.scorer?.status||"pending"):"--")}function Y9(u){let f=U8(u);if(f.total>0&&f.passed===f.total)return"succeeded";if(f.total>0&&f.passed>0)return"running";if(f.scorers.length>0)return"failed";return"pending"}function LY(u){return Array.isArray(u?.items)?u.items.filter(Du):[]}function KY({run:u}){let f=z9(u);return G("span",{className:`pipeline-score-badge ${Y9(u)}`},`score ${f}`)}function GY({run:u,onRaw:f}){let r=U8(u).scorers;if(!u)return G(Ar,{title:"暂无评分",text:"选择一个 epoch 后会显示 scorer 结果。"});if(r.length===0)return G("div",{className:"pipeline-score-empty"},G("strong",null,"评分器等待中"),G("span",null,"DAG 完成后,Pipeline control backend 会把 scorer summary 追加到 run artifact,并通过 UniDesk 显示。"));return G("div",{className:"pipeline-score-board","data-testid":"pipeline-score-board"},r.map((n,i)=>{let y=U8({scorers:[n]}),_=LY(n),$=y.percent??0;return G("article",{key:`${n.scorerId||n.component||i}`,className:`pipeline-score-card ${Y9({scorers:[n]})}`},G("div",{className:"pipeline-score-head"},G("div",null,G("span",null,n.scorerId||n.component||"scorer"),G("strong",null,y.text||n.status||"--")),G(xn,{status:n.status||"unknown"},n.status||"unknown")),G("div",{className:"pipeline-score-meter","aria-label":`score ${$}%`},G("span",{style:{width:`${$}%`}})),G("div",{className:"pipeline-score-facts"},G("span",null,`${$}%`),G("span",null,n.component||"--"),G("span",null,n.applicationCheckoutRef||"--")),_.length>0?G("div",{className:"pipeline-score-items"},_.map((c)=>G("span",{key:`${c.id||c.filter}`,className:`pipeline-score-item ${String(c.status||"").toLowerCase()}`,title:`${c.filter||"--"} / ran=${c.ran??"?"}`},G("b",null,c.id||"--"),G("small",null,c.status||"--")))):G("p",{className:"muted paragraph"},"当前 scorer 尚未返回 item 级结果。"),n.error?G("p",{className:"pipeline-score-error"},tw(n.error,360)):null,G("div",{className:"panel-actions inline-actions"},G(kr,{title:`Scorer ${n.scorerId||i}`,data:n,onOpen:f,testId:"raw-pipeline-score"})))}))}function zY(u){let f=u.reduce((l,r)=>{let n=String(r?.componentClass||"unknown");return l[n]=(l[n]||0)+1,l},{});return Object.entries(f).map(([l,r])=>({name:l,count:Number(r)})).sort((l,r)=>r.count-l.count||l.name.localeCompare(r.name))}function D$(u){if(Array.isArray(u))return u.map((f)=>typeof f==="string"?f:String(f?.id||f?.nodeId||"")).filter(Boolean);if(Array.isArray(u?.nodes))return D$(u.nodes);if(Array.isArray(u?.nodeIds))return D$(u.nodeIds);return[]}function TY(u){return Du(u?.instanceInputs?.monitor)?u.instanceInputs.monitor:{}}function qw(u,f){if(String(u?.kind||"").toLowerCase()!=="procedure")return!1;let l=TY(u);if(u?.instanceInputs?.monitorMode===!0||l.enabled===!0)return!0;let r=Jw(u?.componentRef);return String(f?.id||f?.config?.id||r||"").toLowerCase().includes("monitor")}function EY(u){return u.filter((f)=>qw(f)).map((f)=>String(f?.id||"")).filter(Boolean)}function ZY(u,f){if(f.length===0)return u;let l=new Set(f),r=f.filter((n)=>u.includes(n));if(r.length===0)return u;return[...r,...u.filter((n)=>!l.has(n))]}function OY(u,f){if(f.length===0)return u;let l=new Set(f),r=f.filter((i)=>u.some((y)=>y.includes(i)));if(r.length===0)return u;let n=u.map((i)=>i.filter((y)=>!l.has(y))).filter((i)=>i.length>0);return[r,...n]}function HY(u,f,l){let n=X9(u).map(D$).filter((F)=>F.length>0);if(n.length>0)return n;let i=f.map((F)=>String(F?.id||"")).filter(Boolean),y=new Set(i),_=new Map(i.map((F)=>[F,0])),$=new Map(i.map((F)=>[F,[]]));for(let F of l){let U=String(F?.from||F?.source||""),Q=String(F?.to||F?.target||"");if(!y.has(U)||!y.has(Q))continue;$.get(U)?.push(Q),_.set(Q,(_.get(Q)||0)+1)}let c=new Map,A=i.filter((F)=>(_.get(F)||0)===0);for(let F of A)c.set(F,0);while(A.length>0){let F=A.shift(),U=(c.get(F)||0)+1;for(let Q of $.get(F)||[])if(_.set(Q,Math.max(0,(_.get(Q)||0)-1)),c.set(Q,Math.max(c.get(Q)||0,U)),(_.get(Q)||0)===0)A.push(Q)}i.forEach((F)=>{if(!c.has(F))c.set(F,0)});let j=Math.max(0,...Array.from(c.values()));return Array.from({length:j+1},(F,U)=>i.filter((Q)=>c.get(Q)===U)).filter((F)=>F.length>0)}function BY(u,f,l){let n=X9(u).map(D$).filter((_)=>_.length>0),i=n.length>0?n.flatMap((_)=>_):(()=>{let _=f.map((w)=>String(w?.id||"")).filter(Boolean),$=new Set(_),c=l.filter((w)=>String(w?.edgeType||"").toLowerCase()!=="rework"),A=new Map(_.map((w)=>[w,0])),j=new Map(_.map((w)=>[w,[]]));for(let w of c){let L=String(w?.from||w?.source||""),J=String(w?.to||w?.target||"");if(!$.has(L)||!$.has(J))continue;j.get(L)?.push(J),A.set(J,(A.get(J)||0)+1)}let F=new Map,U=_.filter((w)=>(A.get(w)||0)===0);for(let w of U)F.set(w,0);while(U.length>0){let w=U.shift(),L=(F.get(w)||0)+1;for(let J of j.get(w)||[])if(A.set(J,Math.max(0,(A.get(J)||0)-1)),F.set(J,Math.max(F.get(J)||0,L)),(A.get(J)||0)===0)U.push(J)}_.forEach((w)=>{if(!F.has(w))F.set(w,0)});let Q=Math.max(0,...Array.from(F.values()));return Array.from({length:Q+1},(w,L)=>_.filter((J)=>F.get(J)===L)).flatMap((w)=>w)})(),y=new Set(i);for(let _ of f){let $=String(_?.id||"");if(!$||y.has($))continue;i.push($),y.add($)}return ZY(i,EY(f))}function T$(u){return`${u.source}->${u.target}-${u.index}`}function dW(u,f,l){let r=Uw(u),n=D9(u),i=QY(l),y=new Map(r.map((m)=>[String(m?.id||""),m])),_=r.filter((m)=>qw(m,aW(m,i))).map((m)=>String(m?.id||"")).filter(Boolean),$=OY(HY(u,r,n),_),c=[],A=new Map,j=330,F=122;$.forEach((m,O)=>{let p=m.length*122;m.forEach((Y,v)=>{let T=y.get(Y)||{id:Y},S=aW(T,i),k=oW(f,Y).toLowerCase(),I=String(T.kind||S?.componentClass||"node").toLowerCase(),b=Jw(T.componentRef||S),o=String(S?.config?.version||S?.version||""),s=String(S?.config?.description||S?.description||""),x=v*122-Math.floor(p/2);A.set(Y,{column:O,row:v,y:x}),c.push({id:Y,type:"pipelineNode",position:{x:O*330,y:x},data:{exportLabel:{id:Y,kind:I,componentRef:b,componentVersion:o,componentDescription:s,status:k},label:G("div",{className:"flow-node-label"},G("strong",null,Y),G("span",null,I),G("code",{title:s||b},o?`${b}@${o}`:b),G(xn,{status:k},k))},className:`pipeline-flow-node ${I} ${k}`})})});let U=n.flatMap((m,O)=>{let p=String(m?.from||m?.source||""),Y=String(m?.to||m?.target||"");if(!y.has(p)||!y.has(Y))return[];return[{source:p,target:Y,index:O,condition:m?.condition,edgeType:m?.edgeType}]}),Q=U.reduce((m,O)=>m.set(O.source,(m.get(O.source)||0)+1),new Map),w=U.reduce((m,O)=>m.set(O.target,(m.get(O.target)||0)+1),new Map),L=U.reduce((m,O)=>{let p=`${O.source}->${O.target}`;return m.set(p,(m.get(p)||0)+1)},new Map),J=new Map,N=new Map,q=new Map,W=new Map,z=new Map,Z=new Map,H=U.reduce((m,O)=>{let p=A.get(O.source),Y=A.get(O.target),v=(Y?.column||0)-(p?.column||0);if(v<=0||String(O.edgeType||"").toLowerCase()==="rework"||v!==1)return m;let S=`${O.source}->column:${Y?.column??""}`,k=m.get(S)||[];return k.push(O),m.set(S,k),m},new Map);for(let m of H.values()){if(m.length<2)continue;m.slice().sort((O,p)=>{let Y=A.get(O.target),v=A.get(p.target);return(Y?.y||0)-(v?.y||0)||O.index-p.index}).forEach((O,p,Y)=>{Z.set(T$(O),{slot:p-(Y.length-1)/2,count:Y.length})})}[...U].sort((m,O)=>{let p=A.get(m.source),Y=A.get(m.target),v=A.get(O.source),T=A.get(O.target),S=Math.abs((Y?.column||0)-(p?.column||0))*330+Math.abs((Y?.y||0)-(p?.y||0)),k=Math.abs((T?.column||0)-(v?.column||0))*330+Math.abs((T?.y||0)-(v?.y||0));return S-k||m.index-O.index}).forEach((m)=>{let O=A.get(m.source)||{column:0,row:0,y:0},p=A.get(m.target)||{column:0,row:0,y:0},Y=p.column-O.column,v=Math.max(0,Y),T=Y<=0||String(m.edgeType||"").toLowerCase()==="rework",S=O.y-p.y,k=w.get(m.target)||1,I=Z.has(T$(m)),b=!T&&v<=1&&(I||k===1),o=z.get(m.target)||new Map;z.set(m.target,o);let s=B$.slice().sort((x,fu)=>{let $u=(qu)=>{let P=String(qu.side),e=0;if(T){if(P==="left")e+=86;if(P==="top")e+=p.y<=0?-22:12;if(P==="bottom")e+=p.y>=0?-22:12;if(Math.abs(p.y)<12&&P!=="left")e+=m.index%2===0?P==="top"?-6:6:P==="bottom"?-6:6;return e}if(b){if(P==="left")e-=I?72:44;if(P!=="left")e+=I?72:44;return e+Math.abs(S)*0.02}if(P==="left")e+=v<=1?0:24;if(P==="top")e+=S<-36?-18:42;if(P==="bottom")e+=S>36?-18:42;if(v<=1&&Math.abs(S)<=82&&P!=="left")e+=38;if(v>1&&P!=="left")e-=10;return e},tu=O.y-p.y,ju=tu!==0?tu:m.index%2===0?-1:1,Gu=(qu)=>{let P=o.get(qu.id)||0;return $u(qu)+P*64+gX(qu,o,ju)};return Gu(x)-Gu(fu)||String(x.id).localeCompare(String(fu.id))})[0];o.set(s.id,(o.get(s.id)||0)+1),W.set(T$(m),s)});let D=U.map((m)=>{let O=oW(f,m.target).toLowerCase(),p=`${m.source}->${m.target}`,Y=J.get(m.source)||0,v=N.get(m.target)||0,T=q.get(p)||0;J.set(m.source,Y+1),N.set(m.target,v+1),q.set(p,T+1);let S=Y-((Q.get(m.source)||1)-1)/2,k=v-((w.get(m.target)||1)-1)/2,I=T-((L.get(p)||1)-1)/2,b=A.get(m.source),o=A.get(m.target),s=(o?.column||0)-(b?.column||0),x=Math.max(1,Math.abs(s)),fu=s<=0||String(m.edgeType||"").toLowerCase()==="rework",$u=Math.abs((o?.y||0)-(b?.y||0)),tu=Z.get(T$(m)),ju=!fu&&s===1&&(w.get(m.target)||0)>1,Gu=tu?tu.slot:I*2+S+k*0.45,qu=Gu===0?m.index%2===0?-1:1:Math.sign(Gu),P=W.get(T$(m))||B$[1],e=P.side==="top"?-1:P.side==="bottom"?1:qu,uu=fu||x>1||$u>96||Math.abs(Gu)>0.2||P.side!=="left",Wu=fu?118+x*18:22+x*16,g=P.side==="left"?0:28,Qu=uu?Math.max(-280,Math.min(280,e*Math.min(180,Wu+g+$u*0.22)+Gu*28)):0,Tu=Math.max(0,Math.min(Z$.length-1,Math.round(S+(Z$.length-1)/2))),Zu=Z$[Tu]||Z$[1],Xu=O==="succeeded"?"var(--accent-2)":O==="running"?"var(--accent)":O==="failed"?"var(--danger)":"rgba(129, 147, 159, 0.78)",ff=b?.column||0,_f=o?.column||0,Jf=Qu===0?0:Math.sign(Qu),mf=fu?`feedback:${ff}->${_f}:${Jf}`:tu?`fanout:${ff}->${_f}:${m.source}`:ju?`fanin:${ff}->${_f}:${m.target}`:P.side!=="left"||x>1?`corridor:${ff}->${_f}:${P.side}:${Jf}:${Math.round(Math.abs(Qu)/56)}`:"";return{id:`${m.source}->${m.target}-${m.index}`,source:m.source,target:m.target,sourceHandle:Zu.id,targetHandle:P.id,type:"pipelineCurve",zIndex:12,animated:O==="running",data:{baseEdgeColor:Xu,laneOffset:Qu,routeMode:tu&&P.side==="left"?"direct-forward-left":"",targetSide:P.side,isFeedback:fu,overlapGroup:mf},targetStatus:O}}),h=D.reduce((m,O)=>{let p=String(O.data?.overlapGroup||"");return p?m.set(p,(m.get(p)||0)+1):m},new Map),B=new Map,X=D.map((m)=>{let O=String(m.targetStatus||"pending"),p={...m};delete p.targetStatus;let Y=String(m.data?.overlapGroup||""),v=Y?h.get(Y)||0:0,T=v>1?B.get(Y)||0:-1;if(v>1)B.set(Y,T+1);let S=T>=0?MW[T%MW.length]:String(m.data.baseEdgeColor),k={stroke:S};if(m.data.isFeedback)k.strokeDasharray="9 7";return{...p,data:{...m.data,edgeColor:S,overlapSlot:T,overlapCount:v},style:k,markerEnd:{type:Yn.ArrowClosed,color:S},className:`pipeline-flow-edge ${O} ${m.data.isFeedback?"feedback":""} ${T>=0?"overlap-colored":""}`}});return{nodes:c,edges:X}}function Il(u){return String(u??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function eW(u){let f=String(u||"");if(f.includes("--accent-2"))return"#4eb7a8";if(f.includes("--accent"))return"#d7a13a";if(f.includes("--danger"))return"#cf6a54";return f.startsWith("#")?f:"#81939f"}function Q8(u){return`arrow-${u.replace(/[^a-zA-Z0-9_-]+/g,"")}`}function Nw(u,f="pipeline"){return String(u||f).replace(/[^a-zA-Z0-9_-]+/g,"-").replace(/^-|-$/g,"")||f}function uw(u,f){let l=u.position.x,r=u.position.y,n=B$.find((i)=>i.id===f);if(n?.side==="top")return{x:l+jy*xW(n.style?.left,0.5),y:r,position:Lu.Top};if(n?.side==="bottom")return{x:l+jy*xW(n.style?.left,0.5),y:r+Fy,position:Lu.Bottom};return{x:l,y:r+Fy/2,position:Lu.Left}}function VY(u){return{x:u.position.x+jy,y:u.position.y+Fy/2}}function DY(u,f){let l=Math.min(...u.nodes.map((w)=>w.position.x),0)-220,r=Math.min(...u.nodes.map((w)=>w.position.y),0)-220,n=Math.max(...u.nodes.map((w)=>w.position.x+jy),1)+220,i=Math.max(...u.nodes.map((w)=>w.position.y+Fy),1)+220,y=Math.ceil(n-l),_=Math.ceil(i-r),$=new Map(u.nodes.map((w)=>[w.id,w])),c=u.edges.map((w)=>eW(w.data?.edgeColor||w.style?.stroke)),j=Array.from(new Set(["#4eb7a8","#d7a13a","#cf6a54","#81939f",...c])).map((w)=>``).join(""),F=u.edges.flatMap((w)=>{let L=$.get(w.source),J=$.get(w.target);if(!L||!J)return[];let N=VY(L),q=uw(J,String(w.targetHandle||"in-left")),W=yw(N.x,N.y,q.x,q.y,q.position,Number(w.data?.laneOffset||0),String(w.data?.routeMode||"")),z=eW(w.data?.edgeColor||w.style?.stroke),Z=w.data?.isFeedback?' stroke-dasharray="9 7"':"";return``}).join(` -`),U=u.nodes.map((w)=>{let L=w.data?.exportLabel||{},J=String(L.status||"pending").toLowerCase(),N=J==="succeeded"?"#4eb7a8":J==="running"?"#d7a13a":J==="failed"?"#cf6a54":"#81939f",q=w.position.x,W=w.position.y,z=B$.map((Z)=>{let H=uw(w,Z.id);if(Z.side==="top"||Z.side==="bottom")return``;return``}).join(` +`)),c=A.reduce((j,F)=>j.concat(...F),[]);return[A,c]}return[[],[]]},[u]);return yu.useEffect(()=>{let $=f?.target??bN,A=f?.actInsideInputWithModifier??!0;if(u!==null){let c=(U)=>{if(n.current=U.ctrlKey||U.metaKey||U.shiftKey||U.altKey,(!n.current||n.current&&!A)&&ac(U))return!1;let L=kN(U.code,_);if(i.current.add(U[L]),vN(y,i.current,!1)){let w=U.composedPath?.()?.[0]||U.target,J=w?.nodeName==="BUTTON"||w?.nodeName==="A";if(f.preventDefault!==!1&&(n.current||!J))U.preventDefault();r(!0)}},j=(U)=>{let Q=kN(U.code,_);if(vN(y,i.current,!0))r(!1),i.current.clear();else i.current.delete(U[Q]);if(U.key==="Meta")i.current.clear();n.current=!1},F=()=>{i.current.clear(),r(!1)};return $?.addEventListener("keydown",c),$?.addEventListener("keyup",j),window.addEventListener("blur",F),window.addEventListener("contextmenu",F),()=>{$?.removeEventListener("keydown",c),$?.removeEventListener("keyup",j),window.removeEventListener("blur",F),window.removeEventListener("contextmenu",F)}}},[u,r]),l}function vN(u,f,l){return u.filter((r)=>l||r.length===f.size).some((r)=>r.every((n)=>f.has(n)))}function kN(u,f){return f.includes(u)?"code":"key"}var AD=()=>{let u=Zf();return yu.useMemo(()=>{return{zoomIn:(f)=>{let{panZoom:l}=u.getState();return l?l.scaleBy(1.2,f):Promise.resolve(!1)},zoomOut:(f)=>{let{panZoom:l}=u.getState();return l?l.scaleBy(0.8333333333333334,f):Promise.resolve(!1)},zoomTo:(f,l)=>{let{panZoom:r}=u.getState();return r?r.scaleTo(f,l):Promise.resolve(!1)},getZoom:()=>u.getState().transform[2],setViewport:async(f,l)=>{let{transform:[r,n,i],panZoom:y}=u.getState();if(!y)return Promise.resolve(!1);return await y.setViewport({x:f.x??r,y:f.y??n,zoom:f.zoom??i},l),Promise.resolve(!0)},getViewport:()=>{let[f,l,r]=u.getState().transform;return{x:f,y:l,zoom:r}},setCenter:async(f,l,r)=>{return u.getState().setCenter(f,l,r)},fitBounds:async(f,l)=>{let{width:r,height:n,minZoom:i,maxZoom:y,panZoom:_}=u.getState(),$=K$(f,r,n,i,y,l?.padding??0.1);if(!_)return Promise.resolve(!1);return await _.setViewport($,{duration:l?.duration,ease:l?.ease,interpolate:l?.interpolate}),Promise.resolve(!0)},screenToFlowPosition:(f,l={})=>{let{transform:r,snapGrid:n,snapToGrid:i,domNode:y}=u.getState();if(!y)return f;let{x:_,y:$}=y.getBoundingClientRect(),A={x:f.x-_,y:f.y-$},c=l.snapGrid??n,j=l.snapToGrid??i;return yy(A,r,j,c)},flowToScreenPosition:(f)=>{let{transform:l,domNode:r}=u.getState();if(!r)return f;let{x:n,y:i}=r.getBoundingClientRect(),y=L$(f,l);return{x:y.x+n,y:y.y+i}}}},[])};function FW(u,f){let l=[],r=new Map,n=[];for(let i of u)if(i.type==="add"){n.push(i);continue}else if(i.type==="remove"||i.type==="replace")r.set(i.id,[i]);else{let y=r.get(i.id);if(y)y.push(i);else r.set(i.id,[i])}for(let i of f){let y=r.get(i.id);if(!y){l.push(i);continue}if(y[0].type==="remove")continue;if(y[0].type==="replace"){l.push({...y[0].item});continue}let _={...i};for(let $ of y)cD($,_);l.push(_)}if(n.length)n.forEach((i)=>{if(i.index!==void 0)l.splice(i.index,0,{...i.item});else l.push({...i.item})});return l}function cD(u,f){switch(u.type){case"select":{f.selected=u.selected;break}case"position":{if(typeof u.position<"u")f.position=u.position;if(typeof u.dragging<"u")f.dragging=u.dragging;break}case"dimensions":{if(typeof u.dimensions<"u"){if(f.measured={...u.dimensions},u.setAttributes){if(u.setAttributes===!0||u.setAttributes==="width")f.width=u.dimensions.width;if(u.setAttributes===!0||u.setAttributes==="height")f.height=u.dimensions.height}}if(typeof u.resizing==="boolean")f.resizing=u.resizing;break}}}function jD(u,f){return FW(u,f)}function FD(u,f){return FW(u,f)}function p1(u,f){return{id:u,type:"select",selected:f}}function ty(u,f=new Set,l=!1){let r=[];for(let[n,i]of u){let y=f.has(n);if(!(i.selected===void 0&&!y)&&i.selected!==y){if(l)i.selected=y;r.push(p1(i.id,y))}}return r}function IN({items:u=[],lookup:f}){let l=[],r=new Map(u.map((n)=>[n.id,n]));for(let[n,i]of u.entries()){let y=f.get(i.id),_=y?.internals?.userNode??y;if(_!==void 0&&_!==i)l.push({id:i.id,item:i,type:"replace"});if(_===void 0)l.push({item:i,type:"add",index:n})}for(let[n]of f)if(r.get(n)===void 0)l.push({id:n,type:"remove"});return l}function gN(u){return{id:u.id,type:"remove"}}var sN=(u)=>oq(u),JD=(u)=>Mc(u);function JW(u){return yu.forwardRef(u)}function aN(u){let[f,l]=yu.useState(BigInt(0)),[r]=yu.useState(()=>UD(()=>l((n)=>n+BigInt(1))));return t9(()=>{let n=r.get();if(n.length)u(n),r.reset()},[f]),r}function UD(u){let f=[];return{get:()=>f,reset:()=>{f=[]},push:(l)=>{f.push(l),u()}}}var UW=yu.createContext(null);function QD({children:u}){let f=Zf(),l=yu.useCallback((_)=>{let{nodes:$=[],setNodes:A,hasDefaultNodes:c,onNodesChange:j,nodeLookup:F,fitViewQueued:U,onNodesChangeMiddlewareMap:Q}=f.getState(),L=$;for(let J of _)L=typeof J==="function"?J(L):J;let w=IN({items:L,lookup:F});for(let J of Q.values())w=J(w);if(c)A(L);if(w.length>0)j?.(w);else if(U)window.requestAnimationFrame(()=>{let{fitViewQueued:J,nodes:N,setNodes:q}=f.getState();if(J)q(N)})},[]),r=aN(l),n=yu.useCallback((_)=>{let{edges:$=[],setEdges:A,hasDefaultEdges:c,onEdgesChange:j,edgeLookup:F}=f.getState(),U=$;for(let Q of _)U=typeof Q==="function"?Q(U):Q;if(c)A(U);else if(j)j(IN({items:U,lookup:F}))},[]),i=aN(n),y=yu.useMemo(()=>({nodeQueue:r,edgeQueue:i}),[]);return ru.jsx(UW.Provider,{value:y,children:u})}function qD(){let u=yu.useContext(UW);if(!u)throw Error("useBatchContext must be used within a BatchProvider");return u}var ND=(u)=>!!u.panZoom;function c9(){let u=AD(),f=Zf(),l=qD(),r=eu(ND),n=yu.useMemo(()=>{let i=(j)=>f.getState().nodeLookup.get(j),y=(j)=>{l.nodeQueue.push(j)},_=(j)=>{l.edgeQueue.push(j)},$=(j)=>{let{nodeLookup:F,nodeOrigin:U}=f.getState(),Q=sN(j)?j:F.get(j.id),L=Q.parentId?Ic(Q.position,Q.measured,Q.parentId,F,U):Q.position,w={...Q,position:L,width:Q.measured?.width??Q.width,height:Q.measured?.height??Q.height};return S1(w)},A=(j,F,U={replace:!1})=>{y((Q)=>Q.map((L)=>{if(L.id===j){let w=typeof F==="function"?F(L):F;return U.replace&&sN(w)?w:{...L,...w}}return L}))},c=(j,F,U={replace:!1})=>{_((Q)=>Q.map((L)=>{if(L.id===j){let w=typeof F==="function"?F(L):F;return U.replace&&JD(w)?w:{...L,...w}}return L}))};return{getNodes:()=>f.getState().nodes.map((j)=>({...j})),getNode:(j)=>i(j)?.internals.userNode,getInternalNode:i,getEdges:()=>{let{edges:j=[]}=f.getState();return j.map((F)=>({...F}))},getEdge:(j)=>f.getState().edgeLookup.get(j),setNodes:y,setEdges:_,addNodes:(j)=>{let F=Array.isArray(j)?j:[j];l.nodeQueue.push((U)=>[...U,...F])},addEdges:(j)=>{let F=Array.isArray(j)?j:[j];l.edgeQueue.push((U)=>[...U,...F])},toObject:()=>{let{nodes:j=[],edges:F=[],transform:U}=f.getState(),[Q,L,w]=U;return{nodes:j.map((J)=>({...J})),edges:F.map((J)=>({...J})),viewport:{x:Q,y:L,zoom:w}}},deleteElements:async({nodes:j=[],edges:F=[]})=>{let{nodes:U,edges:Q,onNodesDelete:L,onEdgesDelete:w,triggerNodeChanges:J,triggerEdgeChanges:N,onDelete:q,onBeforeDelete:W}=f.getState(),{nodes:z,edges:Z}=await uN({nodesToRemove:j,edgesToRemove:F,nodes:U,edges:Q,onBeforeDelete:W}),H=Z.length>0,E=z.length>0;if(H){let D=Z.map(gN);w?.(Z),N(D)}if(E){let D=z.map(gN);L?.(z),J(D)}if(E||H)q?.({nodes:z,edges:Z});return{deletedNodes:z,deletedEdges:Z}},getIntersectingNodes:(j,F=!0,U)=>{let Q=bc(j),L=Q?j:$(j),w=U!==void 0;if(!L)return[];return(U||f.getState().nodes).filter((J)=>{let N=f.getState().nodeLookup.get(J.id);if(N&&!Q&&(J.id===j.id||!N.internals.positionAbsolute))return!1;let q=S1(w?J:N),W=ny(q,L);return F&&W>0||W>=q.width*q.height||W>=L.width*L.height})},isNodeIntersecting:(j,F,U=!0)=>{let L=bc(j)?j:$(j);if(!L)return!1;let w=ny(L,F);return U&&w>0||w>=F.width*F.height||w>=L.width*L.height},updateNode:A,updateNodeData:(j,F,U={replace:!1})=>{A(j,(Q)=>{let L=typeof F==="function"?F(Q):F;return U.replace?{...Q,data:L}:{...Q,data:{...Q.data,...L}}},U)},updateEdge:c,updateEdgeData:(j,F,U={replace:!1})=>{c(j,(Q)=>{let L=typeof F==="function"?F(Q):F;return U.replace?{...Q,data:L}:{...Q,data:{...Q.data,...L}}},U)},getNodesBounds:(j)=>{let{nodeLookup:F,nodeOrigin:U}=f.getState();return Rc(j,{nodeLookup:F,nodeOrigin:U})},getHandleConnections:({type:j,id:F,nodeId:U})=>Array.from(f.getState().connectionLookup.get(`${U}-${j}${F?`-${F}`:""}`)?.values()??[]),getNodeConnections:({type:j,handleId:F,nodeId:U})=>Array.from(f.getState().connectionLookup.get(`${U}${j?F?`-${j}-${F}`:`-${j}`:""}`)?.values()??[]),fitView:async(j)=>{let F=f.getState().fitViewResolver??rN();return f.setState({fitViewQueued:!0,fitViewOptions:j,fitViewResolver:F}),l.nodeQueue.push((U)=>[...U]),F.promise}}},[]);return yu.useMemo(()=>{return{...n,...u,viewportInitialized:r}},[r])}var oN=(u)=>u.selected,WD=typeof window<"u"?window:void 0;function LD({deleteKeyCode:u,multiSelectionKeyCode:f}){let l=Zf(),{deleteElements:r}=c9(),n=z$(u,{actInsideInputWithModifier:!1}),i=z$(f,{target:WD});yu.useEffect(()=>{if(n){let{edges:y,nodes:_}=l.getState();r({nodes:_.filter(oN),edges:y.filter(oN)}),l.setState({nodesSelectionActive:!1})}},[n]),yu.useEffect(()=>{l.setState({multiSelectionActive:i})},[i])}function wD(u){let f=Zf();yu.useEffect(()=>{let l=()=>{if(!u.current||!(u.current.checkVisibility?.()??!0))return!1;let r=b6(u.current);if(r.height===0||r.width===0)f.getState().onError?.("004",Fr.error004());f.setState({width:r.width||500,height:r.height||500})};if(u.current){l(),window.addEventListener("resize",l);let r=new ResizeObserver(()=>l());return r.observe(u.current),()=>{if(window.removeEventListener("resize",l),r&&u.current)r.unobserve(u.current)}}},[])}var i8={position:"absolute",width:"100%",height:"100%",top:0,left:0},KD=(u)=>({userSelectionActive:u.userSelectionActive,lib:u.lib,connectionInProgress:u.connection.inProgress});function GD({onPaneContextMenu:u,zoomOnScroll:f=!0,zoomOnPinch:l=!0,panOnScroll:r=!1,panOnScrollSpeed:n=0.5,panOnScrollMode:i=C0.Free,zoomOnDoubleClick:y=!0,panOnDrag:_=!0,defaultViewport:$,translateExtent:A,minZoom:c,maxZoom:j,zoomActivationKeyCode:F,preventScrolling:U=!0,children:Q,noWheelClassName:L,noPanClassName:w,onViewportChange:J,isControlledViewport:N,paneClickDistance:q,selectionOnDrag:W}){let z=Zf(),Z=yu.useRef(null),{userSelectionActive:H,lib:E,connectionInProgress:D}=eu(KD,zf),h=z$(F),V=yu.useRef();wD(Z);let Y=yu.useCallback((p)=>{if(J?.({x:p[0],y:p[1],zoom:p[2]}),!N)z.setState({transform:p})},[J,N]);return yu.useEffect(()=>{if(Z.current){V.current=GN({domNode:Z.current,minZoom:c,maxZoom:j,translateExtent:A,viewport:$,onDraggingChange:(X)=>z.setState((v)=>v.paneDragging===X?v:{paneDragging:X}),onPanZoomStart:(X,v)=>{let{onViewportChangeStart:T,onMoveStart:S}=z.getState();S?.(X,v),T?.(v)},onPanZoom:(X,v)=>{let{onViewportChange:T,onMove:S}=z.getState();S?.(X,v),T?.(v)},onPanZoomEnd:(X,v)=>{let{onViewportChangeEnd:T,onMoveEnd:S}=z.getState();S?.(X,v),T?.(v)}});let{x:p,y:O,zoom:m}=V.current.getViewport();return z.setState({panZoom:V.current,transform:[p,O,m],domNode:Z.current.closest(".react-flow")}),()=>{V.current?.destroy()}}},[]),yu.useEffect(()=>{V.current?.update({onPaneContextMenu:u,zoomOnScroll:f,zoomOnPinch:l,panOnScroll:r,panOnScrollSpeed:n,panOnScrollMode:i,zoomOnDoubleClick:y,panOnDrag:_,zoomActivationKeyPressed:h,preventScrolling:U,noPanClassName:w,userSelectionActive:H,noWheelClassName:L,lib:E,onTransformChange:Y,connectionInProgress:D,selectionOnDrag:W,paneClickDistance:q})},[u,f,l,r,n,i,y,_,h,U,w,H,L,E,Y,D,W,q]),ru.jsx("div",{className:"react-flow__renderer",ref:Z,style:i8,children:Q})}var zD=(u)=>({userSelectionActive:u.userSelectionActive,userSelectionRect:u.userSelectionRect});function TD(){let{userSelectionActive:u,userSelectionRect:f}=eu(zD,zf);if(!(u&&f))return null;return ru.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:f.width,height:f.height,transform:`translate(${f.x}px, ${f.y}px)`}})}var _9=(u,f)=>{return(l)=>{if(l.target!==f.current)return;u?.(l)}},ED=(u)=>({userSelectionActive:u.userSelectionActive,elementsSelectable:u.elementsSelectable,connectionInProgress:u.connection.inProgress,dragging:u.paneDragging});function ZD({isSelecting:u,selectionKeyPressed:f,selectionMode:l=X1.Full,panOnDrag:r,paneClickDistance:n,selectionOnDrag:i,onSelectionStart:y,onSelectionEnd:_,onPaneClick:$,onPaneContextMenu:A,onPaneScroll:c,onPaneMouseEnter:j,onPaneMouseMove:F,onPaneMouseLeave:U,children:Q}){let L=Zf(),{userSelectionActive:w,elementsSelectable:J,dragging:N,connectionInProgress:q}=eu(ED,zf),W=J&&(u||w),z=yu.useRef(null),Z=yu.useRef(),H=yu.useRef(new Set),E=yu.useRef(new Set),D=yu.useRef(!1),h=(T)=>{if(D.current||q){D.current=!1;return}$?.(T),L.getState().resetSelectedElements(),L.setState({nodesSelectionActive:!1})},V=(T)=>{if(Array.isArray(r)&&r?.includes(2)){T.preventDefault();return}A?.(T)},Y=c?(T)=>c(T):void 0,p=(T)=>{if(D.current)T.stopPropagation(),D.current=!1},O=(T)=>{let{domNode:S}=L.getState();if(Z.current=S?.getBoundingClientRect(),!Z.current)return;let k=T.target===z.current;if(!k&&!!T.target.closest(".nokey")||!u||!(i&&k||f)||T.button!==0||!T.isPrimary)return;T.target?.setPointerCapture?.(T.pointerId),D.current=!1;let{x:o,y:s}=Zr(T.nativeEvent,Z.current);if(L.setState({userSelectionRect:{width:0,height:0,startX:o,startY:s,x:o,y:s}}),!k)T.stopPropagation(),T.preventDefault()},m=(T)=>{let{userSelectionRect:S,transform:k,nodeLookup:I,edgeLookup:b,connectionLookup:o,triggerNodeChanges:s,triggerEdgeChanges:x,defaultEdgeOptions:fu,resetSelectedElements:$u}=L.getState();if(!Z.current||!S)return;let{x:tu,y:ju}=Zr(T.nativeEvent,Z.current),{startX:Gu,startY:qu}=S;if(!D.current){let g=f?0:n;if(Math.hypot(tu-Gu,ju-qu)<=g)return;$u(),y?.(T)}D.current=!0;let P={startX:Gu,startY:qu,x:tug.id)),E.current=new Set;let Wu=fu?.selectable??!0;for(let g of H.current){let Qu=o.get(g);if(!Qu)continue;for(let{edgeId:Tu}of Qu.values()){let Zu=b.get(Tu);if(Zu&&(Zu.selectable??Wu))E.current.add(Tu)}}if(!gc(e,H.current)){let g=ty(I,H.current,!0);s(g)}if(!gc(uu,E.current)){let g=ty(b,E.current);x(g)}L.setState({userSelectionRect:P,userSelectionActive:!0,nodesSelectionActive:!1})},X=(T)=>{if(T.button!==0)return;if(T.target?.releasePointerCapture?.(T.pointerId),!w&&T.target===z.current&&L.getState().userSelectionRect)h?.(T);if(L.setState({userSelectionActive:!1,userSelectionRect:null}),D.current)_?.(T),L.setState({nodesSelectionActive:H.current.size>0})},v=r===!0||Array.isArray(r)&&r.includes(0);return ru.jsxs("div",{className:Yf(["react-flow__pane",{draggable:v,dragging:N,selection:u}]),onClick:W?void 0:_9(h,z),onContextMenu:_9(V,z),onWheel:_9(Y,z),onPointerEnter:W?void 0:j,onPointerMove:W?m:F,onPointerUp:W?X:void 0,onPointerDownCapture:W?O:void 0,onClickCapture:W?p:void 0,onPointerLeave:U,ref:z,style:i8,children:[Q,ru.jsx(TD,{})]})}function A9({id:u,store:f,unselect:l=!1,nodeRef:r}){let{addSelectedNodes:n,unselectNodesAndEdges:i,multiSelectionActive:y,nodeLookup:_,onError:$}=f.getState(),A=_.get(u);if(!A){$?.("012",Fr.error012(u));return}if(f.setState({nodesSelectionActive:!1}),!A.selected)n([u]);else if(l||A.selected&&y)i({nodes:[A],edges:[]}),requestAnimationFrame(()=>r?.current?.blur())}function QW({nodeRef:u,disabled:f=!1,noDragClassName:l,handleSelector:r,nodeId:n,isSelectable:i,nodeClickDistance:y}){let _=Zf(),[$,A]=yu.useState(!1),c=yu.useRef();return yu.useEffect(()=>{c.current=UN({getStoreItems:()=>_.getState(),onNodeMouseDown:(j)=>{A9({id:j,store:_,nodeRef:u})},onDragStart:()=>{A(!0)},onDragStop:()=>{A(!1)}})},[]),yu.useEffect(()=>{if(f||!u.current||!c.current)return;return c.current.update({noDragClassName:l,handleSelector:r,domNode:u.current,isSelectable:i,nodeId:n,nodeClickDistance:y}),()=>{c.current?.destroy()}},[l,r,f,i,u,n,y]),$}var OD=(u)=>(f)=>f.selected&&(f.draggable||u&&typeof f.draggable>"u");function qW(){let u=Zf();return yu.useCallback((l)=>{let{nodeExtent:r,snapToGrid:n,snapGrid:i,nodesDraggable:y,onError:_,updateNodePositions:$,nodeLookup:A,nodeOrigin:c}=u.getState(),j=new Map,F=OD(y),U=n?i[0]:5,Q=n?i[1]:5,L=l.direction.x*U*l.factor,w=l.direction.y*Q*l.factor;for(let[,J]of A){if(!F(J))continue;let N={x:J.internals.positionAbsolute.x+L,y:J.internals.positionAbsolute.y+w};if(n)N=iy(N,i);let{position:q,positionAbsolute:W}=xc({nodeId:J.id,nextPosition:N,nodeLookup:A,nodeExtent:r,nodeOrigin:c,onError:_});J.position=q,J.internals.positionAbsolute=W,j.set(J.id,J)}$(j)},[])}var j9=yu.createContext(null),HD=j9.Provider;j9.Consumer;var NW=()=>{return yu.useContext(j9)},BD=(u)=>({connectOnClick:u.connectOnClick,noPanClassName:u.noPanClassName,rfId:u.rfId}),VD=(u,f,l)=>(r)=>{let{connectionClickStartHandle:n,connectionMode:i,connection:y}=r,{fromHandle:_,toHandle:$,isValid:A}=y,c=$?.nodeId===u&&$?.id===f&&$?.type===l;return{connectingFrom:_?.nodeId===u&&_?.id===f&&_?.type===l,connectingTo:c,clickConnecting:n?.nodeId===u&&n?.id===f&&n?.type===l,isPossibleEndHandle:i===Vn.Strict?_?.type!==l:u!==_?.nodeId||f!==_?.id,connectionInProcess:!!_,clickConnectionInProcess:!!n,valid:c&&A}};function DD({type:u="source",position:f=wu.Top,isValidConnection:l,isConnectable:r=!0,isConnectableStart:n=!0,isConnectableEnd:i=!0,id:y,onConnect:_,children:$,className:A,onMouseDown:c,onTouchStart:j,...F},U){let Q=y||null,L=u==="target",w=Zf(),J=NW(),{connectOnClick:N,noPanClassName:q,rfId:W}=eu(BD,zf),{connectingFrom:z,connectingTo:Z,clickConnecting:H,isPossibleEndHandle:E,connectionInProcess:D,clickConnectionInProcess:h,valid:V}=eu(VD(J,Q,u),zf);if(!J)w.getState().onError?.("010",Fr.error010());let Y=(m)=>{let{defaultEdgeOptions:X,onConnect:v,hasDefaultEdges:T}=w.getState(),S={...X,...m};if(T){let{edges:k,setEdges:I}=w.getState();I(ec(S,k))}v?.(S),_?.(S)},p=(m)=>{if(!J)return;let X=oc(m.nativeEvent);if(n&&(X&&m.button===0||!X)){let v=w.getState();o6.onPointerDown(m.nativeEvent,{handleDomNode:m.currentTarget,autoPanOnConnect:v.autoPanOnConnect,connectionMode:v.connectionMode,connectionRadius:v.connectionRadius,domNode:v.domNode,nodeLookup:v.nodeLookup,lib:v.lib,isTarget:L,handleId:Q,nodeId:J,flowId:v.rfId,panBy:v.panBy,cancelConnection:v.cancelConnection,onConnectStart:v.onConnectStart,onConnectEnd:(...T)=>w.getState().onConnectEnd?.(...T),updateConnection:v.updateConnection,onConnect:Y,isValidConnection:l||((...T)=>w.getState().isValidConnection?.(...T)??!0),getTransform:()=>w.getState().transform,getFromHandle:()=>w.getState().connection.fromHandle,autoPanSpeed:v.autoPanSpeed,dragThreshold:v.connectionDragThreshold})}if(X)c?.(m);else j?.(m)},O=(m)=>{let{onClickConnectStart:X,onClickConnectEnd:v,connectionClickStartHandle:T,connectionMode:S,isValidConnection:k,lib:I,rfId:b,nodeLookup:o,connection:s}=w.getState();if(!J||!T&&!n)return;if(!T){X?.(m.nativeEvent,{nodeId:J,handleId:Q,handleType:u}),w.setState({connectionClickStartHandle:{nodeId:J,type:u,id:Q}});return}let x=sc(m.target),fu=l||k,{connection:$u,isValid:tu}=o6.isValid(m.nativeEvent,{handle:{nodeId:J,id:Q,type:u},connectionMode:S,fromNodeId:T.nodeId,fromHandleId:T.id||null,fromType:T.type,isValidConnection:fu,flowId:b,doc:x,lib:I,nodeLookup:o});if(tu&&$u)Y($u);let ju=structuredClone(s);delete ju.inProgress,ju.toPosition=ju.toHandle?ju.toHandle.position:null,v?.(m,ju),w.setState({connectionClickStartHandle:null})};return ru.jsx("div",{"data-handleid":Q,"data-nodeid":J,"data-handlepos":f,"data-id":`${W}-${J}-${Q}-${u}`,className:Yf(["react-flow__handle",`react-flow__handle-${f}`,"nodrag",q,A,{source:!L,target:L,connectable:r,connectablestart:n,connectableend:i,clickconnecting:H,connectingfrom:z,connectingto:Z,valid:V,connectionindicator:r&&(!D||E)&&(D||h?i:n)}]),onMouseDown:p,onTouchStart:p,onClick:N?O:void 0,ref:U,...F,children:$})}var m1=yu.memo(JW(DD));function XD({data:u,isConnectable:f,sourcePosition:l=wu.Bottom}){return ru.jsxs(ru.Fragment,{children:[u?.label,ru.jsx(m1,{type:"source",position:l,isConnectable:f})]})}function YD({data:u,isConnectable:f,targetPosition:l=wu.Top,sourcePosition:r=wu.Bottom}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(m1,{type:"target",position:l,isConnectable:f}),u?.label,ru.jsx(m1,{type:"source",position:r,isConnectable:f})]})}function SD(){return null}function pD({data:u,isConnectable:f,targetPosition:l=wu.Top}){return ru.jsxs(ru.Fragment,{children:[ru.jsx(m1,{type:"target",position:l,isConnectable:f}),u?.label]})}var l8={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},dN={input:XD,default:YD,output:pD,group:SD};function mD(u){if(u.internals.handleBounds===void 0)return{width:u.width??u.initialWidth??u.style?.width,height:u.height??u.initialHeight??u.style?.height};return{width:u.width??u.style?.width,height:u.height??u.style?.height}}var PD=(u)=>{let{width:f,height:l,x:r,y:n}=ry(u.nodeLookup,{filter:(i)=>!!i.selected});return{width:Er(f)?f:null,height:Er(l)?l:null,userSelectionActive:u.userSelectionActive,transformString:`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]}) translate(${r}px,${n}px)`}};function MD({onSelectionContextMenu:u,noPanClassName:f,disableKeyboardA11y:l}){let r=Zf(),{width:n,height:i,transformString:y,userSelectionActive:_}=eu(PD,zf),$=qW(),A=yu.useRef(null);yu.useEffect(()=>{if(!l)A.current?.focus({preventScroll:!0})},[l]);let c=!_&&n!==null&&i!==null;if(QW({nodeRef:A,disabled:!c}),!c)return null;let j=u?(U)=>{let Q=r.getState().nodes.filter((L)=>L.selected);u(U,Q)}:void 0,F=(U)=>{if(Object.prototype.hasOwnProperty.call(l8,U.key))U.preventDefault(),$({direction:l8[U.key],factor:U.shiftKey?4:1})};return ru.jsx("div",{className:Yf(["react-flow__nodesselection","react-flow__container",f]),style:{transform:y},children:ru.jsx("div",{ref:A,className:"react-flow__nodesselection-rect",onContextMenu:j,tabIndex:l?void 0:-1,onKeyDown:l?void 0:F,style:{width:n,height:i}})})}var eN=typeof window<"u"?window:void 0,CD=(u)=>{return{nodesSelectionActive:u.nodesSelectionActive,userSelectionActive:u.userSelectionActive}};function WW({children:u,onPaneClick:f,onPaneMouseEnter:l,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,paneClickDistance:_,deleteKeyCode:$,selectionKeyCode:A,selectionOnDrag:c,selectionMode:j,onSelectionStart:F,onSelectionEnd:U,multiSelectionKeyCode:Q,panActivationKeyCode:L,zoomActivationKeyCode:w,elementsSelectable:J,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:W,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:E,defaultViewport:D,translateExtent:h,minZoom:V,maxZoom:Y,preventScrolling:p,onSelectionContextMenu:O,noWheelClassName:m,noPanClassName:X,disableKeyboardA11y:v,onViewportChange:T,isControlledViewport:S}){let{nodesSelectionActive:k,userSelectionActive:I}=eu(CD,zf),b=z$(A,{target:eN}),o=z$(L,{target:eN}),s=o||E,x=o||W,fu=c&&s!==!0,$u=b||I||fu;return LD({deleteKeyCode:$,multiSelectionKeyCode:Q}),ru.jsx(GD,{onPaneContextMenu:i,elementsSelectable:J,zoomOnScroll:N,zoomOnPinch:q,panOnScroll:x,panOnScrollSpeed:z,panOnScrollMode:Z,zoomOnDoubleClick:H,panOnDrag:!b&&s,defaultViewport:D,translateExtent:h,minZoom:V,maxZoom:Y,zoomActivationKeyCode:w,preventScrolling:p,noWheelClassName:m,noPanClassName:X,onViewportChange:T,isControlledViewport:S,paneClickDistance:_,selectionOnDrag:fu,children:ru.jsxs(ZD,{onSelectionStart:F,onSelectionEnd:U,onPaneClick:f,onPaneMouseEnter:l,onPaneMouseMove:r,onPaneMouseLeave:n,onPaneContextMenu:i,onPaneScroll:y,panOnDrag:s,isSelecting:!!$u,selectionMode:j,selectionKeyPressed:b,paneClickDistance:_,selectionOnDrag:fu,children:[u,k&&ru.jsx(MD,{onSelectionContextMenu:O,noPanClassName:X,disableKeyboardA11y:v})]})})}WW.displayName="FlowRenderer";var RD=yu.memo(WW),xD=(u)=>(f)=>{return u?R6(f.nodeLookup,{x:0,y:0,width:f.width,height:f.height},f.transform,!0).map((l)=>l.id):Array.from(f.nodeLookup.keys())};function hD(u){return eu(yu.useCallback(xD(u),[u]),zf)}var bD=(u)=>u.updateNodeInternals;function vD(){let u=eu(bD),[f]=yu.useState(()=>{if(typeof ResizeObserver>"u")return null;return new ResizeObserver((l)=>{let r=new Map;l.forEach((n)=>{let i=n.target.getAttribute("data-id");r.set(i,{id:i,nodeElement:n.target,force:!0})}),u(r)})});return yu.useEffect(()=>{return()=>{f?.disconnect()}},[f]),f}function kD({node:u,nodeType:f,hasDimensions:l,resizeObserver:r}){let n=Zf(),i=yu.useRef(null),y=yu.useRef(null),_=yu.useRef(u.sourcePosition),$=yu.useRef(u.targetPosition),A=yu.useRef(f),c=l&&!!u.internals.handleBounds;return yu.useEffect(()=>{if(i.current&&!u.hidden&&(!c||y.current!==i.current)){if(y.current)r?.unobserve(y.current);r?.observe(i.current),y.current=i.current}},[c,u.hidden]),yu.useEffect(()=>{return()=>{if(y.current)r?.unobserve(y.current),y.current=null}},[]),yu.useEffect(()=>{if(i.current){let j=A.current!==f,F=_.current!==u.sourcePosition,U=$.current!==u.targetPosition;if(j||F||U)A.current=f,_.current=u.sourcePosition,$.current=u.targetPosition,n.getState().updateNodeInternals(new Map([[u.id,{id:u.id,nodeElement:i.current,force:!0}]]))}},[u.id,f,u.sourcePosition,u.targetPosition]),i}function ID({id:u,onClick:f,onMouseEnter:l,onMouseMove:r,onMouseLeave:n,onContextMenu:i,onDoubleClick:y,nodesDraggable:_,elementsSelectable:$,nodesConnectable:A,nodesFocusable:c,resizeObserver:j,noDragClassName:F,noPanClassName:U,disableKeyboardA11y:Q,rfId:L,nodeTypes:w,nodeClickDistance:J,onError:N}){let{node:q,internals:W,isParent:z}=eu((tu)=>{let ju=tu.nodeLookup.get(u),Gu=tu.parentLookup.has(u);return{node:ju,internals:ju.internals,isParent:Gu}},zf),Z=q.type||"default",H=w?.[Z]||dN[Z];if(H===void 0)N?.("003",Fr.error003(Z)),Z="default",H=w?.default||dN.default;let E=!!(q.draggable||_&&typeof q.draggable>"u"),D=!!(q.selectable||$&&typeof q.selectable>"u"),h=!!(q.connectable||A&&typeof q.connectable>"u"),V=!!(q.focusable||c&&typeof q.focusable>"u"),Y=Zf(),p=kc(q),O=kD({node:q,nodeType:Z,hasDimensions:p,resizeObserver:j}),m=QW({nodeRef:O,disabled:q.hidden||!E,noDragClassName:F,handleSelector:q.dragHandle,nodeId:u,isSelectable:D,nodeClickDistance:J}),X=qW();if(q.hidden)return null;let v=t0(q),T=mD(q),S=D||E||f||l||r||n,k=l?(tu)=>l(tu,{...W.userNode}):void 0,I=r?(tu)=>r(tu,{...W.userNode}):void 0,b=n?(tu)=>n(tu,{...W.userNode}):void 0,o=i?(tu)=>i(tu,{...W.userNode}):void 0,s=y?(tu)=>y(tu,{...W.userNode}):void 0,x=(tu)=>{let{selectNodesOnDrag:ju,nodeDragThreshold:Gu}=Y.getState();if(D&&(!ju||!E||Gu>0))A9({id:u,store:Y,nodeRef:O});if(f)f(tu,{...W.userNode})},fu=(tu)=>{if(ac(tu.nativeEvent)||Q)return;if(Sc.includes(tu.key)&&D){let ju=tu.key==="Escape";A9({id:u,store:Y,unselect:ju,nodeRef:O})}else if(E&&q.selected&&Object.prototype.hasOwnProperty.call(l8,tu.key)){tu.preventDefault();let{ariaLabelConfig:ju}=Y.getState();Y.setState({ariaLiveMessage:ju["node.a11yDescription.ariaLiveMessage"]({direction:tu.key.replace("Arrow","").toLowerCase(),x:~~W.positionAbsolute.x,y:~~W.positionAbsolute.y})}),X({direction:l8[tu.key],factor:tu.shiftKey?4:1})}},$u=()=>{if(Q||!O.current?.matches(":focus-visible"))return;let{transform:tu,width:ju,height:Gu,autoPanOnNodeFocus:qu,setCenter:P}=Y.getState();if(!qu)return;if(!(R6(new Map([[u,q]]),{x:0,y:0,width:ju,height:Gu},tu,!0).length>0))P(q.position.x+v.width/2,q.position.y+v.height/2,{zoom:tu[2]})};return ru.jsx("div",{className:Yf(["react-flow__node",`react-flow__node-${Z}`,{[U]:E},q.className,{selected:q.selected,selectable:D,parent:z,draggable:E,dragging:m}]),ref:O,style:{zIndex:W.z,transform:`translate(${W.positionAbsolute.x}px,${W.positionAbsolute.y}px)`,pointerEvents:S?"all":"none",visibility:p?"visible":"hidden",...q.style,...T},"data-id":u,"data-testid":`rf__node-${u}`,onMouseEnter:k,onMouseMove:I,onMouseLeave:b,onContextMenu:o,onClick:x,onDoubleClick:s,onKeyDown:V?fu:void 0,tabIndex:V?0:void 0,onFocus:V?$u:void 0,role:q.ariaRole??(V?"group":void 0),"aria-roledescription":"node","aria-describedby":Q?void 0:`${AW}-${L}`,"aria-label":q.ariaLabel,...q.domAttributes,children:ru.jsx(HD,{value:u,children:ru.jsx(H,{id:u,data:q.data,type:Z,positionAbsoluteX:W.positionAbsolute.x,positionAbsoluteY:W.positionAbsolute.y,selected:q.selected??!1,selectable:D,draggable:E,deletable:q.deletable??!0,isConnectable:h,sourcePosition:q.sourcePosition,targetPosition:q.targetPosition,dragging:m,dragHandle:q.dragHandle,zIndex:W.z,parentId:q.parentId,...v})})})}var gD=yu.memo(ID),sD=(u)=>({nodesDraggable:u.nodesDraggable,nodesConnectable:u.nodesConnectable,nodesFocusable:u.nodesFocusable,elementsSelectable:u.elementsSelectable,onError:u.onError});function LW(u){let{nodesDraggable:f,nodesConnectable:l,nodesFocusable:r,elementsSelectable:n,onError:i}=eu(sD,zf),y=hD(u.onlyRenderVisibleElements),_=vD();return ru.jsx("div",{className:"react-flow__nodes",style:i8,children:y.map(($)=>{return ru.jsx(gD,{id:$,nodeTypes:u.nodeTypes,nodeExtent:u.nodeExtent,onClick:u.onNodeClick,onMouseEnter:u.onNodeMouseEnter,onMouseMove:u.onNodeMouseMove,onMouseLeave:u.onNodeMouseLeave,onContextMenu:u.onNodeContextMenu,onDoubleClick:u.onNodeDoubleClick,noDragClassName:u.noDragClassName,noPanClassName:u.noPanClassName,rfId:u.rfId,disableKeyboardA11y:u.disableKeyboardA11y,resizeObserver:_,nodesDraggable:f,nodesConnectable:l,nodesFocusable:r,elementsSelectable:n,nodeClickDistance:u.nodeClickDistance,onError:i},$)})})}LW.displayName="NodeRenderer";var aD=yu.memo(LW);function oD(u){return eu(yu.useCallback((l)=>{if(!u)return l.edges.map((n)=>n.id);let r=[];if(l.width&&l.height)for(let n of l.edges){let i=l.nodeLookup.get(n.source),y=l.nodeLookup.get(n.target);if(i&&y&&yN({sourceNode:i,targetNode:y,width:l.width,height:l.height,transform:l.transform}))r.push(n.id)}return r},[u]),zf)}var dD=({color:u="none",strokeWidth:f=1})=>{let l={strokeWidth:f,...u&&{stroke:u}};return ru.jsx("polyline",{className:"arrow",style:l,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},eD=({color:u="none",strokeWidth:f=1})=>{let l={strokeWidth:f,...u&&{stroke:u,fill:u}};return ru.jsx("polyline",{className:"arrowclosed",style:l,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},uW={[Dn.Arrow]:dD,[Dn.ArrowClosed]:eD};function uX(u){let f=Zf();return yu.useMemo(()=>{if(!Object.prototype.hasOwnProperty.call(uW,u))return f.getState().onError?.("009",Fr.error009(u)),null;return uW[u]},[u])}var fX=({id:u,type:f,color:l,width:r=12.5,height:n=12.5,markerUnits:i="strokeWidth",strokeWidth:y,orient:_="auto-start-reverse"})=>{let $=uX(f);if(!$)return null;return ru.jsx("marker",{className:"react-flow__arrowhead",id:u,markerWidth:`${r}`,markerHeight:`${n}`,viewBox:"-10 -10 20 20",markerUnits:i,orient:_,refX:"0",refY:"0",children:ru.jsx($,{color:l,strokeWidth:y})})},wW=({defaultColor:u,rfId:f})=>{let l=eu((i)=>i.edges),r=eu((i)=>i.defaultEdgeOptions),n=yu.useMemo(()=>{return $N(l,{id:f,defaultColor:u,defaultMarkerStart:r?.markerStart,defaultMarkerEnd:r?.markerEnd})},[l,r,f,u]);if(!n.length)return null;return ru.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:ru.jsx("defs",{children:n.map((i)=>ru.jsx(fX,{id:i.id,type:i.type,color:i.color,width:i.width,height:i.height,markerUnits:i.markerUnits,strokeWidth:i.strokeWidth,orient:i.orient},i.id))})})};wW.displayName="MarkerDefinitions";var lX=yu.memo(wW);function KW({x:u,y:f,label:l,labelStyle:r,labelShowBg:n=!0,labelBgStyle:i,labelBgPadding:y=[2,4],labelBgBorderRadius:_=2,children:$,className:A,...c}){let[j,F]=yu.useState({x:1,y:0,width:0,height:0}),U=Yf(["react-flow__edge-textwrapper",A]),Q=yu.useRef(null);if(yu.useEffect(()=>{if(Q.current){let L=Q.current.getBBox();F({x:L.x,y:L.y,width:L.width,height:L.height})}},[l]),!l)return null;return ru.jsxs("g",{transform:`translate(${u-j.width/2} ${f-j.height/2})`,className:U,visibility:j.width?"visible":"hidden",...c,children:[n&&ru.jsx("rect",{width:j.width+2*y[0],x:-y[0],y:-y[1],height:j.height+2*y[1],className:"react-flow__edge-textbg",style:i,rx:_,ry:_}),ru.jsx("text",{className:"react-flow__edge-text",y:j.height/2,dy:"0.3em",ref:Q,style:r,children:l}),$]})}KW.displayName="EdgeText";var rX=yu.memo(KW);function Ay({path:u,labelX:f,labelY:l,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:_,labelBgBorderRadius:$,interactionWidth:A=20,...c}){return ru.jsxs(ru.Fragment,{children:[ru.jsx("path",{...c,d:u,fill:"none",className:Yf(["react-flow__edge-path",c.className])}),A?ru.jsx("path",{d:u,fill:"none",strokeOpacity:0,strokeWidth:A,className:"react-flow__edge-interaction"}):null,r&&Er(f)&&Er(l)?ru.jsx(rX,{x:f,y:l,label:r,labelStyle:n,labelShowBg:i,labelBgStyle:y,labelBgPadding:_,labelBgBorderRadius:$}):null]})}function fW({pos:u,x1:f,y1:l,x2:r,y2:n}){if(u===wu.Left||u===wu.Right)return[0.5*(f+r),l];return[f,0.5*(l+n)]}function GW({sourceX:u,sourceY:f,sourcePosition:l=wu.Bottom,targetX:r,targetY:n,targetPosition:i=wu.Top}){let[y,_]=fW({pos:l,x1:u,y1:f,x2:r,y2:n}),[$,A]=fW({pos:i,x1:r,y1:n,x2:u,y2:f}),[c,j,F,U]=v6({sourceX:u,sourceY:f,targetX:r,targetY:n,sourceControlX:y,sourceControlY:_,targetControlX:$,targetControlY:A});return[`M${u},${f} C${y},${_} ${$},${A} ${r},${n}`,c,j,F,U]}function zW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,sourcePosition:y,targetPosition:_,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,interactionWidth:J})=>{let[N,q,W]=GW({sourceX:l,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:_}),z=u.isInternal?void 0:f;return ru.jsx(Ay,{id:z,path:N,labelX:q,labelY:W,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,interactionWidth:J})})}var nX=zW({isInternal:!1}),TW=zW({isInternal:!0});nX.displayName="SimpleBezierEdge";TW.displayName="SimpleBezierEdgeInternal";function EW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,sourcePosition:U=wu.Bottom,targetPosition:Q=wu.Top,markerEnd:L,markerStart:w,pathOptions:J,interactionWidth:N})=>{let[q,W,z]=G$({sourceX:l,sourceY:r,sourcePosition:U,targetX:n,targetY:i,targetPosition:Q,borderRadius:J?.borderRadius,offset:J?.offset,stepPosition:J?.stepPosition}),Z=u.isInternal?void 0:f;return ru.jsx(Ay,{id:Z,path:q,labelX:W,labelY:z,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,markerEnd:L,markerStart:w,interactionWidth:N})})}var ZW=EW({isInternal:!1}),OW=EW({isInternal:!0});ZW.displayName="SmoothStepEdge";OW.displayName="SmoothStepEdgeInternal";function HW(u){return yu.memo(({id:f,...l})=>{let r=u.isInternal?void 0:f;return ru.jsx(ZW,{...l,id:r,pathOptions:yu.useMemo(()=>({borderRadius:0,offset:l.pathOptions?.offset}),[l.pathOptions?.offset])})})}var iX=HW({isInternal:!1}),BW=HW({isInternal:!0});iX.displayName="StepEdge";BW.displayName="StepEdgeInternal";function VW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,markerEnd:U,markerStart:Q,interactionWidth:L})=>{let[w,J,N]=I6({sourceX:l,sourceY:r,targetX:n,targetY:i}),q=u.isInternal?void 0:f;return ru.jsx(Ay,{id:q,path:w,labelX:J,labelY:N,label:y,labelStyle:_,labelShowBg:$,labelBgStyle:A,labelBgPadding:c,labelBgBorderRadius:j,style:F,markerEnd:U,markerStart:Q,interactionWidth:L})})}var yX=VW({isInternal:!1}),DW=VW({isInternal:!0});yX.displayName="StraightEdge";DW.displayName="StraightEdgeInternal";function XW(u){return yu.memo(({id:f,sourceX:l,sourceY:r,targetX:n,targetY:i,sourcePosition:y=wu.Bottom,targetPosition:_=wu.Top,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,pathOptions:J,interactionWidth:N})=>{let[q,W,z]=k6({sourceX:l,sourceY:r,sourcePosition:y,targetX:n,targetY:i,targetPosition:_,curvature:J?.curvature}),Z=u.isInternal?void 0:f;return ru.jsx(Ay,{id:Z,path:q,labelX:W,labelY:z,label:$,labelStyle:A,labelShowBg:c,labelBgStyle:j,labelBgPadding:F,labelBgBorderRadius:U,style:Q,markerEnd:L,markerStart:w,interactionWidth:N})})}var _X=XW({isInternal:!1}),YW=XW({isInternal:!0});_X.displayName="BezierEdge";YW.displayName="BezierEdgeInternal";var lW={default:YW,straight:DW,step:BW,smoothstep:OW,simplebezier:TW},rW={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null},$X=(u,f,l)=>{if(l===wu.Left)return u-f;if(l===wu.Right)return u+f;return u},tX=(u,f,l)=>{if(l===wu.Top)return u-f;if(l===wu.Bottom)return u+f;return u},nW="react-flow__edgeupdater";function iW({position:u,centerX:f,centerY:l,radius:r=10,onMouseDown:n,onMouseEnter:i,onMouseOut:y,type:_}){return ru.jsx("circle",{onMouseDown:n,onMouseEnter:i,onMouseOut:y,className:Yf([nW,`${nW}-${_}`]),cx:$X(f,r,u),cy:tX(l,r,u),r,stroke:"transparent",fill:"transparent"})}function AX({isReconnectable:u,reconnectRadius:f,edge:l,sourceX:r,sourceY:n,targetX:i,targetY:y,sourcePosition:_,targetPosition:$,onReconnect:A,onReconnectStart:c,onReconnectEnd:j,setReconnecting:F,setUpdateHover:U}){let Q=Zf(),L=(W,z)=>{if(W.button!==0)return;let{autoPanOnConnect:Z,domNode:H,connectionMode:E,connectionRadius:D,lib:h,onConnectStart:V,cancelConnection:Y,nodeLookup:p,rfId:O,panBy:m,updateConnection:X}=Q.getState(),v=z.type==="target",T=(I,b)=>{F(!1),j?.(I,l,z.type,b)},S=(I)=>A?.(l,I),k=(I,b)=>{F(!0),c?.(W,l,z.type),V?.(I,b)};o6.onPointerDown(W.nativeEvent,{autoPanOnConnect:Z,connectionMode:E,connectionRadius:D,domNode:H,handleId:z.id,nodeId:z.nodeId,nodeLookup:p,isTarget:v,edgeUpdaterType:z.type,lib:h,flowId:O,cancelConnection:Y,panBy:m,isValidConnection:(...I)=>Q.getState().isValidConnection?.(...I)??!0,onConnect:S,onConnectStart:k,onConnectEnd:(...I)=>Q.getState().onConnectEnd?.(...I),onReconnectEnd:T,updateConnection:X,getTransform:()=>Q.getState().transform,getFromHandle:()=>Q.getState().connection.fromHandle,dragThreshold:Q.getState().connectionDragThreshold,handleDomNode:W.currentTarget})},w=(W)=>L(W,{nodeId:l.target,id:l.targetHandle??null,type:"target"}),J=(W)=>L(W,{nodeId:l.source,id:l.sourceHandle??null,type:"source"}),N=()=>U(!0),q=()=>U(!1);return ru.jsxs(ru.Fragment,{children:[(u===!0||u==="source")&&ru.jsx(iW,{position:_,centerX:r,centerY:n,radius:f,onMouseDown:w,onMouseEnter:N,onMouseOut:q,type:"source"}),(u===!0||u==="target")&&ru.jsx(iW,{position:$,centerX:i,centerY:y,radius:f,onMouseDown:J,onMouseEnter:N,onMouseOut:q,type:"target"})]})}function cX({id:u,edgesFocusable:f,edgesReconnectable:l,elementsSelectable:r,onClick:n,onDoubleClick:i,onContextMenu:y,onMouseEnter:_,onMouseMove:$,onMouseLeave:A,reconnectRadius:c,onReconnect:j,onReconnectStart:F,onReconnectEnd:U,rfId:Q,edgeTypes:L,noPanClassName:w,onError:J,disableKeyboardA11y:N}){let q=eu((P)=>P.edgeLookup.get(u)),W=eu((P)=>P.defaultEdgeOptions);q=W?{...W,...q}:q;let z=q.type||"default",Z=L?.[z]||lW[z];if(Z===void 0)J?.("011",Fr.error011(z)),z="default",Z=L?.default||lW.default;let H=!!(q.focusable||f&&typeof q.focusable>"u"),E=typeof j<"u"&&(q.reconnectable||l&&typeof q.reconnectable>"u"),D=!!(q.selectable||r&&typeof q.selectable>"u"),h=yu.useRef(null),[V,Y]=yu.useState(!1),[p,O]=yu.useState(!1),m=Zf(),{zIndex:X,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b}=eu(yu.useCallback((P)=>{let e=P.nodeLookup.get(q.source),uu=P.nodeLookup.get(q.target);if(!e||!uu)return{zIndex:q.zIndex,...rW};let Wu=_N({id:u,sourceNode:e,targetNode:uu,sourceHandle:q.sourceHandle||null,targetHandle:q.targetHandle||null,connectionMode:P.connectionMode,onError:J});return{zIndex:iN({selected:q.selected,zIndex:q.zIndex,sourceNode:e,targetNode:uu,elevateOnSelect:P.elevateEdgesOnSelect,zIndexMode:P.zIndexMode}),...Wu||rW}},[q.source,q.target,q.sourceHandle,q.targetHandle,q.selected,q.zIndex]),zf),o=yu.useMemo(()=>q.markerStart?`url('#${g6(q.markerStart,Q)}')`:void 0,[q.markerStart,Q]),s=yu.useMemo(()=>q.markerEnd?`url('#${g6(q.markerEnd,Q)}')`:void 0,[q.markerEnd,Q]);if(q.hidden||v===null||T===null||S===null||k===null)return null;let x=(P)=>{let{addSelectedEdges:e,unselectNodesAndEdges:uu,multiSelectionActive:Wu}=m.getState();if(D)if(m.setState({nodesSelectionActive:!1}),q.selected&&Wu)uu({nodes:[],edges:[q]}),h.current?.blur();else e([u]);if(n)n(P,q)},fu=i?(P)=>{i(P,{...q})}:void 0,$u=y?(P)=>{y(P,{...q})}:void 0,tu=_?(P)=>{_(P,{...q})}:void 0,ju=$?(P)=>{$(P,{...q})}:void 0,Gu=A?(P)=>{A(P,{...q})}:void 0,qu=(P)=>{if(!N&&Sc.includes(P.key)&&D){let{unselectNodesAndEdges:e,addSelectedEdges:uu}=m.getState();if(P.key==="Escape")h.current?.blur(),e({edges:[q]});else uu([u])}};return ru.jsx("svg",{style:{zIndex:X},children:ru.jsxs("g",{className:Yf(["react-flow__edge",`react-flow__edge-${z}`,q.className,w,{selected:q.selected,animated:q.animated,inactive:!D&&!n,updating:V,selectable:D}]),onClick:x,onDoubleClick:fu,onContextMenu:$u,onMouseEnter:tu,onMouseMove:ju,onMouseLeave:Gu,onKeyDown:H?qu:void 0,tabIndex:H?0:void 0,role:q.ariaRole??(H?"group":"img"),"aria-roledescription":"edge","data-id":u,"data-testid":`rf__edge-${u}`,"aria-label":q.ariaLabel===null?void 0:q.ariaLabel||`Edge from ${q.source} to ${q.target}`,"aria-describedby":H?`${cW}-${Q}`:void 0,ref:h,...q.domAttributes,children:[!p&&ru.jsx(Z,{id:u,source:q.source,target:q.target,type:q.type,selected:q.selected,animated:q.animated,selectable:D,deletable:q.deletable??!0,label:q.label,labelStyle:q.labelStyle,labelShowBg:q.labelShowBg,labelBgStyle:q.labelBgStyle,labelBgPadding:q.labelBgPadding,labelBgBorderRadius:q.labelBgBorderRadius,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b,data:q.data,style:q.style,sourceHandleId:q.sourceHandle,targetHandleId:q.targetHandle,markerStart:o,markerEnd:s,pathOptions:"pathOptions"in q?q.pathOptions:void 0,interactionWidth:q.interactionWidth}),E&&ru.jsx(AX,{edge:q,isReconnectable:E,reconnectRadius:c,onReconnect:j,onReconnectStart:F,onReconnectEnd:U,sourceX:v,sourceY:T,targetX:S,targetY:k,sourcePosition:I,targetPosition:b,setUpdateHover:Y,setReconnecting:O})]})})}var jX=yu.memo(cX),FX=(u)=>({edgesFocusable:u.edgesFocusable,edgesReconnectable:u.edgesReconnectable,elementsSelectable:u.elementsSelectable,connectionMode:u.connectionMode,onError:u.onError});function SW({defaultMarkerColor:u,onlyRenderVisibleElements:f,rfId:l,edgeTypes:r,noPanClassName:n,onReconnect:i,onEdgeContextMenu:y,onEdgeMouseEnter:_,onEdgeMouseMove:$,onEdgeMouseLeave:A,onEdgeClick:c,reconnectRadius:j,onEdgeDoubleClick:F,onReconnectStart:U,onReconnectEnd:Q,disableKeyboardA11y:L}){let{edgesFocusable:w,edgesReconnectable:J,elementsSelectable:N,onError:q}=eu(FX,zf),W=oD(f);return ru.jsxs("div",{className:"react-flow__edges",children:[ru.jsx(lX,{defaultColor:u,rfId:l}),W.map((z)=>{return ru.jsx(jX,{id:z,edgesFocusable:w,edgesReconnectable:J,elementsSelectable:N,noPanClassName:n,onReconnect:i,onContextMenu:y,onMouseEnter:_,onMouseMove:$,onMouseLeave:A,onClick:c,reconnectRadius:j,onDoubleClick:F,onReconnectStart:U,onReconnectEnd:Q,rfId:l,onError:q,edgeTypes:r,disableKeyboardA11y:L},z)})]})}SW.displayName="EdgeRenderer";var JX=yu.memo(SW),UX=(u)=>`translate(${u.transform[0]}px,${u.transform[1]}px) scale(${u.transform[2]})`;function QX({children:u}){let f=eu(UX);return ru.jsx("div",{className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:f},children:u})}function qX(u){let f=c9(),l=yu.useRef(!1);yu.useEffect(()=>{if(!l.current&&f.viewportInitialized&&u)setTimeout(()=>u(f),1),l.current=!0},[u,f.viewportInitialized])}var NX=(u)=>u.panZoom?.syncViewport;function WX(u){let f=eu(NX),l=Zf();return yu.useEffect(()=>{if(u)f?.(u),l.setState({transform:[u.x,u.y,u.zoom]})},[u,f]),null}function yW(u){return u.connection.inProgress?{...u.connection,to:yy(u.connection.to,u.transform)}:{...u.connection}}function LX(u){if(u)return(l)=>{let r=yW(l);return u(r)};return yW}function wX(u){let f=LX(u);return eu(f,zf)}var KX=(u)=>({nodesConnectable:u.nodesConnectable,isValid:u.connection.isValid,inProgress:u.connection.inProgress,width:u.width,height:u.height});function GX({containerStyle:u,style:f,type:l,component:r}){let{nodesConnectable:n,width:i,height:y,isValid:_,inProgress:$}=eu(KX,zf);if(!(i&&n&&$))return null;return ru.jsx("svg",{style:u,width:i,height:y,className:"react-flow__connectionline react-flow__container",children:ru.jsx("g",{className:Yf(["react-flow__connection",Pc(_)]),children:ru.jsx(pW,{style:f,type:l,CustomComponent:r,isValid:_})})})}var pW=({style:u,type:f=$0.Bezier,CustomComponent:l,isValid:r})=>{let{inProgress:n,from:i,fromNode:y,fromHandle:_,fromPosition:$,to:A,toNode:c,toHandle:j,toPosition:F,pointer:U}=wX();if(!n)return;if(l)return ru.jsx(l,{connectionLineType:f,connectionLineStyle:u,fromNode:y,fromHandle:_,fromX:i.x,fromY:i.y,toX:A.x,toY:A.y,fromPosition:$,toPosition:F,connectionStatus:Pc(r),toNode:c,toHandle:j,pointer:U});let Q="",L={sourceX:i.x,sourceY:i.y,sourcePosition:$,targetX:A.x,targetY:A.y,targetPosition:F};switch(f){case $0.Bezier:[Q]=k6(L);break;case $0.SimpleBezier:[Q]=GW(L);break;case $0.Step:[Q]=G$({...L,borderRadius:0});break;case $0.SmoothStep:[Q]=G$(L);break;default:[Q]=I6(L)}return ru.jsx("path",{d:Q,fill:"none",className:"react-flow__connection-path",style:u})};pW.displayName="ConnectionLine";var zX={};function _W(u=zX){let f=yu.useRef(u),l=Zf();yu.useEffect(()=>{},[u])}function TX(){let u=Zf(),f=yu.useRef(!1);yu.useEffect(()=>{},[])}function mW({nodeTypes:u,edgeTypes:f,onInit:l,onNodeClick:r,onEdgeClick:n,onNodeDoubleClick:i,onEdgeDoubleClick:y,onNodeMouseEnter:_,onNodeMouseMove:$,onNodeMouseLeave:A,onNodeContextMenu:c,onSelectionContextMenu:j,onSelectionStart:F,onSelectionEnd:U,connectionLineType:Q,connectionLineStyle:L,connectionLineComponent:w,connectionLineContainerStyle:J,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,deleteKeyCode:E,onlyRenderVisibleElements:D,elementsSelectable:h,defaultViewport:V,translateExtent:Y,minZoom:p,maxZoom:O,preventScrolling:m,defaultMarkerColor:X,zoomOnScroll:v,zoomOnPinch:T,panOnScroll:S,panOnScrollSpeed:k,panOnScrollMode:I,zoomOnDoubleClick:b,panOnDrag:o,onPaneClick:s,onPaneMouseEnter:x,onPaneMouseMove:fu,onPaneMouseLeave:$u,onPaneScroll:tu,onPaneContextMenu:ju,paneClickDistance:Gu,nodeClickDistance:qu,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:Wu,reconnectRadius:g,onReconnect:Qu,onReconnectStart:Tu,onReconnectEnd:Zu,noDragClassName:Xu,noWheelClassName:uf,noPanClassName:_f,disableKeyboardA11y:Jf,nodeExtent:Pf,rfId:Sl,viewport:vf,onViewportChange:ll}){return _W(u),_W(f),TX(),qX(l),WX(vf),ru.jsx(RD,{onPaneClick:s,onPaneMouseEnter:x,onPaneMouseMove:fu,onPaneMouseLeave:$u,onPaneContextMenu:ju,onPaneScroll:tu,paneClickDistance:Gu,deleteKeyCode:E,selectionKeyCode:N,selectionOnDrag:q,selectionMode:W,onSelectionStart:F,onSelectionEnd:U,multiSelectionKeyCode:z,panActivationKeyCode:Z,zoomActivationKeyCode:H,elementsSelectable:h,zoomOnScroll:v,zoomOnPinch:T,zoomOnDoubleClick:b,panOnScroll:S,panOnScrollSpeed:k,panOnScrollMode:I,panOnDrag:o,defaultViewport:V,translateExtent:Y,minZoom:p,maxZoom:O,onSelectionContextMenu:j,preventScrolling:m,noDragClassName:Xu,noWheelClassName:uf,noPanClassName:_f,disableKeyboardA11y:Jf,onViewportChange:ll,isControlledViewport:!!vf,children:ru.jsxs(QX,{children:[ru.jsx(JX,{edgeTypes:f,onEdgeClick:n,onEdgeDoubleClick:y,onReconnect:Qu,onReconnectStart:Tu,onReconnectEnd:Zu,onlyRenderVisibleElements:D,onEdgeContextMenu:P,onEdgeMouseEnter:e,onEdgeMouseMove:uu,onEdgeMouseLeave:Wu,reconnectRadius:g,defaultMarkerColor:X,noPanClassName:_f,disableKeyboardA11y:Jf,rfId:Sl}),ru.jsx(GX,{style:L,type:Q,component:w,containerStyle:J}),ru.jsx("div",{className:"react-flow__edgelabel-renderer"}),ru.jsx(aD,{nodeTypes:u,onNodeClick:r,onNodeDoubleClick:i,onNodeMouseEnter:_,onNodeMouseMove:$,onNodeMouseLeave:A,onNodeContextMenu:c,nodeClickDistance:qu,onlyRenderVisibleElements:D,noPanClassName:_f,noDragClassName:Xu,disableKeyboardA11y:Jf,nodeExtent:Pf,rfId:Sl}),ru.jsx("div",{className:"react-flow__viewport-portal"})]})})}mW.displayName="GraphView";var EX=yu.memo(mW),$W=({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$=0.5,maxZoom:A=2,nodeOrigin:c,nodeExtent:j,zIndexMode:F="basic"}={})=>{let U=new Map,Q=new Map,L=new Map,w=new Map,J=r??f??[],N=l??u??[],q=c??[0,0],W=j??ly;n9(L,w,J);let{nodesInitialized:z}=s6(N,U,Q,{nodeOrigin:q,nodeExtent:W,zIndexMode:F}),Z=[0,0,1];if(y&&n&&i){let H=ry(U,{filter:(V)=>!!((V.width||V.initialWidth)&&(V.height||V.initialHeight))}),{x:E,y:D,zoom:h}=K$(H,n,i,$,A,_?.padding??0.1);Z=[E,D,h]}return{rfId:"1",width:n??0,height:i??0,transform:Z,nodes:N,nodesInitialized:z,nodeLookup:U,parentLookup:Q,edges:J,edgeLookup:w,connectionLookup:L,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:l!==void 0,hasDefaultEdges:r!==void 0,panZoom:null,minZoom:$,maxZoom:A,translateExtent:ly,nodeExtent:W,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:Vn.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:q,nodeDragThreshold:1,connectionDragThreshold:1,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesReconnectable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,elevateEdgesOnSelect:!0,selectNodesOnDrag:!0,multiSelectionActive:!1,fitViewQueued:y??!1,fitViewOptions:_,fitViewResolver:null,connection:{...mc},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:vc,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:pc,zIndexMode:F,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},ZX=({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$,maxZoom:A,nodeOrigin:c,nodeExtent:j,zIndexMode:F})=>MN((U,Q)=>{async function L(){let{nodeLookup:w,panZoom:J,fitViewOptions:N,fitViewResolver:q,width:W,height:z,minZoom:Z,maxZoom:H}=Q();if(!J)return;await eq({nodes:w,width:W,height:z,panZoom:J,minZoom:Z,maxZoom:H},N),q?.resolve(!0),U({fitViewResolver:null})}return{...$W({nodes:u,edges:f,width:n,height:i,fitView:y,fitViewOptions:_,minZoom:$,maxZoom:A,nodeOrigin:c,nodeExtent:j,defaultNodes:l,defaultEdges:r,zIndexMode:F}),setNodes:(w)=>{let{nodeLookup:J,parentLookup:N,nodeOrigin:q,elevateNodesOnSelect:W,fitViewQueued:z,zIndexMode:Z,nodesSelectionActive:H}=Q(),{nodesInitialized:E,hasSelectedNodes:D}=s6(w,J,N,{nodeOrigin:q,nodeExtent:j,elevateNodesOnSelect:W,checkEquality:!0,zIndexMode:Z}),h=H&&D;if(z&&E)L(),U({nodes:w,nodesInitialized:E,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:h});else U({nodes:w,nodesInitialized:E,nodesSelectionActive:h})},setEdges:(w)=>{let{connectionLookup:J,edgeLookup:N}=Q();n9(J,N,w),U({edges:w})},setDefaultNodesAndEdges:(w,J)=>{if(w){let{setNodes:N}=Q();N(w),U({hasDefaultNodes:!0})}if(J){let{setEdges:N}=Q();N(J),U({hasDefaultEdges:!0})}},updateNodeInternals:(w)=>{let{triggerNodeChanges:J,nodeLookup:N,parentLookup:q,domNode:W,nodeOrigin:z,nodeExtent:Z,debug:H,fitViewQueued:E,zIndexMode:D}=Q(),{changes:h,updatedInternals:V}=jN(w,N,q,W,z,Z,D);if(!V)return;if(AN(N,q,{nodeOrigin:z,nodeExtent:Z,zIndexMode:D}),E)L(),U({fitViewQueued:!1,fitViewOptions:void 0});else U({});if(h?.length>0){if(H)console.log("React Flow: trigger node changes",h);J?.(h)}},updateNodePositions:(w,J=!1)=>{let N=[],q=[],{nodeLookup:W,triggerNodeChanges:z,connection:Z,updateConnection:H,onNodesChangeMiddlewareMap:E}=Q();for(let[D,h]of w){let V=W.get(D),Y=!!(V?.expandParent&&V?.parentId&&h?.position),p={id:D,type:"position",position:Y?{x:Math.max(0,h.position.x),y:Math.max(0,h.position.y)}:h.position,dragging:J};if(V&&Z.inProgress&&Z.fromNode.id===V.id){let O=Xn(V,Z.fromHandle,wu.Left,!0);H({...Z,from:O})}if(Y&&V.parentId)N.push({id:D,parentId:V.parentId,rect:{...h.internals.positionAbsolute,width:h.measured.width??0,height:h.measured.height??0}});q.push(p)}if(N.length>0){let{parentLookup:D,nodeOrigin:h}=Q(),V=a6(N,W,D,h);q.push(...V)}for(let D of E.values())q=D(q);z(q)},triggerNodeChanges:(w)=>{let{onNodesChange:J,setNodes:N,nodes:q,hasDefaultNodes:W,debug:z}=Q();if(w?.length){if(W){let Z=jD(w,q);N(Z)}if(z)console.log("React Flow: trigger node changes",w);J?.(w)}},triggerEdgeChanges:(w)=>{let{onEdgesChange:J,setEdges:N,edges:q,hasDefaultEdges:W,debug:z}=Q();if(w?.length){if(W){let Z=FD(w,q);N(Z)}if(z)console.log("React Flow: trigger edge changes",w);J?.(w)}},addSelectedNodes:(w)=>{let{multiSelectionActive:J,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(J){let Z=w.map((H)=>p1(H,!0));W(Z);return}W(ty(q,new Set([...w]),!0)),z(ty(N))},addSelectedEdges:(w)=>{let{multiSelectionActive:J,edgeLookup:N,nodeLookup:q,triggerNodeChanges:W,triggerEdgeChanges:z}=Q();if(J){let Z=w.map((H)=>p1(H,!0));z(Z);return}z(ty(N,new Set([...w]))),W(ty(q,new Set,!0))},unselectNodesAndEdges:({nodes:w,edges:J}={})=>{let{edges:N,nodes:q,nodeLookup:W,triggerNodeChanges:z,triggerEdgeChanges:Z}=Q(),H=w?w:q,E=J?J:N,D=[];for(let V of H){if(!V.selected)continue;let Y=W.get(V.id);if(Y)Y.selected=!1;D.push(p1(V.id,!1))}let h=[];for(let V of E){if(!V.selected)continue;h.push(p1(V.id,!1))}z(D),Z(h)},setMinZoom:(w)=>{let{panZoom:J,maxZoom:N}=Q();J?.setScaleExtent([w,N]),U({minZoom:w})},setMaxZoom:(w)=>{let{panZoom:J,minZoom:N}=Q();J?.setScaleExtent([N,w]),U({maxZoom:w})},setTranslateExtent:(w)=>{Q().panZoom?.setTranslateExtent(w),U({translateExtent:w})},resetSelectedElements:()=>{let{edges:w,nodes:J,triggerNodeChanges:N,triggerEdgeChanges:q,elementsSelectable:W}=Q();if(!W)return;let z=J.reduce((H,E)=>E.selected?[...H,p1(E.id,!1)]:H,[]),Z=w.reduce((H,E)=>E.selected?[...H,p1(E.id,!1)]:H,[]);N(z),q(Z)},setNodeExtent:(w)=>{let{nodes:J,nodeLookup:N,parentLookup:q,nodeOrigin:W,elevateNodesOnSelect:z,nodeExtent:Z,zIndexMode:H}=Q();if(w[0][0]===Z[0][0]&&w[0][1]===Z[0][1]&&w[1][0]===Z[1][0]&&w[1][1]===Z[1][1])return;s6(J,N,q,{nodeOrigin:W,nodeExtent:w,elevateNodesOnSelect:z,checkEquality:!1,zIndexMode:H}),U({nodeExtent:w})},panBy:(w)=>{let{transform:J,width:N,height:q,panZoom:W,translateExtent:z}=Q();return FN({delta:w,panZoom:W,transform:J,translateExtent:z,width:N,height:q})},setCenter:async(w,J,N)=>{let{width:q,height:W,maxZoom:z,panZoom:Z}=Q();if(!Z)return Promise.resolve(!1);let H=typeof N?.zoom<"u"?N.zoom:z;return await Z.setViewport({x:q/2-w*H,y:W/2-J*H,zoom:H},{duration:N?.duration,ease:N?.ease,interpolate:N?.interpolate}),Promise.resolve(!0)},cancelConnection:()=>{U({connection:{...mc}})},updateConnection:(w)=>{U({connection:w})},reset:()=>U({...$W()})}},Object.is);function OX({initialNodes:u,initialEdges:f,defaultNodes:l,defaultEdges:r,initialWidth:n,initialHeight:i,initialMinZoom:y,initialMaxZoom:_,initialFitViewOptions:$,fitView:A,nodeOrigin:c,nodeExtent:j,zIndexMode:F,children:U}){let[Q]=yu.useState(()=>ZX({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,width:n,height:i,fitView:A,minZoom:y,maxZoom:_,fitViewOptions:$,nodeOrigin:c,nodeExtent:j,zIndexMode:F}));return ru.jsx(kV,{value:Q,children:ru.jsx(QD,{children:U})})}function HX({children:u,nodes:f,edges:l,defaultNodes:r,defaultEdges:n,width:i,height:y,fitView:_,fitViewOptions:$,minZoom:A,maxZoom:c,nodeOrigin:j,nodeExtent:F,zIndexMode:U}){if(yu.useContext(r8))return ru.jsx(ru.Fragment,{children:u});return ru.jsx(OX,{initialNodes:f,initialEdges:l,defaultNodes:r,defaultEdges:n,initialWidth:i,initialHeight:y,fitView:_,initialFitViewOptions:$,initialMinZoom:A,initialMaxZoom:c,nodeOrigin:j,nodeExtent:F,zIndexMode:U,children:u})}var BX={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function VX({nodes:u,edges:f,defaultNodes:l,defaultEdges:r,className:n,nodeTypes:i,edgeTypes:y,onNodeClick:_,onEdgeClick:$,onInit:A,onMove:c,onMoveStart:j,onMoveEnd:F,onConnect:U,onConnectStart:Q,onConnectEnd:L,onClickConnectStart:w,onClickConnectEnd:J,onNodeMouseEnter:N,onNodeMouseMove:q,onNodeMouseLeave:W,onNodeContextMenu:z,onNodeDoubleClick:Z,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onNodesDelete:h,onEdgesDelete:V,onDelete:Y,onSelectionChange:p,onSelectionDragStart:O,onSelectionDrag:m,onSelectionDragStop:X,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:S,onBeforeDelete:k,connectionMode:I,connectionLineType:b=$0.Bezier,connectionLineStyle:o,connectionLineComponent:s,connectionLineContainerStyle:x,deleteKeyCode:fu="Backspace",selectionKeyCode:$u="Shift",selectionOnDrag:tu=!1,selectionMode:ju=X1.Full,panActivationKeyCode:Gu="Space",multiSelectionKeyCode:qu=_y()?"Meta":"Control",zoomActivationKeyCode:P=_y()?"Meta":"Control",snapToGrid:e,snapGrid:uu,onlyRenderVisibleElements:Wu=!1,selectNodesOnDrag:g,nodesDraggable:Qu,autoPanOnNodeFocus:Tu,nodesConnectable:Zu,nodesFocusable:Xu,nodeOrigin:uf=jW,edgesFocusable:_f,edgesReconnectable:Jf,elementsSelectable:Pf=!0,defaultViewport:Sl=iD,minZoom:vf=0.5,maxZoom:ll=2,translateExtent:dl=ly,preventScrolling:el=!0,nodeExtent:cu,defaultMarkerColor:ku="#b1b1b7",zoomOnScroll:Tl=!0,zoomOnPinch:pu=!0,panOnScroll:rl=!1,panOnScrollSpeed:El=0.5,panOnScrollMode:Jl=C0.Free,zoomOnDoubleClick:nl=!0,panOnDrag:pl=!0,onPaneClick:qr,onPaneMouseEnter:rf,onPaneMouseMove:C1,onPaneMouseLeave:kn,onPaneScroll:R1,onPaneContextMenu:lu,paneClickDistance:Ou=1,nodeClickDistance:Yu=0,children:Iu,onReconnect:Qf,onReconnectStart:il,onReconnectEnd:ff,onEdgeContextMenu:df,onEdgeDoubleClick:$f,onEdgeMouseEnter:C$,onEdgeMouseMove:V8,onEdgeMouseLeave:Tf,reconnectRadius:u7=10,onNodesChange:kf,onEdgesChange:ur,noDragClassName:Wy="nodrag",noWheelClassName:R$="nowheel",noPanClassName:x1="nopan",fitView:Ly,fitViewOptions:h1,connectOnClick:x$,attributionPosition:ml,proOptions:sr,defaultEdgeOptions:h$,elevateNodesOnSelect:b$=!0,elevateEdgesOnSelect:wy=!1,disableKeyboardA11y:Ky=!1,autoPanOnConnect:ar,autoPanOnNodeDrag:v$,autoPanSpeed:pf,connectionRadius:D8,isValidConnection:k$,onError:Dr,style:In,id:b0,nodeDragThreshold:b1,connectionDragThreshold:gn,viewport:Gy,onViewportChange:f7,width:v1,height:l7,colorMode:I$="light",debug:X8,onScroll:g$,ariaLabelConfig:Y8,zIndexMode:U0="basic",...k1},sn){let Ul=b0||"1",s$=tD(I$),zy=yu.useCallback((fr)=>{fr.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),g$?.(fr)},[g$]);return ru.jsx("div",{"data-testid":"rf__wrapper",...k1,onScroll:zy,style:{...In,...BX},ref:sn,className:Yf(["react-flow",n,s$]),id:b0,role:"application",children:ru.jsxs(HX,{nodes:u,edges:f,width:v1,height:l7,fitView:Ly,fitViewOptions:h1,minZoom:vf,maxZoom:ll,nodeOrigin:uf,nodeExtent:cu,zIndexMode:U0,children:[ru.jsx($D,{nodes:u,edges:f,defaultNodes:l,defaultEdges:r,onConnect:U,onConnectStart:Q,onConnectEnd:L,onClickConnectStart:w,onClickConnectEnd:J,nodesDraggable:Qu,autoPanOnNodeFocus:Tu,nodesConnectable:Zu,nodesFocusable:Xu,edgesFocusable:_f,edgesReconnectable:Jf,elementsSelectable:Pf,elevateNodesOnSelect:b$,elevateEdgesOnSelect:wy,minZoom:vf,maxZoom:ll,nodeExtent:cu,onNodesChange:kf,onEdgesChange:ur,snapToGrid:e,snapGrid:uu,connectionMode:I,translateExtent:dl,connectOnClick:x$,defaultEdgeOptions:h$,fitView:Ly,fitViewOptions:h1,onNodesDelete:h,onEdgesDelete:V,onDelete:Y,onNodeDragStart:H,onNodeDrag:E,onNodeDragStop:D,onSelectionDrag:m,onSelectionDragStart:O,onSelectionDragStop:X,onMove:c,onMoveStart:j,onMoveEnd:F,noPanClassName:x1,nodeOrigin:uf,rfId:Ul,autoPanOnConnect:ar,autoPanOnNodeDrag:v$,autoPanSpeed:pf,onError:Dr,connectionRadius:D8,isValidConnection:k$,selectNodesOnDrag:g,nodeDragThreshold:b1,connectionDragThreshold:gn,onBeforeDelete:k,debug:X8,ariaLabelConfig:Y8,zIndexMode:U0}),ru.jsx(EX,{onInit:A,onNodeClick:_,onEdgeClick:$,onNodeMouseEnter:N,onNodeMouseMove:q,onNodeMouseLeave:W,onNodeContextMenu:z,onNodeDoubleClick:Z,nodeTypes:i,edgeTypes:y,connectionLineType:b,connectionLineStyle:o,connectionLineComponent:s,connectionLineContainerStyle:x,selectionKeyCode:$u,selectionOnDrag:tu,selectionMode:ju,deleteKeyCode:fu,multiSelectionKeyCode:qu,panActivationKeyCode:Gu,zoomActivationKeyCode:P,onlyRenderVisibleElements:Wu,defaultViewport:Sl,translateExtent:dl,minZoom:vf,maxZoom:ll,preventScrolling:el,zoomOnScroll:Tl,zoomOnPinch:pu,zoomOnDoubleClick:nl,panOnScroll:rl,panOnScrollSpeed:El,panOnScrollMode:Jl,panOnDrag:pl,onPaneClick:qr,onPaneMouseEnter:rf,onPaneMouseMove:C1,onPaneMouseLeave:kn,onPaneScroll:R1,onPaneContextMenu:lu,paneClickDistance:Ou,nodeClickDistance:Yu,onSelectionContextMenu:v,onSelectionStart:T,onSelectionEnd:S,onReconnect:Qf,onReconnectStart:il,onReconnectEnd:ff,onEdgeContextMenu:df,onEdgeDoubleClick:$f,onEdgeMouseEnter:C$,onEdgeMouseMove:V8,onEdgeMouseLeave:Tf,reconnectRadius:u7,defaultMarkerColor:ku,noDragClassName:Wy,noWheelClassName:R$,noPanClassName:x1,rfId:Ul,disableKeyboardA11y:Ky,nodeExtent:cu,viewport:Gy,onViewportChange:f7}),ru.jsx(nD,{onSelectionChange:p}),Iu,ru.jsx(eV,{proOptions:sr,position:ml}),ru.jsx(dV,{rfId:Ul,disableKeyboardA11y:Ky})]})})}var PW=JW(VX);var cb=Fr.error014();function DX({dimensions:u,lineWidth:f,variant:l,className:r}){return ru.jsx("path",{strokeWidth:f,d:`M${u[0]/2} 0 V${u[1]} M0 ${u[1]/2} H${u[0]}`,className:Yf(["react-flow__background-pattern",l,r])})}function XX({radius:u,className:f}){return ru.jsx("circle",{cx:u,cy:u,r:u,className:Yf(["react-flow__background-pattern","dots",f])})}var Sn;(function(u){u.Lines="lines",u.Dots="dots",u.Cross="cross"})(Sn||(Sn={}));var YX={[Sn.Dots]:1,[Sn.Lines]:1,[Sn.Cross]:6},SX=(u)=>({transform:u.transform,patternId:`pattern-${u.rfId}`});function MW({id:u,variant:f=Sn.Dots,gap:l=20,size:r,lineWidth:n=1,offset:i=0,color:y,bgColor:_,style:$,className:A,patternClassName:c}){let j=yu.useRef(null),{transform:F,patternId:U}=eu(SX,zf),Q=r||YX[f],L=f===Sn.Dots,w=f===Sn.Cross,J=Array.isArray(l)?l:[l,l],N=[J[0]*F[2]||1,J[1]*F[2]||1],q=Q*F[2],W=Array.isArray(i)?i:[i,i],z=w?[q,q]:N,Z=[W[0]*F[2]||1+z[0]/2,W[1]*F[2]||1+z[1]/2],H=`${U}${u?u:""}`;return ru.jsxs("svg",{className:Yf(["react-flow__background",A]),style:{...$,...i8,"--xy-background-color-props":_,"--xy-background-pattern-color-props":y},ref:j,"data-testid":"rf__background",children:[ru.jsx("pattern",{id:H,x:F[0]%N[0],y:F[1]%N[1],width:N[0],height:N[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${Z[0]},-${Z[1]})`,children:L?ru.jsx(XX,{radius:q/2,className:c}):ru.jsx(DX,{dimensions:z,lineWidth:n,variant:f,className:c})}),ru.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${H})`})]})}MW.displayName="Background";var CW=yu.memo(MW);function pX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:ru.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function mX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:ru.jsx("path",{d:"M0 0h32v4.2H0z"})})}function PX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:ru.jsx("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"})})}function MX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:ru.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"})})}function CX(){return ru.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:ru.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"})})}function f8({children:u,className:f,...l}){return ru.jsx("button",{type:"button",className:Yf(["react-flow__controls-button",f]),...l,children:u})}var RX=(u)=>({isInteractive:u.nodesDraggable||u.nodesConnectable||u.elementsSelectable,minZoomReached:u.transform[2]<=u.minZoom,maxZoomReached:u.transform[2]>=u.maxZoom,ariaLabelConfig:u.ariaLabelConfig});function RW({style:u,showZoom:f=!0,showFitView:l=!0,showInteractive:r=!0,fitViewOptions:n,onZoomIn:i,onZoomOut:y,onFitView:_,onInteractiveChange:$,className:A,children:c,position:j="bottom-left",orientation:F="vertical","aria-label":U}){let Q=Zf(),{isInteractive:L,minZoomReached:w,maxZoomReached:J,ariaLabelConfig:N}=eu(RX,zf),{zoomIn:q,zoomOut:W,fitView:z}=c9(),Z=()=>{q(),i?.()},H=()=>{W(),y?.()},E=()=>{z(n),_?.()},D=()=>{Q.setState({nodesDraggable:!L,nodesConnectable:!L,elementsSelectable:!L}),$?.(!L)};return ru.jsxs(n8,{className:Yf(["react-flow__controls",F==="horizontal"?"horizontal":"vertical",A]),position:j,style:u,"data-testid":"rf__controls","aria-label":U??N["controls.ariaLabel"],children:[f&&ru.jsxs(ru.Fragment,{children:[ru.jsx(f8,{onClick:Z,className:"react-flow__controls-zoomin",title:N["controls.zoomIn.ariaLabel"],"aria-label":N["controls.zoomIn.ariaLabel"],disabled:J,children:ru.jsx(pX,{})}),ru.jsx(f8,{onClick:H,className:"react-flow__controls-zoomout",title:N["controls.zoomOut.ariaLabel"],"aria-label":N["controls.zoomOut.ariaLabel"],disabled:w,children:ru.jsx(mX,{})})]}),l&&ru.jsx(f8,{className:"react-flow__controls-fitview",onClick:E,title:N["controls.fitView.ariaLabel"],"aria-label":N["controls.fitView.ariaLabel"],children:ru.jsx(PX,{})}),r&&ru.jsx(f8,{className:"react-flow__controls-interactive",onClick:D,title:N["controls.interactive.ariaLabel"],"aria-label":N["controls.interactive.ariaLabel"],children:L?ru.jsx(CX,{}):ru.jsx(MX,{})}),c]})}RW.displayName="Controls";var xW=yu.memo(RW);function xX({id:u,x:f,y:l,width:r,height:n,style:i,color:y,strokeColor:_,strokeWidth:$,className:A,borderRadius:c,shapeRendering:j,selected:F,onClick:U}){let{background:Q,backgroundColor:L}=i||{},w=y||Q||L;return ru.jsx("rect",{className:Yf(["react-flow__minimap-node",{selected:F},A]),x:f,y:l,rx:c,ry:c,width:r,height:n,style:{fill:w,stroke:_,strokeWidth:$},shapeRendering:j,onClick:U?(J)=>U(J,u):void 0})}var hX=yu.memo(xX),bX=(u)=>u.nodes.map((f)=>f.id),$9=(u)=>u instanceof Function?u:()=>u;function vX({nodeStrokeColor:u,nodeColor:f,nodeClassName:l="",nodeBorderRadius:r=5,nodeStrokeWidth:n,nodeComponent:i=hX,onClick:y}){let _=eu(bX,zf),$=$9(f),A=$9(u),c=$9(l),j=typeof window>"u"||!!window.chrome?"crispEdges":"geometricPrecision";return ru.jsx(ru.Fragment,{children:_.map((F)=>ru.jsx(IX,{id:F,nodeColorFunc:$,nodeStrokeColorFunc:A,nodeClassNameFunc:c,nodeBorderRadius:r,nodeStrokeWidth:n,NodeComponent:i,onClick:y,shapeRendering:j},F))})}function kX({id:u,nodeColorFunc:f,nodeStrokeColorFunc:l,nodeClassNameFunc:r,nodeBorderRadius:n,nodeStrokeWidth:i,shapeRendering:y,NodeComponent:_,onClick:$}){let{node:A,x:c,y:j,width:F,height:U}=eu((Q)=>{let L=Q.nodeLookup.get(u);if(!L)return{node:void 0,x:0,y:0,width:0,height:0};let w=L.internals.userNode,{x:J,y:N}=L.internals.positionAbsolute,{width:q,height:W}=t0(w);return{node:w,x:J,y:N,width:q,height:W}},zf);if(!A||A.hidden||!kc(A))return null;return ru.jsx(_,{x:c,y:j,width:F,height:U,style:A.style,selected:!!A.selected,className:r(A),color:f(A),borderRadius:n,strokeColor:l(A),strokeWidth:i,shapeRendering:y,onClick:$,id:A.id})}var IX=yu.memo(kX),gX=yu.memo(vX),sX=200,aX=150,oX=(u)=>!u.hidden,dX=(u)=>{let f={x:-u.transform[0]/u.transform[2],y:-u.transform[1]/u.transform[2],width:u.width/u.transform[2],height:u.height/u.transform[2]};return{viewBB:f,boundingRect:u.nodeLookup.size>0?hc(ry(u.nodeLookup,{filter:oX}),f):f,rfId:u.rfId,panZoom:u.panZoom,translateExtent:u.translateExtent,flowWidth:u.width,flowHeight:u.height,ariaLabelConfig:u.ariaLabelConfig}},eX="react-flow__minimap-desc";function hW({style:u,className:f,nodeStrokeColor:l,nodeColor:r,nodeClassName:n="",nodeBorderRadius:i=5,nodeStrokeWidth:y,nodeComponent:_,bgColor:$,maskColor:A,maskStrokeColor:c,maskStrokeWidth:j,position:F="bottom-right",onClick:U,onNodeClick:Q,pannable:L=!1,zoomable:w=!1,ariaLabel:J,inversePan:N,zoomStep:q=1,offsetScale:W=5}){let z=Zf(),Z=yu.useRef(null),{boundingRect:H,viewBB:E,rfId:D,panZoom:h,translateExtent:V,flowWidth:Y,flowHeight:p,ariaLabelConfig:O}=eu(dX,zf),m=u?.width??sX,X=u?.height??aX,v=H.width/m,T=H.height/X,S=Math.max(v,T),k=S*m,I=S*X,b=W*S,o=H.x-(k-H.width)/2-b,s=H.y-(I-H.height)/2-b,x=k+b*2,fu=I+b*2,$u=`${eX}-${D}`,tu=yu.useRef(0),ju=yu.useRef();tu.current=S,yu.useEffect(()=>{if(Z.current&&h)return ju.current=LN({domNode:Z.current,panZoom:h,getTransform:()=>z.getState().transform,getViewScale:()=>tu.current}),()=>{ju.current?.destroy()}},[h]),yu.useEffect(()=>{ju.current?.update({translateExtent:V,width:Y,height:p,inversePan:N,pannable:L,zoomStep:q,zoomable:w})},[L,w,N,q,V,Y,p]);let Gu=U?(e)=>{let[uu,Wu]=ju.current?.pointer(e)||[0,0];U(e,{x:uu,y:Wu})}:void 0,qu=Q?yu.useCallback((e,uu)=>{let Wu=z.getState().nodeLookup.get(uu).internals.userNode;Q(e,Wu)},[]):void 0,P=J??O["minimap.ariaLabel"];return ru.jsx(n8,{position:F,style:{...u,"--xy-minimap-background-color-props":typeof $==="string"?$:void 0,"--xy-minimap-mask-background-color-props":typeof A==="string"?A:void 0,"--xy-minimap-mask-stroke-color-props":typeof c==="string"?c:void 0,"--xy-minimap-mask-stroke-width-props":typeof j==="number"?j*S:void 0,"--xy-minimap-node-background-color-props":typeof r==="string"?r:void 0,"--xy-minimap-node-stroke-color-props":typeof l==="string"?l:void 0,"--xy-minimap-node-stroke-width-props":typeof y==="number"?y:void 0},className:Yf(["react-flow__minimap",f]),"data-testid":"rf__minimap",children:ru.jsxs("svg",{width:m,height:X,viewBox:`${o} ${s} ${x} ${fu}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":$u,ref:Z,onClick:Gu,children:[P&&ru.jsx("title",{id:$u,children:P}),ru.jsx(gX,{onClick:qu,nodeColor:r,nodeStrokeColor:l,nodeBorderRadius:i,nodeClassName:n,nodeStrokeWidth:y,nodeComponent:_}),ru.jsx("path",{className:"react-flow__minimap-mask",d:`M${o-b},${s-b}h${x+b*2}v${fu+b*2}h${-x-b*2}z + M${E.x},${E.y}h${E.width}v${E.height}h${-E.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}hW.displayName="MiniMap";var jb=yu.memo(hW),uY=(u)=>(f)=>u?`${Math.max(1/f.transform[2],1)}`:void 0,fY={[Yn.Line]:"right",[Yn.Handle]:"bottom-right"};function lY({nodeId:u,position:f,variant:l=Yn.Handle,className:r,style:n=void 0,children:i,color:y,minWidth:_=10,minHeight:$=10,maxWidth:A=Number.MAX_VALUE,maxHeight:c=Number.MAX_VALUE,keepAspectRatio:j=!1,resizeDirection:F,autoScale:U=!0,shouldResize:Q,onResizeStart:L,onResize:w,onResizeEnd:J}){let N=NW(),q=typeof u==="string"?u:N,W=Zf(),z=yu.useRef(null),Z=l===Yn.Handle,H=eu(yu.useCallback(uY(Z&&U),[Z,U]),zf),E=yu.useRef(null),D=f??fY[l];yu.useEffect(()=>{if(!z.current||!q)return;if(!E.current)E.current=TN({domNode:z.current,nodeId:q,getStoreItems:()=>{let{nodeLookup:V,transform:Y,snapGrid:p,snapToGrid:O,nodeOrigin:m,domNode:X}=W.getState();return{nodeLookup:V,transform:Y,snapGrid:p,snapToGrid:O,nodeOrigin:m,paneDomNode:X}},onChange:(V,Y)=>{let{triggerNodeChanges:p,nodeLookup:O,parentLookup:m,nodeOrigin:X}=W.getState(),v=[],T={x:V.x,y:V.y},S=O.get(q);if(S&&S.expandParent&&S.parentId){let k=S.origin??X,I=V.width??S.measured.width??0,b=V.height??S.measured.height??0,o={id:S.id,parentId:S.parentId,rect:{width:I,height:b,...Ic({x:V.x??S.position.x,y:V.y??S.position.y},{width:I,height:b},S.parentId,O,k)}},s=a6([o],O,m,X);v.push(...s),T.x=V.x?Math.max(k[0]*I,V.x):void 0,T.y=V.y?Math.max(k[1]*b,V.y):void 0}if(T.x!==void 0&&T.y!==void 0){let k={id:q,type:"position",position:{...T}};v.push(k)}if(V.width!==void 0&&V.height!==void 0){let I={id:q,type:"dimensions",resizing:!0,setAttributes:!F?!0:F==="horizontal"?"width":"height",dimensions:{width:V.width,height:V.height}};v.push(I)}for(let k of Y){let I={...k,type:"position"};v.push(I)}p(v)},onEnd:({width:V,height:Y})=>{let p={id:q,type:"dimensions",resizing:!1,dimensions:{width:V,height:Y}};W.getState().triggerNodeChanges([p])}});return E.current.update({controlPosition:D,boundaries:{minWidth:_,minHeight:$,maxWidth:A,maxHeight:c},keepAspectRatio:j,resizeDirection:F,onResizeStart:L,onResize:w,onResizeEnd:J,shouldResize:Q}),()=>{E.current?.destroy()}},[D,_,$,A,c,j,L,w,J,Q]);let h=D.split("-");return ru.jsx("div",{className:Yf(["react-flow__resize-control","nodrag",...h,l,r]),ref:z,style:{...n,scale:H,...y&&{[Z?"backgroundColor":"borderColor"]:y}},children:i})}var Fb=yu.memo(lY);var G=Mn.default.createElement,{useEffect:j0}=Mn.default,gl=Mn.default.useState,Pn=Mn.default.useRef,B$=[{id:"in-left",side:"left",position:wu.Left,style:{top:"50%"}},{id:"in-top-left",side:"top",slot:"left",slotIndex:-1,position:wu.Top,style:{left:"28%"}},{id:"in-top-mid",side:"top",slot:"mid",slotIndex:0,position:wu.Top,style:{left:"50%"}},{id:"in-top-right",side:"top",slot:"right",slotIndex:1,position:wu.Top,style:{left:"72%"}},{id:"in-bottom-left",side:"bottom",slot:"left",slotIndex:-1,position:wu.Bottom,style:{left:"28%"}},{id:"in-bottom-mid",side:"bottom",slot:"mid",slotIndex:0,position:wu.Bottom,style:{left:"50%"}},{id:"in-bottom-right",side:"bottom",slot:"right",slotIndex:1,position:wu.Bottom,style:{left:"72%"}}],Z$=[{id:"out-right",position:wu.Right,style:{top:"50%"}}],bW=["#4eb7a8","#d7a13a","#69aee8","#e0835f","#b7d86b","#d98bd2","#5fc6bf"],jy=236,Fy=88,vW=15000,rY=10,F9=96,A0=72,J9=64,kW=12;function y8(){return typeof document>"u"||document.visibilityState!=="hidden"}function IW(u,f){let l=Number.parseFloat(String(u||""));return Number.isFinite(l)?l/100:f}function nY(u,f,l){let r=String(u.side||"");if(r!=="top"&&r!=="bottom")return 0;let n=Number(u.slotIndex||0),i=r==="top"?"in-top-mid":"in-bottom-mid",y=f.get(u.id)||0,_=f.get(i)||0;if(n===0)return _===0?-26:28+y*74;let $=l===0?Math.abs(n)*2:Math.sign(l)===Math.sign(n)?-3:3;if(_>0&&y===0)return-14+$;return 8+y*74+$}function _8(u){let f=u.filter((i,y)=>{let _=u[y-1];return!_||Math.abs(_.x-i.x)>0.5||Math.abs(_.y-i.y)>0.5});if(f.length<2)return"";let l=`M ${f[0].x},${f[0].y}`,r=f[0];for(let i=1;i0.5||Math.abs(F.y-r.y)>0.5)l+=` L ${F.x},${F.y}`;l+=` Q ${_.x},${_.y} ${U.x},${U.y}`,r=U}let n=f[f.length-1];return`${l} L ${n.x},${n.y}`}function cL(u,f,l,r,n,i,y=""){let _=l>=u,$=Math.max(1,Math.abs(l-u)),A=Math.abs(r-f),c=Math.max(34,Math.min(118,$*0.26)),j=Math.min(280,Math.abs(i));if(_&&n===wu.Left&&j<4&&A<28&&$<420)return`M ${u},${f} C ${u+c},${f} ${l-c},${r} ${l},${r}`;if(_&&n===wu.Left&&(y==="direct-forward-left"||$<=260&&A<=210)){let J=Math.max(42,Math.min(140,$*0.48)),N=Math.max(-28,Math.min(28,i*0.18));return`M ${u},${f} C ${u+J},${f+N} ${l-J},${r} ${l},${r}`}if(_){let J=u+c;if(n===wu.Top||n===wu.Bottom){let W=n===wu.Top?-1:1,z=r+W*(54+j*0.42);return _8([{x:u,y:f},{x:J,y:f},{x:J+Math.min(120,$*0.18),y:z},{x:l,y:z},{x:l,y:r+W*34},{x:l,y:r}])}let N=l-c,q=(f+r)/2+i;return _8([{x:u,y:f},{x:J,y:f},{x:J+Math.min(110,$*0.16),y:q},{x:N-Math.min(90,$*0.12),y:q},{x:N,y:r},{x:l,y:r}])}let Q=n===wu.Bottom?1:n===wu.Top?-1:i>=0?1:-1,L=Math.max(u,l)+92+Math.min(180,j*0.52),w=Q<0?Math.min(f,r)-84-j*0.62:Math.max(f,r)+84+j*0.62;if(n===wu.Top||n===wu.Bottom)return _8([{x:u,y:f},{x:u+c,y:f},{x:L,y:w},{x:l,y:w},{x:l,y:r+Q*38},{x:l,y:r}]);return _8([{x:u,y:f},{x:u+c,y:f},{x:L,y:w},{x:l-c,y:w},{x:l-c,y:r},{x:l,y:r}])}function iY({data:u}){return G("div",{className:"pipeline-flow-node-body"},B$.map((f)=>G(m1,{key:f.id,id:f.id,type:"target",position:f.position,isConnectable:!1,className:`pipeline-flow-handle input ${f.side} slot-${f.slot||"mid"}`,style:f.style})),Z$.map((f)=>G(m1,{key:f.id,id:f.id,type:"source",position:f.position,isConnectable:!1,className:"pipeline-flow-handle output right",style:f.style})),u?.label)}function yY({id:u,sourceX:f,sourceY:l,targetX:r,targetY:n,targetPosition:i,markerEnd:y,markerStart:_,style:$,data:A}){let c=Number(A?.laneOffset||0),j=cL(f,l,r,n,i,c,String(A?.routeMode||""));return G(Ay,{id:u,path:j,markerEnd:y,markerStart:_,style:$,interactionWidth:28})}var _Y={pipelineCurve:yY},$Y={pipelineNode:iY};function c8(u){if(!u)return"--";let f=new Date(u);if(Number.isNaN(f.getTime()))return"--";return tf(f)}function Hr(u){let f=Number(u);if(!Number.isFinite(f)||f<0)return"--";let l=Math.round(f/1000);if(l<60)return`${l}s`;if(l<3600)return`${Math.floor(l/60)}m ${l%60}s`;return`${Math.floor(l/3600)}h ${Math.floor(l%3600/60)}m`}function U9(u){let f=Number(u);if(!Number.isFinite(f))return"--";return f.toLocaleString("zh-CN")}function gW(u){let f=Number(u);if(!Number.isFinite(f))return"--";return`${Math.round(Math.max(0,Math.min(1,f))*100)}%`}function Du(u){return typeof u==="object"&&u!==null&&!Array.isArray(u)}function Vu(u){return Array.isArray(u)?u:[]}function vu(u){if(!u)return null;let f=new Date(u);return Number.isNaN(f.getTime())?null:f.getTime()}function V$(u){return Number.isFinite(Number(u))?new Date(Number(u)).toISOString():""}function Y$(...u){for(let f of u){let l=vu(f);if(l!==null)return new Date(l).toISOString()}return""}function B9(...u){let f=u.map(vu).filter((l)=>l!==null);return f.length>0?new Date(Math.max(...f)).toISOString():""}function V9(u){return["succeeded","failed","skipped","cancelled","canceled","completed"].includes(String(u||"").toLowerCase())}function jL(u){let f=UL(u).toLowerCase();return["running","active","in-progress","in_progress"].includes(f)}function sW(u,f="status"){return u.reduce((l,r)=>{let n=String(r?.[f]||"unknown").toLowerCase();return l[n]=(l[n]||0)+1,l},{})}function FL(u){if(!u||typeof u!=="string")return null;try{let f=JSON.parse(u);return Du(f)?f:null}catch{return null}}function Q9(u){let f=u.map(FL).filter((i)=>Boolean(i)),l=f.flatMap((i)=>[i.timestamp,i.createdAt,i.updatedAt]).filter(Boolean),r=B9(...l),n=Array.from(new Set(f.map((i)=>String(i.event||i.action||i.type||"")).filter(Boolean))).slice(0,3);return{total:u.length,parsed:f.length,lastAt:r,eventKinds:n}}function j8(u){if(u===null||u===void 0)return"--";if(typeof u==="boolean")return u?"是":"否";if(typeof u==="number")return String(u);if(typeof u==="string")return u.length>80?`${u.slice(0,77)}...`:u;if(Array.isArray(u))return`${u.length} 项`;if(typeof u==="object")return`${Object.keys(u).length} 字段`;return String(u)}function JL(u,f=280){if(u===null||u===void 0)return"";let r=(typeof u==="string"?u:String(u)).replace(/\r\n/gu,` +`).trim();return r.length>f?`${r.slice(0,Math.max(0,f-1))}...`:r}function UL(u){if(typeof u==="string")return u;if(Du(u))return String(u.status||u.state||u.phase||"unknown");return"unknown"}function tY(u){return u.filter((f)=>f&&f.value!==void 0&&f.value!==null&&String(f.value)!=="")}function K9({items:u}){let f=tY(Vu(u));return G("div",{className:"pipeline-kv-grid"},f.map((l)=>G("span",{key:l.label},G("b",null,l.label),G("span",null,l.value))))}function D9({items:u}){let f=Vu(u).map((l)=>String(l||"")).filter(Boolean);if(f.length===0)return null;return G("div",{className:"pipeline-chip-row"},f.map((l,r)=>G("span",{key:`${r}-${l}`},l)))}function G9(u,f){let l=String(f?.procedureRunId||""),r=Vu(u?.procedureRuns);return r.find((n)=>String(Br(n))===l)||r.at(-1)||null}function AY(u,f){let l=String(f||"");if(!l)return null;return Vu(u?.procedureRuns).find((r)=>Br(r)===l)||null}function q9(u){return Vu(u?.attempts).length}function aW(u){return Vu(u?.attempts).reduce((f,l)=>f+W8(l).length,0)}function W8(u){return Vu(u?.opencodeMessages?.steps).filter(Du)}function QL(u){let f=String(u?.status||"").toLowerCase();if(["error","failed","failure"].includes(f))return"failed";if(["completed","succeeded","success"].includes(f))return"succeeded";if(["running","started","in_progress"].includes(f))return"running";return"unknown"}function cY(u,f){let l=T9(u.map((i)=>i?.agent)).slice(0,3),r=T9(u.map((i)=>i?.model)).slice(0,3),n=f.length<=2?f.map((i)=>`session ${i}`):[`sessions ${f.length}`,...f.slice(0,2).map((i)=>`session ${i}`)];return[...l.map((i)=>`agent ${i}`),...r.map((i)=>`model ${i}`),...n]}function O$(u,f=0){return String(u?.messageId||u?.index||"")||`step-${f}`}function jY({steps:u,sessionIds:f,sessionFacts:l,matchedStepKey:r}){let n=Vu(u),i=n.findIndex((w,J)=>O$(w,J)===r),y=i>=0?n[i]:null,_=n.flatMap((w)=>[vu(w?.createdAt),vu(w?.completedAt)]).filter((w)=>w!==null),$=_.length>0?Math.min(..._):null,A=_.length>0?Math.max(..._):null,c=$!==null&&A!==null?Math.max(0,A-$):null,j=n.reduce((w,J)=>w+Vu(J?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool").length,0),F=n.reduce((w,J)=>w+Vu(J?.parts).filter((N)=>["text","reasoning"].includes(String(N?.type||"").toLowerCase())).length,0),U=n.reduce((w,J)=>w+Vu(J?.parts).filter((N)=>String(N?.type||"").toLowerCase()==="tool"&&QL(N)==="failed").length,0),Q=[`${n.length} steps`,`${f.length} sessions`,`${F} messages`,`${j} tools`,c!==null?`duration ${Hr(c)}`:"",U>0?`${U} failed tools`:""].filter(Boolean),L=y?[`Step ${y?.index??i+1}`,String(y?.role||"role --"),y?.model?`model ${y.model}`:"",y?.finish?`finish ${y.finish}`:"",y?.durationMs!==void 0&&y?.durationMs!==null?`duration ${Hr(y.durationMs)}`:""].filter(Boolean):[];return G("section",{className:"pipeline-trace-timeline","data-testid":"pipeline-step-timeline"},G("div",{className:"pipeline-trace-head"},G("div",null,G("b",null,"OpenCode Trace"),G("span",null,"Trace 使用 Code Queue 统一样式展示完整 agent loop;Pipeline 旧 step/message/tool 卡片样式已废弃。")),G("div",{className:"pipeline-trace-session-head","data-testid":"pipeline-step-timeline-session"},G("span",null,Q.join(" / ")||"Trace"),l.length>0?G(D9,{items:l}):null)),y?G("div",{className:"pipeline-trace-focus","data-testid":"pipeline-trace-matched-step"},G("span",{className:"codex-output-channel"},"Matched"),G("strong",null,`Gantt selection -> ${L.join(" / ")}`),G("time",null,`${c8(y?.createdAt)} -> ${c8(y?.completedAt)}`)):null,G(St,{port:mU,input:n,className:"codex-transcript pipeline-trace",testId:"pipeline-opencode-step-trace",emptyText:"暂无 OpenCode Trace 输出",keepRecentToolCalls:3}))}function z9(u){return Vu(u).flatMap((f)=>{if(Du(f))return[f];let l=FL(f);return l?[l]:[]})}function Ir(u){return String(u?.event||u?.action||u?.requestedAction||u?.type||"").toLowerCase()}function cy(u){return Y$(u?.timestamp,u?.createdAt,u?.updatedAt,u?.startedAt,u?.finishedAt)}function FY(u){return vu(cy(u))}function L8(u){return String(u?.attempt||u?.id||"")}function T9(u){let f=new Set,l=[];for(let r of u){let n=String(r||"");if(!n||f.has(n))continue;f.add(n),l.push(n)}return l}function oW(u){switch(String(u||"").toLowerCase()){case"monitor":return"monitor";case"webui":return"webui";case"cli":return"cli";case"system":return"runner";default:return String(u||"--")}}function P1(u){return String(u?.requestedAction||u?.action||"").toLowerCase()}function H$(u){switch(P1(u)){case"guide":return"引导";case"modify":return"修改";case"approve":return"审核通过";case"restart":return"重启";case"redo":return"重做";default:return String(u?.requestedAction||u?.action||"控制")}}function dW(u){switch(Ir(u)){case"initial-prompt-delivered":return"初始 prompt";case"append-prompt-delivered":return"追加 prompt";case"append-prompt-queued":return"追加 prompt 已排队";case"monitor-prompt-delivered":return"Monitor prompt";case"node-long-running-observation":return"长任务观察";case"node-finished":return"节点完成";case"oa-policy-downstream-evaluated":return"OA 下游策略";case"control-command-queued":return`${H$(u)} 已发起`;case"control-command-applied":return`${H$(u)} 已生效`;case"control-command-ignored":return`${H$(u)} 已忽略`;default:return String(u?.event||u?.action||u?.requestedAction||"event")}}function eW(u){return JL(u?.promptPreview||u?.reasonPreview||u?.prompt||u?.reason||"",240)}function JY(u){let f=String(u?.prompt||""),l=String(u?.reason||u?.restartReason||""),r=f?"":String(u?.promptPreview||""),n=l?"":String(u?.reasonPreview||"");return[f||r?{label:f?"prompt":"prompt preview",value:f||r}:null,l||n?{label:l?"reason":"reason preview",value:l||n}:null,Vu(u?.resetNodeIds).length>0?{label:"reset nodes",value:Vu(u.resetNodeIds).join(", ")}:null,Vu(u?.runningResetNodeIds).length>0?{label:"interrupted running nodes",value:Vu(u.runningResetNodeIds).join(", ")}:null,Vu(u?.interruptedProcedureRunIds).length>0?{label:"interrupted procedures",value:Vu(u.interruptedProcedureRunIds).join(", ")}:null,u?.interruptedProcedureRunId?{label:"interrupted procedure",value:String(u.interruptedProcedureRunId)}:null].filter(Boolean)}function N9(u){let f=W8(u),l=f.map(($)=>vu($?.createdAt)).filter(($)=>$!==null),r=f.map(($)=>vu($?.completedAt)??vu($?.createdAt)).filter(($)=>$!==null),n=z9(u?.controlEventRecords).map(($)=>FY($)).filter(($)=>$!==null),i=Vu(u?.assistantOutputs).map(($)=>vu($?.updatedAt)).filter(($)=>$!==null),y=l[0]??n[0]??i[0]??null,_=r.at(-1)??n.at(-1)??i.at(-1)??y;return{startMs:y,endMs:_}}function UY(u,f,l,r,n=""){let i=Vu(u?.procedureRuns).filter((_)=>w8(_,f)===l);if(i.length===0)return null;if(n){let _=i.find(($)=>Br($)===n);if(_)return _}if(r===null)return i.at(-1)||null;let y=i.find((_)=>{let $=vu($8(_,u)),A=vu(t8(_,u))??$;return $!==null&&A!==null&&r>=$-1000&&r<=A+1000});if(y)return y;return i.slice().sort((_,$)=>{let A=vu($8(_,u))??r,c=vu(t8(_,u))??A,j=vu($8($,u))??r,F=vu(t8($,u))??j,U=Math.min(Math.abs(A-r),Math.abs(c-r)),Q=Math.min(Math.abs(j-r),Math.abs(F-r));return U-Q})[0]||null}function qL(u,f){let l=Vu(u?.attempts).filter(Du);if(l.length===0)return null;let r=String(f?.attempt||"");if(r){let y=l.find((_)=>L8(_)===r);if(y)return y}let n=Number.isFinite(Number(f?.ms))?Number(f.ms):null;if(n===null)return l.at(-1)||null;let i=l.find((y)=>{let _=N9(y);return Number.isFinite(_.startMs)&&Number.isFinite(_.endMs)&&n>=Number(_.startMs)-1000&&n<=Number(_.endMs)+1000});if(i)return i;return l.slice().sort((y,_)=>{let $=N9(y),A=N9(_),c=Math.min(Math.abs(Number($.startMs??n)-n),Math.abs(Number($.endMs??n)-n)),j=Math.min(Math.abs(Number(A.startMs??n)-n),Math.abs(Number(A.endMs??n)-n));return c-j})[0]||l.at(-1)||null}function NL(u,f){let l=W8(u);if(l.length===0)return{step:null,stepIndex:-1,stepKey:""};if(f===null){let i=l[0];return{step:i,stepIndex:0,stepKey:O$(i,0)}}for(let i=0;i=_-1000&&f<=$+1000)return{step:y,stepIndex:i,stepKey:O$(y,i)}}let r=l.findIndex((i)=>{let y=vu(i?.createdAt)??vu(i?.completedAt);return y!==null&&y>=f});if(r>=0){let i=l[r];return{step:i,stepIndex:r,stepKey:O$(i,r)}}let n=Math.max(0,l.length-1);return{step:l[n],stepIndex:n,stepKey:O$(l[n],n)}}function QY(u,f){let l=String(f?.runId||u?.runId||"");if(String(f?.mode||"")==="interval"){let A=f?.interval||{},c=G9(u,A)||A.raw||{};return{mode:"interval",runId:l,interval:A,marker:null,nodeId:String(A?.nodeId||w8(c,l)||""),procedure:c,attempt:null,matchedStep:null,matchedStepIndex:-1,matchedStepKey:""}}let r=Du(f?.marker)?f.marker:{},n=Number.isFinite(Number(r?.ms))?Number(r.ms):null,i=String(r?.nodeId||""),y=i?UY(u,l,i,n,String(r?.procedureRunId||"")):null,_=y?qL(y,r):null,$=_?NL(_,n):{step:null,stepIndex:-1,stepKey:""};return{mode:"event",runId:l,interval:null,marker:r,nodeId:i,procedure:y,attempt:_,matchedStep:$.step,matchedStepIndex:$.stepIndex,matchedStepKey:$.stepKey}}function qY({procedure:u,matchedStepKey:f="",matchedAttemptId:l=""}){let r=Vu(u?.attempts);if(r.length===0)return G(Ur,{title:"暂无 attempt 详情",text:"当前 procedure 还没有可展示的 attempt / OpenCode Trace;若刚点击甘特线,请等待 node 详情抓取完成。"});return r.map((n,i)=>{let y=n?.opencodeMessages||{},_=W8(n),$=Vu(y.sessionIds).map((F)=>String(F)).filter(Boolean),A=cY(_,$),c=L8(n)||`attempt-${i+1}`,j=_.reduce((F,U)=>F+Vu(U?.parts).filter((Q)=>String(Q?.type||"").toLowerCase()==="tool"&&QL(Q)==="failed").length,0);return G("article",{key:c,className:`pipeline-attempt-card ${l===c?"matched":""}`},G("div",{className:"pipeline-attempt-head"},G("div",null,G("strong",null,c),G("span",null,y.source||"opencode")),G("div",{className:"pipeline-attempt-badges"},G("span",null,`${_.length} steps`),G("span",null,`${y.toolCallCount??"--"} tools`),j>0?G("span",{className:"danger"},`${j} failed`):null)),G(K9,{items:[{label:"messages",value:y.messageCount??"--"},{label:"steps",value:y.stepCount??"--"},{label:"tools",value:y.toolCallCount??"--"},{label:"updated",value:Nu(y.updatedAt)},{label:"sessions",value:$.join(", ")||"--"}]}),_.length===0?G("p",{className:"muted paragraph"},"当前 attempt 尚未返回 OpenCode Trace;请确认 D601 pipeline-control 已重建并重新抓取。"):G(jY,{steps:_,sessionIds:$,sessionFacts:A,matchedStepKey:f}))})}function W9(u,f){return`${u}::${f}`}function F8(u,f,l){if(!Du(u))return null;return String(u.runId||"")===f&&String(u.nodeId||"")===l?u:null}function NY(u,f){let l=Du(u)?u:{};if(!Du(f))return l;let r=Vu(f.attempts),n=Vu(l.attempts);return{...l,...f,attempts:r.length>0?r:n}}function WY(u,f,l,r){if(!F8(f,l,r))return u;let n=Vu(f.procedureRuns),i=Du(u)?u:{};return{...i,...f,controlEvents:Vu(f.controlEvents).length>0?f.controlEvents:i.controlEvents,procedureRuns:n.length>0?n:i.procedureRuns}}function LY({selection:u,runDetails:f,nodeDetails:l,nodeDetailsState:r,onRaw:n,onCollapse:i}){if(!u?.mode)return G("aside",{className:"pipeline-gantt-detail-panel empty","data-testid":"pipeline-gantt-detail-panel"},G("div",{className:"pipeline-gantt-detail-head"},G("div",null,G("span",{className:"panel-eyebrow"},"Gantt Detail"),G(nf,{title:"未选择元素",level:3})),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起")),G(Ur,{title:"选择一条执行线或一个控制点",text:"点击甘特图中的 node 执行线、prompt 点或控制点,在这里查看结构化过程和 OpenCode step。"}));let y=String(u?.runId||""),_=String(u?.interval?.nodeId||u?.marker?.nodeId||""),$=f?.runId===y?f.details:null,A=F8(l,y,_),c=String(r?.runId||"")===y&&String(r?.nodeId||"")===_,j=WY($,A,y,_),F=(String(f?.runId||"")!==y||Boolean(f?.loading))&&!j,U=String(f?.runId||"")===y?String(f?.error||""):"",Q=c?String(r?.error||""):"",L=j?QY(j,u):null,w=L?.interval||u?.interval||null,J=L?.marker||u?.marker||null,N=String(w?.procedureRunId||J?.procedureRunId||""),q=A?AY(A,N)||G9(A,w||{procedureRunId:N}):null,W=L?.procedure||(j?G9(j,w||{procedureRunId:N}):null)||w?.raw||{};if(q&&(q9(W)===0||aW(q)>=aW(W)))W=NY(W,q);let z=L?.attempt||null,Z=String(L?.matchedStepKey||"");if(!z&&J&&q9(W)>0)z=qL(W,J),Z=String(NL(z,Number.isFinite(Number(J?.ms))?Number(J.ms):null).stepKey||"");let H=L8(z),E=q9(W)>0,D=c&&Boolean(r?.loading)&&!E,h=Boolean(F||D),V=[E?"":U,Q].filter(Boolean).join(" / "),Y=c&&r?.fetchedAt?r.fetchedAt:f?.fetchedAt,p=UL(W?.status||w?.status||J?.status||J?.event),O=u?.mode==="event"?J?.label||dW(J?.raw||J)||"event":L?.nodeId||w?.nodeId||"node",m=J?JY(J?.raw||J):[],X=J?[Ir(J?.raw||J)?`event ${Ir(J?.raw||J)}`:"",J?.promptEvent?`prompt ${J.promptEvent}`:"",J?.action?`action ${J.action}`:"",J?.sourceKind?`source ${oW(J.sourceKind)}`:"",J?.sourceNodeId?`from ${J.sourceNodeId}`:"",J?.targetNodeId?`to ${J.targetNodeId}`:"",J?.snapReason?`draw ${J.snapReason}`:""].filter(Boolean):[];return G("aside",{className:"pipeline-gantt-detail-panel","data-testid":"pipeline-gantt-detail-panel"},G("div",{className:"pipeline-gantt-detail-head"},G("div",null,G("span",{className:"panel-eyebrow"},u?.mode==="event"?"Gantt Event Detail":"Gantt Line Detail"),G(nf,{title:O,level:3,loading:h})),G("div",{className:"pipeline-gantt-detail-head-actions"},G(Cn,{status:p},p),G("button",{type:"button",className:"ghost-btn mini",onClick:i,"data-testid":"pipeline-gantt-sidebar-collapse"},"收起"))),J?G("article",{className:"pipeline-event-card"},G("div",{className:"pipeline-event-card-head"},G("strong",null,J?.label||dW(J?.raw||J)),G(D9,{items:X})),G(K9,{items:[{label:"event time",value:Nu(J?.timestampIso||J?.timestamp||"--")},J?.snapped?{label:"drawn time",value:Nu(J?.renderedTimestampIso||J?.ms)}:null,{label:"node",value:J?.nodeId||"--"},{label:"procedure",value:J?.procedureRunId||Br(W)||"--"},{label:"attempt",value:J?.attempt||H||"--"},{label:"source kind",value:J?.sourceKind?oW(J.sourceKind):"--"},{label:"source node",value:J?.sourceNodeId||"--"},{label:"target node",value:J?.targetNodeId||"--"},{label:"command",value:J?.commandId||J?.eventId||"--"},J?.snapReason?{label:"placement",value:J.snapReason}:null]}),m.length>0?G("div",{className:"pipeline-event-blocks"},m.map((v,T)=>G("section",{key:`${v.label}-${T}`,className:"pipeline-event-text-block"},G("b",null,v.label),G("p",null,v.value)))):null,eW(J?.raw||J)?G("p",{className:"pipeline-text-preview"},eW(J?.raw||J)):null):null,G(K9,{items:[{label:"epoch",value:y||w?.runId||"--"},{label:"node",value:L?.nodeId||w?.nodeId||J?.nodeId||"--"},{label:"procedure",value:w?.procedureRunId||J?.procedureRunId||Br(W)||"--"},{label:"started",value:Nu(w?.startedAt||W?.startedAt)},{label:"finished",value:Nu(w?.finishedAt||W?.finishedAt)},{label:"duration",value:Hr(w?.durationMs||W?.durationMs)},{label:"fetched",value:Y?tf(Y):"--"},L?.matchedStep?{label:"matched step",value:`Step ${L.matchedStep.index??L.matchedStepIndex+1}`}:null]}),G(yf,{error:V}),G("div",{className:"pipeline-gantt-detail-actions"},G(gr,{title:`Procedure ${w?.procedureRunId||J?.procedureRunId||L?.nodeId||"node"}`,data:W,onOpen:n,testId:"raw-pipeline-gantt-procedure"}),J?G(gr,{title:`Pipeline event ${J?.id||J?.commandId||J?.eventId||L?.nodeId||"event"}`,data:J?.raw||J,onOpen:n,testId:"raw-pipeline-gantt-event"}):null,j?G(gr,{title:`Pipeline run ${y||"--"}`,data:j,onOpen:n,testId:"raw-pipeline-gantt-node-details"}):null),!h&&!Br(W)&&!J?G(Ur,{title:"暂无过程详情",text:"当前选择还没有可匹配的 procedure 运行记录。"}):null,!h&&Br(W)?G(qY,{procedure:W,matchedStepKey:Z,matchedAttemptId:H}):null)}function wY({value:u}){let l=String(u||"--").split(/([_-])/u);return G(Mn.default.Fragment,null,l.map((r,n)=>r==="-"||r==="_"?G(Mn.default.Fragment,{key:n},r,G("wbr",null)):G(Mn.default.Fragment,{key:n},r)))}async function pn(u,f={}){return Eu(u,{invalidJsonPrefix:"Pipeline 返回了无效 JSON",...f})}function Cn({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return G("span",{className:`status-badge ${l}`},f||u||"unknown")}function Yl({label:u,value:f,hint:l,tone:r}){return G("article",{className:`metric-card ${r||""}`},G("div",{className:"metric-label"},u),G("div",{className:"metric-value"},f),G("div",{className:"metric-hint"},l))}function c0({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return G("section",{className:`panel ${n||""}`},G("div",{className:"panel-head"},G("div",null,f?G("p",{className:"panel-eyebrow"},f):null,G(nf,{title:u,loading:i})),l?G("div",{className:"panel-actions"},l):null),G("div",{className:"panel-body"},r))}function gr({title:u,data:f,onOpen:l,testId:r}){return G("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function Or({title:u,subtitle:f,facts:l,data:r,onRaw:n,testId:i}){let y=Vu(l).map((_)=>String(_||"")).filter(Boolean);return G("article",{className:"pipeline-evidence-row"},G("div",{className:"pipeline-evidence-main"},G("strong",null,u),f?G("span",null,f):null),G("div",{className:"pipeline-evidence-facts"},y.map((_,$)=>G("span",{key:`${$}-${_.slice(0,16)}`},_))),r!==void 0?G(gr,{title:u,data:r,onOpen:n,testId:i}):null)}function Ur({title:u,text:f}){return G("div",{className:"empty-state"},G("strong",null,u),G("span",null,f))}function KY(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function GY(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function zY(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function TY(u){return{components:Array.isArray(u?.registry?.components)?u.registry.components:[],pipelines:Array.isArray(u?.pipelines)?u.pipelines:[],runs:Array.isArray(u?.runs)?u.runs:[]}}function uL(u,f,l){let r=u?._unidesk?.arrayLimits?.[f],n=Number(r?.originalLength);return Number.isFinite(n)?n:l}function WL(u){if(!u||typeof u!=="object"||Array.isArray(u))return"--";return`${u.componentClass||"--"}/${u.id||"--"}`}function J8(u){if(!u||typeof u!=="object"||Array.isArray(u))return"";let f=String(u.componentClass||"").trim(),l=String(u.id||"").trim();return f&&l?`${f}/${l}`:""}function X9(u){return u?.config&&typeof u.config==="object"&&!Array.isArray(u.config)?u.config:{}}function LL(u){let f=X9(u),l=Array.isArray(f.nodes)?f.nodes:Array.isArray(u?.nodes)?u.nodes:[],r=new Map;for(let y of l){let _=String(y?.id||y?.nodeId||"");if(_)r.set(_,{...y,id:_})}let n=Y9(u),i=(y)=>{if(y&&!r.has(y))r.set(y,{id:y})};for(let y of S9(u))D$(y).forEach(i);for(let y of n)i(String(y?.from||y?.source||"")),i(String(y?.to||y?.target||""));return Array.from(r.values())}function Y9(u){let f=X9(u);return Array.isArray(f.edges)?f.edges:Array.isArray(u?.edges)?u.edges:[]}function S9(u){let f=X9(u);return Array.isArray(f.topologicalBatches)?f.topologicalBatches:Array.isArray(u?.topologicalBatches)?u.topologicalBatches:[]}function EY(u){let f=new Map;for(let l of u){let r=J8(l);if(r)f.set(r,l);let n=Array.isArray(l?.refs)?l.refs:[];for(let i of n){let y=J8(i);if(y)f.set(y,l)}}return f}function fL(u,f){let l=f.get(J8(u?.componentRef));if(l)return l;let r=J8({componentClass:u?.kind,id:u?.id});return r?f.get(r)||null:null}function lL(u,f){let l=wL(u,f);return String(l?.status||"pending")}function wL(u,f){return(Array.isArray(u?.nodes)?u.nodes:[]).find((r)=>r?.nodeId===f||r?.id===f)||null}function ZY(u){return u.reduce((f,l)=>{let r=String(l?.status||"unknown").toLowerCase();return f[r]=(f[r]||0)+1,f},{})}function OY(u){if(Array.isArray(u?.scorers))return u.scorers.filter(Du);if(Array.isArray(u?.summary?.scorers))return u.summary.scorers.filter(Du);if(Array.isArray(u?.artifact?.summary?.scorers))return u.artifact.summary.scorers.filter(Du);return[]}function HY(u){if(Du(u?.run))return u.run;if(Du(u?.runSummary))return u.runSummary;return null}function BY(u,f){if(!Du(u)&&!Du(f))return null;if(!Du(u))return f;if(!Du(f))return u;return{...u,...f,request:Du(u.request)||Du(f.request)?{...Du(u.request)?u.request:{},...Du(f.request)?f.request:{}}:f.request??u.request,artifact:Du(u.artifact)||Du(f.artifact)?{...Du(u.artifact)?u.artifact:{},...Du(f.artifact)?f.artifact:{}}:f.artifact??u.artifact,summary:Du(u.summary)||Du(f.summary)?{...Du(u.summary)?u.summary:{},...Du(f.summary)?f.summary:{}}:f.summary??u.summary}}function U8(u){let f=OY(u),l=f.find((c)=>Du(c?.score))||f[0]||null,r=Du(l?.score)?l.score:{},n=Number(r.passed),i=Number(r.total),y=Number(r.ratio),_=Number.isFinite(y)?y:Number.isFinite(n)&&Number.isFinite(i)&&i>0?n/i:null,$=_===null?null:Math.round(Math.max(0,Math.min(100,_<=1?_*100:_))),A=String(r.text||(Number.isFinite(n)&&Number.isFinite(i)?`${n}/${i}`:""));return{scorer:l,scorers:f,score:r,passed:Number.isFinite(n)?n:null,total:Number.isFinite(i)?i:null,percent:$,text:A}}function E9(u){let f=U8(u);return f.text||(f.scorers.length>0?String(f.scorer?.status||"pending"):"--")}function p9(u){let f=U8(u);if(f.total>0&&f.passed===f.total)return"succeeded";if(f.total>0&&f.passed>0)return"running";if(f.scorers.length>0)return"failed";return"pending"}function VY(u){return Array.isArray(u?.items)?u.items.filter(Du):[]}function DY({run:u}){let f=E9(u);return G("span",{className:`pipeline-score-badge ${p9(u)}`},`score ${f}`)}function XY({run:u,onRaw:f}){let r=U8(u).scorers;if(!u)return G(Ur,{title:"暂无评分",text:"选择一个 epoch 后会显示 scorer 结果。"});if(r.length===0)return G("div",{className:"pipeline-score-empty"},G("strong",null,"评分器等待中"),G("span",null,"DAG 完成后,Pipeline control backend 会把 scorer summary 追加到 run artifact,并通过 UniDesk 显示。"));return G("div",{className:"pipeline-score-board","data-testid":"pipeline-score-board"},r.map((n,i)=>{let y=U8({scorers:[n]}),_=VY(n),$=y.percent??0;return G("article",{key:`${n.scorerId||n.component||i}`,className:`pipeline-score-card ${p9({scorers:[n]})}`},G("div",{className:"pipeline-score-head"},G("div",null,G("span",null,n.scorerId||n.component||"scorer"),G("strong",null,y.text||n.status||"--")),G(Cn,{status:n.status||"unknown"},n.status||"unknown")),G("div",{className:"pipeline-score-meter","aria-label":`score ${$}%`},G("span",{style:{width:`${$}%`}})),G("div",{className:"pipeline-score-facts"},G("span",null,`${$}%`),G("span",null,n.component||"--"),G("span",null,n.applicationCheckoutRef||"--")),_.length>0?G("div",{className:"pipeline-score-items"},_.map((A)=>G("span",{key:`${A.id||A.filter}`,className:`pipeline-score-item ${String(A.status||"").toLowerCase()}`,title:`${A.filter||"--"} / ran=${A.ran??"?"}`},G("b",null,A.id||"--"),G("small",null,A.status||"--")))):G("p",{className:"muted paragraph"},"当前 scorer 尚未返回 item 级结果。"),n.error?G("p",{className:"pipeline-score-error"},JL(n.error,360)):null,G("div",{className:"panel-actions inline-actions"},G(gr,{title:`Scorer ${n.scorerId||i}`,data:n,onOpen:f,testId:"raw-pipeline-score"})))}))}function YY(u){let f=u.reduce((l,r)=>{let n=String(r?.componentClass||"unknown");return l[n]=(l[n]||0)+1,l},{});return Object.entries(f).map(([l,r])=>({name:l,count:Number(r)})).sort((l,r)=>r.count-l.count||l.name.localeCompare(r.name))}function D$(u){if(Array.isArray(u))return u.map((f)=>typeof f==="string"?f:String(f?.id||f?.nodeId||"")).filter(Boolean);if(Array.isArray(u?.nodes))return D$(u.nodes);if(Array.isArray(u?.nodeIds))return D$(u.nodeIds);return[]}function SY(u){return Du(u?.instanceInputs?.monitor)?u.instanceInputs.monitor:{}}function KL(u,f){if(String(u?.kind||"").toLowerCase()!=="procedure")return!1;let l=SY(u);if(u?.instanceInputs?.monitorMode===!0||l.enabled===!0)return!0;let r=WL(u?.componentRef);return String(f?.id||f?.config?.id||r||"").toLowerCase().includes("monitor")}function pY(u){return u.filter((f)=>KL(f)).map((f)=>String(f?.id||"")).filter(Boolean)}function mY(u,f){if(f.length===0)return u;let l=new Set(f),r=f.filter((n)=>u.includes(n));if(r.length===0)return u;return[...r,...u.filter((n)=>!l.has(n))]}function PY(u,f){if(f.length===0)return u;let l=new Set(f),r=f.filter((i)=>u.some((y)=>y.includes(i)));if(r.length===0)return u;let n=u.map((i)=>i.filter((y)=>!l.has(y))).filter((i)=>i.length>0);return[r,...n]}function MY(u,f,l){let n=S9(u).map(D$).filter((F)=>F.length>0);if(n.length>0)return n;let i=f.map((F)=>String(F?.id||"")).filter(Boolean),y=new Set(i),_=new Map(i.map((F)=>[F,0])),$=new Map(i.map((F)=>[F,[]]));for(let F of l){let U=String(F?.from||F?.source||""),Q=String(F?.to||F?.target||"");if(!y.has(U)||!y.has(Q))continue;$.get(U)?.push(Q),_.set(Q,(_.get(Q)||0)+1)}let A=new Map,c=i.filter((F)=>(_.get(F)||0)===0);for(let F of c)A.set(F,0);while(c.length>0){let F=c.shift(),U=(A.get(F)||0)+1;for(let Q of $.get(F)||[])if(_.set(Q,Math.max(0,(_.get(Q)||0)-1)),A.set(Q,Math.max(A.get(Q)||0,U)),(_.get(Q)||0)===0)c.push(Q)}i.forEach((F)=>{if(!A.has(F))A.set(F,0)});let j=Math.max(0,...Array.from(A.values()));return Array.from({length:j+1},(F,U)=>i.filter((Q)=>A.get(Q)===U)).filter((F)=>F.length>0)}function CY(u,f,l){let n=S9(u).map(D$).filter((_)=>_.length>0),i=n.length>0?n.flatMap((_)=>_):(()=>{let _=f.map((L)=>String(L?.id||"")).filter(Boolean),$=new Set(_),A=l.filter((L)=>String(L?.edgeType||"").toLowerCase()!=="rework"),c=new Map(_.map((L)=>[L,0])),j=new Map(_.map((L)=>[L,[]]));for(let L of A){let w=String(L?.from||L?.source||""),J=String(L?.to||L?.target||"");if(!$.has(w)||!$.has(J))continue;j.get(w)?.push(J),c.set(J,(c.get(J)||0)+1)}let F=new Map,U=_.filter((L)=>(c.get(L)||0)===0);for(let L of U)F.set(L,0);while(U.length>0){let L=U.shift(),w=(F.get(L)||0)+1;for(let J of j.get(L)||[])if(c.set(J,Math.max(0,(c.get(J)||0)-1)),F.set(J,Math.max(F.get(J)||0,w)),(c.get(J)||0)===0)U.push(J)}_.forEach((L)=>{if(!F.has(L))F.set(L,0)});let Q=Math.max(0,...Array.from(F.values()));return Array.from({length:Q+1},(L,w)=>_.filter((J)=>F.get(J)===w)).flatMap((L)=>L)})(),y=new Set(i);for(let _ of f){let $=String(_?.id||"");if(!$||y.has($))continue;i.push($),y.add($)}return mY(i,pY(f))}function T$(u){return`${u.source}->${u.target}-${u.index}`}function rL(u,f,l){let r=LL(u),n=Y9(u),i=EY(l),y=new Map(r.map((p)=>[String(p?.id||""),p])),_=r.filter((p)=>KL(p,fL(p,i))).map((p)=>String(p?.id||"")).filter(Boolean),$=PY(MY(u,r,n),_),A=[],c=new Map,j=330,F=122;$.forEach((p,O)=>{let m=p.length*122;p.forEach((X,v)=>{let T=y.get(X)||{id:X},S=fL(T,i),k=lL(f,X).toLowerCase(),I=String(T.kind||S?.componentClass||"node").toLowerCase(),b=WL(T.componentRef||S),o=String(S?.config?.version||S?.version||""),s=String(S?.config?.description||S?.description||""),x=v*122-Math.floor(m/2);c.set(X,{column:O,row:v,y:x}),A.push({id:X,type:"pipelineNode",position:{x:O*330,y:x},data:{exportLabel:{id:X,kind:I,componentRef:b,componentVersion:o,componentDescription:s,status:k},label:G("div",{className:"flow-node-label"},G("strong",null,X),G("span",null,I),G("code",{title:s||b},o?`${b}@${o}`:b),G(Cn,{status:k},k))},className:`pipeline-flow-node ${I} ${k}`})})});let U=n.flatMap((p,O)=>{let m=String(p?.from||p?.source||""),X=String(p?.to||p?.target||"");if(!y.has(m)||!y.has(X))return[];return[{source:m,target:X,index:O,condition:p?.condition,edgeType:p?.edgeType}]}),Q=U.reduce((p,O)=>p.set(O.source,(p.get(O.source)||0)+1),new Map),L=U.reduce((p,O)=>p.set(O.target,(p.get(O.target)||0)+1),new Map),w=U.reduce((p,O)=>{let m=`${O.source}->${O.target}`;return p.set(m,(p.get(m)||0)+1)},new Map),J=new Map,N=new Map,q=new Map,W=new Map,z=new Map,Z=new Map,H=U.reduce((p,O)=>{let m=c.get(O.source),X=c.get(O.target),v=(X?.column||0)-(m?.column||0);if(v<=0||String(O.edgeType||"").toLowerCase()==="rework"||v!==1)return p;let S=`${O.source}->column:${X?.column??""}`,k=p.get(S)||[];return k.push(O),p.set(S,k),p},new Map);for(let p of H.values()){if(p.length<2)continue;p.slice().sort((O,m)=>{let X=c.get(O.target),v=c.get(m.target);return(X?.y||0)-(v?.y||0)||O.index-m.index}).forEach((O,m,X)=>{Z.set(T$(O),{slot:m-(X.length-1)/2,count:X.length})})}[...U].sort((p,O)=>{let m=c.get(p.source),X=c.get(p.target),v=c.get(O.source),T=c.get(O.target),S=Math.abs((X?.column||0)-(m?.column||0))*330+Math.abs((X?.y||0)-(m?.y||0)),k=Math.abs((T?.column||0)-(v?.column||0))*330+Math.abs((T?.y||0)-(v?.y||0));return S-k||p.index-O.index}).forEach((p)=>{let O=c.get(p.source)||{column:0,row:0,y:0},m=c.get(p.target)||{column:0,row:0,y:0},X=m.column-O.column,v=Math.max(0,X),T=X<=0||String(p.edgeType||"").toLowerCase()==="rework",S=O.y-m.y,k=L.get(p.target)||1,I=Z.has(T$(p)),b=!T&&v<=1&&(I||k===1),o=z.get(p.target)||new Map;z.set(p.target,o);let s=B$.slice().sort((x,fu)=>{let $u=(qu)=>{let P=String(qu.side),e=0;if(T){if(P==="left")e+=86;if(P==="top")e+=m.y<=0?-22:12;if(P==="bottom")e+=m.y>=0?-22:12;if(Math.abs(m.y)<12&&P!=="left")e+=p.index%2===0?P==="top"?-6:6:P==="bottom"?-6:6;return e}if(b){if(P==="left")e-=I?72:44;if(P!=="left")e+=I?72:44;return e+Math.abs(S)*0.02}if(P==="left")e+=v<=1?0:24;if(P==="top")e+=S<-36?-18:42;if(P==="bottom")e+=S>36?-18:42;if(v<=1&&Math.abs(S)<=82&&P!=="left")e+=38;if(v>1&&P!=="left")e-=10;return e},tu=O.y-m.y,ju=tu!==0?tu:p.index%2===0?-1:1,Gu=(qu)=>{let P=o.get(qu.id)||0;return $u(qu)+P*64+nY(qu,o,ju)};return Gu(x)-Gu(fu)||String(x.id).localeCompare(String(fu.id))})[0];o.set(s.id,(o.get(s.id)||0)+1),W.set(T$(p),s)});let D=U.map((p)=>{let O=lL(f,p.target).toLowerCase(),m=`${p.source}->${p.target}`,X=J.get(p.source)||0,v=N.get(p.target)||0,T=q.get(m)||0;J.set(p.source,X+1),N.set(p.target,v+1),q.set(m,T+1);let S=X-((Q.get(p.source)||1)-1)/2,k=v-((L.get(p.target)||1)-1)/2,I=T-((w.get(m)||1)-1)/2,b=c.get(p.source),o=c.get(p.target),s=(o?.column||0)-(b?.column||0),x=Math.max(1,Math.abs(s)),fu=s<=0||String(p.edgeType||"").toLowerCase()==="rework",$u=Math.abs((o?.y||0)-(b?.y||0)),tu=Z.get(T$(p)),ju=!fu&&s===1&&(L.get(p.target)||0)>1,Gu=tu?tu.slot:I*2+S+k*0.45,qu=Gu===0?p.index%2===0?-1:1:Math.sign(Gu),P=W.get(T$(p))||B$[1],e=P.side==="top"?-1:P.side==="bottom"?1:qu,uu=fu||x>1||$u>96||Math.abs(Gu)>0.2||P.side!=="left",Wu=fu?118+x*18:22+x*16,g=P.side==="left"?0:28,Qu=uu?Math.max(-280,Math.min(280,e*Math.min(180,Wu+g+$u*0.22)+Gu*28)):0,Tu=Math.max(0,Math.min(Z$.length-1,Math.round(S+(Z$.length-1)/2))),Zu=Z$[Tu]||Z$[1],Xu=O==="succeeded"?"var(--accent-2)":O==="running"?"var(--accent)":O==="failed"?"var(--danger)":"rgba(129, 147, 159, 0.78)",uf=b?.column||0,_f=o?.column||0,Jf=Qu===0?0:Math.sign(Qu),Pf=fu?`feedback:${uf}->${_f}:${Jf}`:tu?`fanout:${uf}->${_f}:${p.source}`:ju?`fanin:${uf}->${_f}:${p.target}`:P.side!=="left"||x>1?`corridor:${uf}->${_f}:${P.side}:${Jf}:${Math.round(Math.abs(Qu)/56)}`:"";return{id:`${p.source}->${p.target}-${p.index}`,source:p.source,target:p.target,sourceHandle:Zu.id,targetHandle:P.id,type:"pipelineCurve",zIndex:12,animated:O==="running",data:{baseEdgeColor:Xu,laneOffset:Qu,routeMode:tu&&P.side==="left"?"direct-forward-left":"",targetSide:P.side,isFeedback:fu,overlapGroup:Pf},targetStatus:O}}),h=D.reduce((p,O)=>{let m=String(O.data?.overlapGroup||"");return m?p.set(m,(p.get(m)||0)+1):p},new Map),V=new Map,Y=D.map((p)=>{let O=String(p.targetStatus||"pending"),m={...p};delete m.targetStatus;let X=String(p.data?.overlapGroup||""),v=X?h.get(X)||0:0,T=v>1?V.get(X)||0:-1;if(v>1)V.set(X,T+1);let S=T>=0?bW[T%bW.length]:String(p.data.baseEdgeColor),k={stroke:S};if(p.data.isFeedback)k.strokeDasharray="9 7";return{...m,data:{...p.data,edgeColor:S,overlapSlot:T,overlapCount:v},style:k,markerEnd:{type:Dn.ArrowClosed,color:S},className:`pipeline-flow-edge ${O} ${p.data.isFeedback?"feedback":""} ${T>=0?"overlap-colored":""}`}});return{nodes:A,edges:Y}}function sl(u){return String(u??"").replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function nL(u){let f=String(u||"");if(f.includes("--accent-2"))return"#4eb7a8";if(f.includes("--accent"))return"#d7a13a";if(f.includes("--danger"))return"#cf6a54";return f.startsWith("#")?f:"#81939f"}function Q8(u){return`arrow-${u.replace(/[^a-zA-Z0-9_-]+/g,"")}`}function GL(u,f="pipeline"){return String(u||f).replace(/[^a-zA-Z0-9_-]+/g,"-").replace(/^-|-$/g,"")||f}function iL(u,f){let l=u.position.x,r=u.position.y,n=B$.find((i)=>i.id===f);if(n?.side==="top")return{x:l+jy*IW(n.style?.left,0.5),y:r,position:wu.Top};if(n?.side==="bottom")return{x:l+jy*IW(n.style?.left,0.5),y:r+Fy,position:wu.Bottom};return{x:l,y:r+Fy/2,position:wu.Left}}function RY(u){return{x:u.position.x+jy,y:u.position.y+Fy/2}}function xY(u,f){let l=Math.min(...u.nodes.map((L)=>L.position.x),0)-220,r=Math.min(...u.nodes.map((L)=>L.position.y),0)-220,n=Math.max(...u.nodes.map((L)=>L.position.x+jy),1)+220,i=Math.max(...u.nodes.map((L)=>L.position.y+Fy),1)+220,y=Math.ceil(n-l),_=Math.ceil(i-r),$=new Map(u.nodes.map((L)=>[L.id,L])),A=u.edges.map((L)=>nL(L.data?.edgeColor||L.style?.stroke)),j=Array.from(new Set(["#4eb7a8","#d7a13a","#cf6a54","#81939f",...A])).map((L)=>``).join(""),F=u.edges.flatMap((L)=>{let w=$.get(L.source),J=$.get(L.target);if(!w||!J)return[];let N=RY(w),q=iL(J,String(L.targetHandle||"in-left")),W=cL(N.x,N.y,q.x,q.y,q.position,Number(L.data?.laneOffset||0),String(L.data?.routeMode||"")),z=nL(L.data?.edgeColor||L.style?.stroke),Z=L.data?.isFeedback?' stroke-dasharray="9 7"':"";return``}).join(` +`),U=u.nodes.map((L)=>{let w=L.data?.exportLabel||{},J=String(w.status||"pending").toLowerCase(),N=J==="succeeded"?"#4eb7a8":J==="running"?"#d7a13a":J==="failed"?"#cf6a54":"#81939f",q=L.position.x,W=L.position.y,z=B$.map((Z)=>{let H=iL(L,Z.id);if(Z.side==="top"||Z.side==="bottom")return``;return``}).join(` `);return` ${z} - ${Il(L.id||w.id)} - ${Il(L.kind||"node")} - ${Il(L.componentRef||"--")} - ${Il(J)} + ${sl(w.id||L.id)} + ${sl(w.kind||"node")} + ${sl(w.componentRef||"--")} + ${sl(J)} `}).join(` `);return{svg:` ${j} - ${Il(f)} + ${sl(f)} ${U}${F} - `,width:y,height:_}}function XY(u){let f=String(u||"").toLowerCase();if(f==="succeeded"||f==="completed")return"#4eb7a8";if(f==="failed")return"#cf6a54";if(_w(f))return"#69aee8";return"#d7a13a"}function YY(u){let f=String(u?.kind||""),l=String(u?.tone||u?.status||"").toLowerCase();if(f==="prompt"&&l==="initial")return"#d7a13a";if(f==="prompt"&&l==="monitor")return"#69aee8";if(f==="prompt")return"#4eb7a8";if(l==="modify")return"#e0b95a";if(l==="approve"||l==="guide"||l==="monitor")return"#4eb7a8";if(l==="restart"||l==="redo")return"#d7a13a";if(l==="ignored")return"#81939f";if(l==="webui")return"#69aee8";if(l==="cli")return"#d7a13a";return"#a7bac5"}function fw(u){let f=String(u?.sourceKind||"").toLowerCase(),l=String(u?.action||"").toLowerCase(),r=String(u?.status||"").toLowerCase();if(l==="observe"||r==="observation"||f==="monitor")return"#4eb7a8";if(f==="webui")return"#69aee8";if(f==="cli")return"#d7a13a";if(r.includes("ignored"))return"#81939f";return"#8aa0ad"}function SY(u,f,l){let r=YY(u),n=String(u?.kind||"");if(n==="control-source")return``;if(n==="control-target"){let y=String(u?.tone||"").toLowerCase()==="approve"?"rgba(78,183,168,0.22)":"#081118";return``}return``}function mY(u){let f=Vu(u.visibleNodeIds).map((T)=>String(T||"")).filter(Boolean),l=Vu(u.intervals).filter(Du),r=Vu(u.markers).filter(Du),n=Vu(u.arrows).filter(Du),i=Vu(u.ticks).filter(Du),y=Du(u.bounds)?u.bounds:{},_=Du(u.backendLayout)?u.backendLayout:null,$=Math.max(240,Math.round(Number(u.chartHeight||360))),c=Math.max(t0,108),A=128,j=24,F=58,U=56,Q=128+Math.max(1,f.length)*c,w=Math.max(760,Q+48),L=114+$+24,J=24,N=58,q=114,W=(T)=>152+T*c,z=(T)=>W(T)+c/2,Z=Vu(u.meta).map((T)=>String(T||"")).filter(Boolean).slice(0,4).join(" · "),H=new Map(r.map((T)=>[String(T.id||""),T])),D=Array.from(new Set(["#4eb7a8","#69aee8","#d7a13a","#cf6a54","#8aa0ad",...n.map(fw)])).map((T)=>``).join(""),h=i.map((T)=>{let S=114+Ew(T,y,$,_);return` + `,width:y,height:_}}function hY(u){let f=String(u||"").toLowerCase();if(f==="succeeded"||f==="completed")return"#4eb7a8";if(f==="failed")return"#cf6a54";if(jL(f))return"#69aee8";return"#d7a13a"}function bY(u){let f=String(u?.kind||""),l=String(u?.tone||u?.status||"").toLowerCase();if(f==="prompt"&&l==="initial")return"#d7a13a";if(f==="prompt"&&l==="monitor")return"#69aee8";if(f==="prompt")return"#4eb7a8";if(l==="modify")return"#e0b95a";if(l==="approve"||l==="guide"||l==="monitor")return"#4eb7a8";if(l==="restart"||l==="redo")return"#d7a13a";if(l==="ignored")return"#81939f";if(l==="webui")return"#69aee8";if(l==="cli")return"#d7a13a";return"#a7bac5"}function yL(u){let f=String(u?.sourceKind||"").toLowerCase(),l=String(u?.action||"").toLowerCase(),r=String(u?.status||"").toLowerCase();if(l==="observe"||r==="observation"||f==="monitor")return"#4eb7a8";if(f==="webui")return"#69aee8";if(f==="cli")return"#d7a13a";if(r.includes("ignored"))return"#81939f";return"#8aa0ad"}function vY(u,f,l){let r=bY(u),n=String(u?.kind||"");if(n==="control-source")return``;if(n==="control-target"){let y=String(u?.tone||"").toLowerCase()==="approve"?"rgba(78,183,168,0.22)":"#081118";return``}return``}function kY(u){let f=Vu(u.visibleNodeIds).map((T)=>String(T||"")).filter(Boolean),l=Vu(u.intervals).filter(Du),r=Vu(u.markers).filter(Du),n=Vu(u.arrows).filter(Du),i=Vu(u.ticks).filter(Du),y=Du(u.bounds)?u.bounds:{},_=Du(u.backendLayout)?u.backendLayout:null,$=Math.max(240,Math.round(Number(u.chartHeight||360))),A=Math.max(A0,108),c=128,j=24,F=58,U=56,Q=128+Math.max(1,f.length)*A,L=Math.max(760,Q+48),w=114+$+24,J=24,N=58,q=114,W=(T)=>152+T*A,z=(T)=>W(T)+A/2,Z=Vu(u.meta).map((T)=>String(T||"")).filter(Boolean).slice(0,4).join(" · "),H=new Map(r.map((T)=>[String(T.id||""),T])),D=Array.from(new Set(["#4eb7a8","#69aee8","#d7a13a","#cf6a54","#8aa0ad",...n.map(yL)])).map((T)=>``).join(""),h=i.map((T)=>{let S=114+VL(T,y,$,_);return` - ${Il(Nu(T.ms))} - +${Il(Er(Number(T.offsetMs??Number(T.ms)-Number(y.startMs))))} + ${sl(Nu(T.ms))} + +${sl(Hr(Number(T.offsetMs??Number(T.ms)-Number(y.startMs))))} `}).join(` -`),B=['','TIME',...f.map((T,S)=>{let k=W(S),I=T.length>18?`${T.slice(0,16)}…`:T;return` - - ${Il(I)} - node ${S+1} +`),V=['','TIME',...f.map((T,S)=>{let k=W(S),I=T.length>18?`${T.slice(0,16)}…`:T;return` + + ${sl(I)} + node ${S+1} `})].join(` -`),X=f.map((T,S)=>{return``}).join(` -`),m=l.map((T)=>{let S=f.indexOf(String(T.nodeId||""));if(S<0)return"";let k=114+N8(T,y,$,_),I=Math.max(2,Tw(T,y,$,_)),b=XY(T.status),o=z(S)-3.5,s=T.live?``:"",x=I>=28?`${Il(String(T.status||"working"))} - ${Il(Er(T.durationMs))}`:"";return` +`),Y=f.map((T,S)=>{return``}).join(` +`),p=l.map((T)=>{let S=f.indexOf(String(T.nodeId||""));if(S<0)return"";let k=114+N8(T,y,$,_),I=Math.max(2,BL(T,y,$,_)),b=hY(T.status),o=z(S)-3.5,s=T.live?``:"",x=I>=28?`${sl(String(T.status||"working"))} + ${sl(Hr(T.durationMs))}`:"";return` ${s} ${x} `}).join(` -`),O=r.map((T)=>{let S=f.indexOf(String(T.nodeId||""));if(S<0)return"";let k=114+cr(T,y,$,_);return SY(T,z(S),k)}).join(` -`),p=n.map((T)=>{let S=H.get(String(T.targetMarkerId||""));if(!S)return"";let k=H.get(String(T.sourceMarkerId||"")),I=String(k?.nodeId||T.sourceNodeId||""),b=String(S.nodeId||T.targetNodeId||""),o=f.indexOf(I),s=f.indexOf(b);if(o<0||s<0)return"";let x=z(o)-24-128,fu=z(s)-24-128,$u=Jy(_)?Bf(T.sourceY??T.y1)??(k?cr(k,y,$,_):cr(S,y,$,_)):k?cr(k,y,$,_):cr(S,y,$,_),tu=Jy(_)?Bf(T.targetY??T.y2)??cr(S,y,$,_):cr(S,y,$,_),ju=fw(T),Gu=String(T.action||"").toLowerCase()==="observe"?"3 4":"6 5",qu=Il(Zw(x,$u,fu,tu));return` +`),O=r.map((T)=>{let S=f.indexOf(String(T.nodeId||""));if(S<0)return"";let k=114+Jr(T,y,$,_);return vY(T,z(S),k)}).join(` +`),m=n.map((T)=>{let S=H.get(String(T.targetMarkerId||""));if(!S)return"";let k=H.get(String(T.sourceMarkerId||"")),I=String(k?.nodeId||T.sourceNodeId||""),b=String(S.nodeId||T.targetNodeId||""),o=f.indexOf(I),s=f.indexOf(b);if(o<0||s<0)return"";let x=z(o)-24-128,fu=z(s)-24-128,$u=Jy(_)?Vf(T.sourceY??T.y1)??(k?Jr(k,y,$,_):Jr(S,y,$,_)):k?Jr(k,y,$,_):Jr(S,y,$,_),tu=Jy(_)?Vf(T.targetY??T.y2)??Jr(S,y,$,_):Jr(S,y,$,_),ju=yL(T),Gu=String(T.action||"").toLowerCase()==="observe"?"3 4":"6 5",qu=sl(DL(x,$u,fu,tu));return` `}).join(` -`),Y=f.length===0?'No visible Gantt nodes':"";return{svg:` +`),X=f.length===0?'No visible Gantt nodes':"";return{svg:` ${D} - ${Il(u.title||"Pipeline Epoch Gantt")} - ${Il(Z)} - ${B} + ${sl(u.title||"Pipeline Epoch Gantt")} + ${sl(Z)} + ${V} - ${X} - ${h} - ${m} - ${p} - ${O} ${Y} - `,width:w,height:L}}function q8(u,f){let l=URL.createObjectURL(u),r=document.createElement("a");r.href=l,r.download=f,r.click(),setTimeout(()=>URL.revokeObjectURL(l),1000)}async function Ww(u,f){let l=Nw(f,"pipeline"),{svg:r,width:n,height:i}=DY(u,f),y=new Blob([r],{type:"image/svg+xml;charset=utf-8"}),_=URL.createObjectURL(y);try{let $=new Image;await new Promise((F,U)=>{$.onload=()=>F(),$.onerror=()=>U(Error("svg image load failed")),$.src=_});let c=document.createElement("canvas");c.width=n,c.height=i;let A=c.getContext("2d");if(!A)throw Error("canvas unavailable");A.drawImage($,0,0);let j=await new Promise((F)=>c.toBlob(F,"image/png"));if(!j)throw Error("png export failed");q8(j,`${l}.png`)}catch{q8(y,`${l}.svg`)}finally{URL.revokeObjectURL(_)}}async function pY(u){let f=Nw(String(u?.title||"pipeline-gantt"),"pipeline-gantt"),{svg:l,width:r,height:n}=mY(u),i=new Blob([l],{type:"image/svg+xml;charset=utf-8"}),y=URL.createObjectURL(i);try{let _=new Image;await new Promise((j,F)=>{_.onload=()=>j(),_.onerror=()=>F(Error("gantt svg image load failed")),_.src=y});let $=document.createElement("canvas");$.width=r,$.height=n;let c=$.getContext("2d");if(!c)throw Error("canvas unavailable");c.drawImage(_,0,0);let A=await new Promise((j)=>$.toBlob(j,"image/png"));if(!A)throw Error("gantt png export failed");q8(A,`${f}.png`)}catch{q8(i,`${f}.svg`)}finally{URL.revokeObjectURL(y)}}async function PY(u){for(let f of u){if(f.flow.nodes.length===0)continue;await Ww(f.flow,f.title),await new Promise((l)=>setTimeout(l,750))}}function lw(u,f){return u.find((l)=>String(l?.pipelineId||"")===f)||null}function rw(u){return ku(u?.startedAt)??ku(u?.artifact?.startedAt)??ku(u?.request?.createdAt)??ku(u?.updatedAt)??0}function MY(u,f){return u.filter((l)=>String(l?.pipelineId||"")===f).slice().sort((l,r)=>rw(l)-rw(r)||String(l?.runId||"").localeCompare(String(r?.runId||"")))}function T9(u,f){let l=String(f?.runId||""),r=u.findIndex((y)=>String(y?.runId||"")===l),n=r>=0?r+1:u.length,i=String(f?.status||"--");return`Epoch ${n} / ${l||"--"} / ${i}`}function Zr(u){return String(u?.procedureRunId||u?.runId||"")}function L8(u,f){let l=String(u?.nodeId||u?.request?.nodeId||"");if(l)return l;let r=Zr(u),n=`${f}__`;if(r.startsWith(n))return r.slice(n.length).replace(/__\d+$/u,"");return""}function $8(u,f){let l=Du(u?.artifact)?u.artifact:{},r=Du(u?.request)?u.request:{};return Y$(u?.startedAt,l.startedAt,r.createdAt,r.startedAt,u?.createdAt,u?.updatedAt,f?.startedAt,f?.request?.createdAt)}function t8(u,f){let l=String(u?.status?.status||u?.artifact?.status||u?.status||"").toLowerCase(),r=Du(u?.artifact)?u.artifact:{},n=H9(l);return Y$(u?.finishedAt,r.finishedAt,u?.completedAt,n?u?.updatedAt:void 0,n?r.updatedAt:void 0,n?f?.updatedAt:void 0)}function ww(u,f,l=Date.now()){let r=String(u?.runId||""),n=new Set(f.map((i)=>String(i?.id||"")).filter(Boolean));return Vu(u?.procedureRuns).flatMap((i)=>{let y=L8(i,r);if(!y)return[];let _=String(i?.status?.status||i?.artifact?.status||i?.status||"unknown").toLowerCase(),$=$8(i,u),c=ku($);if(c===null)return[];let A=t8(i,u),j=ku(A)??(H9(_)?ku(i?.updatedAt)??c+1000:l),F=Math.max(c+1000,j);return[{nodeId:y,knownNode:n.has(y),procedureRunId:Zr(i),status:_,startMs:c,endMs:F,startedAt:V$(c),finishedAt:V$(F),durationMs:F-c,runId:r,raw:i}]}).sort((i,y)=>i.startMs-y.startMs||i.endMs-y.endMs||i.nodeId.localeCompare(y.nodeId))}function CY(u,f,l=[]){let r=f.map((A)=>Number(A.startMs)).filter(Number.isFinite),n=f.map((A)=>Number(A.endMs)).filter(Number.isFinite);for(let A of l){let j=Bf(A?.eventMs??A?.ms);if(j!==null)r.push(j),n.push(j)}let i=ku(u?.startedAt)??ku(u?.artifact?.startedAt)??ku(u?.request?.createdAt),y=ku(u?.finishedAt)??ku(u?.artifact?.finishedAt)??ku(u?.updatedAt);if(i!==null)r.push(i);if(y!==null)n.push(y);let _=Date.now(),$=r.length>0?Math.min(...r):_-60000,c=Math.max($+60000,n.length>0?Math.max(...n):_);return{startMs:$,endMs:c,durationMs:c-$}}var c8=12,Lw=20,E9=100,RY=!1;function hn(u){let f=Number(u);if(!Number.isFinite(f))return 0;return Math.max(0,Math.min(100,Math.round(f*100)/100))}function xY(u){let f=Math.max(c8,Number(u||c8)),l=Math.log(f/c8)/Math.log(Lw);return hn(l*100)}var X$=xY(E9);function S9(u){let f=hn(u)/100,l=c8*Math.pow(Lw,f),r=f<0.24?"全局":f<0.64?"均衡":"细节";return{value:hn(f*100),pxPerMinute:l,label:r}}function N9(u){let f=Math.round(Number(u));return Math.abs(f-E9)<=1?E9:f}function hY(u,f=X$){let l=Math.max(1,Number(u.durationMs||0)/60000),r=S9(f);return Math.round(Math.max(360,Math.min(7200,l*Number(r.pxPerMinute||48))))}function bY(u,f=7){let l=Math.max(1,Number(u.endMs||0)-Number(u.startMs||0));return Array.from({length:f},(r,n)=>{let i=f===1?0:n/(f-1);return{ms:Number(u.startMs)+l*i,percent:i*100}})}function vY(u,f){let l=Math.max(1,Number(f.endMs)-Number(f.startMs));return Math.max(0,Math.min(100,(u-Number(f.startMs))/l*100))}function Bf(u){let f=Number(u);return Number.isFinite(f)?f:null}function m9(u){return _w(u?.status)&&!H9(u?.status)}function Kw(u,f,l,r){let n=Math.max(1,l-f),i=Math.max(0,Math.min(1,(u-f)/n));return Number((i*r).toFixed(3))}function nw(u,f){if(!f)return null;let l=Bf(f?.startMs),r=Bf(f?.endMs),n=Bf(f?.chartHeight);if(l===null||r===null||n===null)return null;return Kw(u,l,r,n)}function Gw(u,f){let l=Bf(u?.rawStartMs??u?.startMs)??Bf(u?.startMs)??f,r=Bf(u?.endMs)??l+1000;if(!m9(u))return Math.max(l+1000,r);return Math.max(l+1000,r,f)}function kY(u,f,l,r){let n=Bf(u?.startMs)??r-60000,i=Bf(u?.endMs)??r,y=l.reduce((Q,w)=>Math.max(Q,Gw(w,r)),i),_=Math.max(n+60000,i,y),$=Math.max(1,_-n),c={startMs:n,endMs:_,durationMs:$},A=hY(c,f),j=S9(f),F=Math.max(5,Math.min(18,Math.round(A/150))),U=bY(c,F).map((Q)=>{let w=Number(Q.ms),L=Kw(w,n,_,A);return{...Q,y:L,timestamp:V$(w),offsetMs:w-n}});return{source:"frontend-y",startMs:n,endMs:_,durationMs:$,chartHeight:A,scale:hn(f),normalizedScale:Number((hn(f)/100).toFixed(3)),pxPerMinute:Number(Number(j.pxPerMinute||0).toFixed(3)),ticks:U}}function IY(u,f,l){if(!m9(u))return u;let r=Bf(u?.rawStartMs??u?.startMs)??Bf(u?.startMs)??l,n=Gw(u,l),i=nw(r,f),y=nw(n,f),_=Bf(i??u?.y1??u?.startY)??0,$=Bf(y??u?.y2??u?.endY)??_+10,c=Math.max(24,$-_);return{...u,live:!0,startMs:r,endMs:n,durationMs:Math.max(1000,n-r),finishedAt:V$(n),y1:_,y2:$,startY:_,endY:$,height:c}}function p9(u,f,l){return vY(u,f)/100*l}function Jy(u){return Boolean(u&&String(u?.source||"")!=="frontend-y")}function zw(u,f,l,r,n){if(Jy(r))for(let y of n){let _=Bf(u?.[y]);if(_!==null)return _}let i=Bf(u?.ms??u?.eventMs??u?.startMs);return p9(i??Number(f.startMs),f,l)}function N8(u,f,l,r){return zw(u,f,l,r,["y1","startY"])}function Z9(u,f,l,r){if(Jy(r)){let i=Bf(u?.y2??u?.endY);if(i!==null)return i}let n=Bf(u?.endMs)??Number(f.endMs);return p9(n,f,l)}function Tw(u,f,l,r){if(Jy(r)){let i=Bf(u?.height);if(i!==null)return Math.max(1,i)}let n=u?.live?24:10;return Math.max(n,Z9(u,f,l,r)-N8(u,f,l,r))}function cr(u,f,l,r){return zw(u,f,l,r,["y","timeAxisY"])}function Ew(u,f,l,r){if(Jy(r)||String(r?.source||"")==="frontend-y"){let y=Bf(u?.y);if(y!==null)return y}let n=Bf(u?.percent);if(n!==null)return n/100*l;let i=Bf(u?.ms)??Number(f.startMs);return p9(i,f,l)}function gY(u){let f=String(u?.promptEvent||u?.raw?.promptEvent||u?.event||"").toLowerCase();if(!["node-long-running-observation","node-finished"].includes(f))return"";let l=String(u?.sourceNodeId||u?.raw?.sourceNodeId||u?.raw?.detail?.nodeId||""),r=String(u?.nodeId||u?.targetNodeId||"");return l&&l!==r?l:""}function sY(u,f){let l=new Set(f.map((n)=>[String(n.sourceNodeId||""),String(n.targetNodeId||""),String(n.targetMarkerId||""),String(n.action||"")].join(":"))),r=[...f];for(let n of u){let i=gY(n),y=String(n?.nodeId||""),_=String(n?.id||"");if(!i||!y||!_)continue;let $=[i,y,_,"observe"].join(":");if(l.has($))continue;l.add($),r.push({id:`observation-arrow:${_}:${i}:${y}`,commandId:String(n?.commandId||n?.eventId||_),sourceNodeId:i,targetNodeId:y,sourceMarkerId:"",targetMarkerId:_,sourceKind:"monitor",action:"observe",status:"observation"})}return{markers:u,arrows:r}}function aY(u){let f=vr(u),l=String(u?.promptEvent||"");if(f==="initial-prompt-delivered")return"initial";if(l==="node-finished"||l==="node-long-running-observation"||l.startsWith("monitor-"))return"monitor";if(f==="monitor-prompt-delivered"||String(u?.sourceKind||"").toLowerCase()==="monitor")return"monitor";return"append"}function oY(u){return Vu(u?.tags||u?.raw?.tags).map((f)=>String(f||"")).filter(Boolean)}function dY(u){let f=vr(u),l=String(u?.promptEvent||"");if(f==="initial-prompt-delivered")return"初始 prompt";if(l==="node-long-running-observation")return"长任务观察";if(l==="node-finished")return oY(u).includes("monitor.audit")?"节点完成 / OA 审核":"节点完成";if(l==="monitor-interval")return"Monitor observation";if(l==="monitor-start")return"Monitor start";if(l==="monitor-stop")return"Monitor stop";if(f==="monitor-prompt-delivered")return"Monitor prompt";if(f==="append-prompt-queued")return"追加 prompt 已排队";return"追加 prompt"}function iw(u){let f=vr(u);if(f==="control-command-applied")return 3;if(f==="control-command-ignored")return 2;if(f==="control-command-queued")return 1;return 0}function eY(u,f){let l=String(u?.commandId||"");if(l)return`command:${l}`;return["control-event",Ay(u)||Y$(u?.createdAt,u?.timestamp)||`index-${f}`,String(u?.sourceKind||""),String(u?.sourceNodeId||""),String(u?.targetNodeId||""),C1(u)].join(":")}function uS(u){return G9([u?.targetNodeId,...Vu(u?.resetNodeIds)])}function fS(u,f){let l=H$(u),r=vr(u),n=String(u?.targetNodeId||""),i=Boolean(n)&&f!==n;if(r==="control-command-applied")return i?`${l} 波及`:`${l} 生效`;if(r==="control-command-ignored")return`${l} 忽略`;if(r==="control-command-queued")return`${l} 已发起`;return i?`${l} 波及`:l}function lS(u){if(vr(u)==="control-command-ignored")return"ignored";let l=C1(u);if(l==="restart"||l==="redo")return"restart";if(l==="modify")return"modify";if(l==="approve")return"approve";if(l==="guide")return"guide";return"pending"}function rS(u){let f=String(u?.sourceKind||"").toLowerCase();if(f==="monitor")return"monitor";if(f==="webui")return"webui";if(f==="cli")return"cli";return"system"}function nS(u,f,l,r){let n=u.filter((c)=>String(c.nodeId||"")===f).sort((c,A)=>Number(c.startMs)-Number(A.startMs)),i=n.find((c)=>l>=Number(c.startMs)-1000&&l<=Number(c.endMs)+1000);if(i)return{ms:l,onInterval:!0,snapReason:"inside-interval",procedureRunId:String(i.procedureRunId||"")};let y=C1(r),_=n.slice().reverse().find((c)=>Number(c.endMs)<=l+1000);if(_&&y==="approve")return{ms:Number(_.endMs),onInterval:!0,snapReason:"previous-interval-end",procedureRunId:String(_.procedureRunId||"")};let $=n.find((c)=>Number(c.startMs)>=l-1000);if($&&["guide","modify","restart","redo"].includes(y))return{ms:Number($.startMs),onInterval:!0,snapReason:"next-interval-start",procedureRunId:String($.procedureRunId||"")};return{ms:l,onInterval:!1,snapReason:"event-time",procedureRunId:String(r?.procedureRunId||"")}}function Zw(u,f,l,r){let n=Math.hypot(l-u,r-f),i=n>RW?RW:0,y=i>0?l-(l-u)/n*i:l,_=i>0?r-(r-f)/n*i:r,$=y-u,c=Math.max(16,Math.min(42,Math.abs($)*0.45+12)),A=$===0?1:Math.sign($);return`M ${u},${f} C ${u+A*c},${f} ${y-A*c},${_} ${y},${_}`}function iS(u,f){let l=String(u?.runId||f?.runId||""),r=ww({...Du(f)?f:{},...Du(u)?u:{},runId:l,procedureRuns:Vu(u?.procedureRuns).length>0?u.procedureRuns:f?.procedureRuns},[]),n=[],i=[],y=[],_=new Set,$=new Map,c=(F,U)=>{if(!F.nodeId||!Number.isFinite(Number(F.ms)))return;if(_.has(F.id))return;_.add(F.id),U.push(F)};for(let F of Vu(u?.procedureRuns)){let U=L8(F,l),Q=Zr(F);if(!U)continue;for(let w of Vu(F?.attempts)){let L=w8(w);for(let J of K9(w?.controlEventRecords)){let N=vr(J);if(!["initial-prompt-delivered","append-prompt-delivered","monitor-prompt-delivered"].includes(N))continue;let q=Ay(J),W=ku(q);if(W===null)continue;let z=String(J?.eventId||"");c({id:`prompt:${z||`${Q}:${L}:${N}:${W}`}`,runId:l,nodeId:U,procedureRunId:Q,attempt:L,kind:"prompt",tone:aY(J),status:"delivered",label:dY(J),ms:W,timestampIso:q,sourceKind:String(J?.sourceKind||""),sourceNodeId:String(J?.sourceNodeId||""),targetNodeId:U,action:"",eventId:z,commandId:String(J?.commandId||""),raw:J},n)}}}let A=new Map;K9(u?.controlEvents).forEach((F,U)=>{let Q=eY(F,U),w=A.get(Q)||{key:Q,events:[]};w.events.push(F),A.set(Q,w)});for(let F of A.values()){let U=Vu(F.events).slice().sort((B,X)=>iw(X)-iw(B)),Q=Vu(F.events).find((B)=>vr(B)==="control-command-queued")||null,w=U[0]||Q;if(!Q&&!w)continue;let L=String(Q?.sourceNodeId||w?.sourceNodeId||""),J=String(Q?.sourceKind||w?.sourceKind||""),N=Ay(Q)||Ay(w)||Y$(Q?.createdAt,w?.createdAt),q=ku(N),W=String(w?.commandId||Q?.commandId||F.key),z=(vr(w)||"control-command-queued").replace(/^control-command-/u,""),Z="";if(L&&q!==null)Z=`control-source:${W}:${L}`,$.set(W,Z),c({id:Z,runId:l,nodeId:L,procedureRunId:String(Q?.procedureRunId||w?.procedureRunId||""),attempt:"",kind:"control-source",tone:rS(Q||w),status:z,label:`${H$(Q||w)} 发起`,ms:q,timestampIso:N,action:C1(Q||w),sourceKind:J,sourceNodeId:L,targetNodeId:String(w?.targetNodeId||Q?.targetNodeId||""),commandId:W,raw:Q||w},i);let H=w||Q,E=Ay(H)||N,D=ku(E);if(D===null)continue;let h=uS(H);for(let B of h){let X=nS(r,B,D,H),m=`control-target:${W}:${B}`;if(c({id:m,runId:l,nodeId:B,procedureRunId:X.procedureRunId,attempt:"",kind:"control-target",tone:lS(H),status:z,label:fS(H,B),ms:X.ms,eventMs:D,onInterval:X.onInterval,snapReason:X.snapReason,snapped:Number(X.ms)!==D,timestampIso:E,renderedTimestampIso:V$(Number(X.ms)),action:C1(H),sourceKind:J,sourceNodeId:L,targetNodeId:B,commandId:W,raw:H},i),Z&&L&&L!==B)y.push({id:`control-arrow:${W}:${L}:${B}`,commandId:W,sourceNodeId:L,targetNodeId:B,sourceMarkerId:Z,targetMarkerId:m,sourceKind:J,action:C1(H),status:z})}}let j=[...n,...i].sort((F,U)=>Number(F.ms)-Number(U.ms)||String(F.nodeId).localeCompare(String(U.nodeId))||String(F.id).localeCompare(String(U.id)));return{...sY(j,y),sourceMarkerByCommand:$}}function yS({details:u,selectedNodeId:f,selectedNodeRuntime:l,control:r,onRaw:n}){if(!u)return G("span",{className:"muted"},"点击“抓取过程”读取 node 运行材料;主界面只显示结构化摘要,完整内容需点开原始 JSON。");let i=Vu(u.procedureRuns),y=i.at(-1)||{},_=Vu(y.attempts),$=_.at(-1)||{},c=Vu(y.workerLogTail),A=Vu($.controlEventsTail),j=Vu($.controlPromptsTail),F=Vu($.monitorPromptsTail),U=J9(A),Q=J9(j),w=J9(F),L=$.opencodeMessages||{};return G("div",{className:"pipeline-evidence-list compact"},G(Tr,{title:"Node runtime",subtitle:f||"--",facts:[`status ${l?.status||"pending"}`,`attempts ${l?.attempts??_.length}`,`procedure ${l?.currentProcedureRunId||Zr(y)||"--"}`,r.fetchedAt?`fetched ${$f(r.fetchedAt)}`:"not fetched"],data:u.node||u,onRaw:n,testId:"raw-pipeline-node-runtime"}),G(Tr,{title:"Procedure runs",subtitle:`${i.length} groups`,facts:[`latest ${y.status?.status||y.status||"--"}`,`steps ${Vu(y.recentSteps).length}`,`duration ${Er(ku(y.finishedAt)&&ku(y.startedAt)?Number(ku(y.finishedAt))-Number(ku(y.startedAt)):y.durationMs)}`],data:i,onRaw:n,testId:"raw-pipeline-node-procedures"}),G(Tr,{title:"OpenCode messages",subtitle:String(L.exists?"available":"not indexed"),facts:[`messages ${j8(L.messageCount)}`,`size ${j8(L.size)}`,`updated ${Nu(L.updatedAt)}`],data:L,onRaw:n,testId:"raw-pipeline-node-messages"}),G(Tr,{title:"Control prompts",subtitle:"manual / monitor append queues",facts:[`manual tail ${Q.total}`,`monitor tail ${w.total}`,`last ${Nu(O9(Q.lastAt,w.lastAt))}`],data:{controlPromptsTail:j,monitorPromptsTail:F},onRaw:n,testId:"raw-pipeline-node-prompts"}),G(Tr,{title:"Control events",subtitle:U.eventKinds.length>0?U.eventKinds.join(", "):"event tail",facts:[`tail ${U.total}`,`parsed ${U.parsed}`,`last ${Nu(U.lastAt)}`],data:A,onRaw:n,testId:"raw-pipeline-node-events"}),G(Tr,{title:"Worker log",subtitle:"tail is hidden on main canvas",facts:[`tail ${c.length} lines`,"raw only via button",`procedure ${Zr(y)||"--"}`],data:c,onRaw:n,testId:"raw-pipeline-node-worker-log"}))}function _S({activeRun:u,onRaw:f}){if(!u)return G(Ar,{title:"暂无运行材料",text:"没有 Pipeline epoch 时不会展示运行材料索引。"});let l=Vu(u.nodes),r=Vu(u.procedureRuns),n=Vu(u.submissions),i=Vu(u.workerLogTail),y=bW(l),_=bW(r),$=r.filter((A)=>String(A?.status||"").toLowerCase()==="failed"),c=O9(...r.flatMap((A)=>[A.updatedAt,A.finishedAt,A.startedAt]));return G("div",{className:"pipeline-evidence-list"},G(Tr,{title:"Epoch overview",subtitle:u.runId||"--",facts:[`pipeline ${u.pipelineId||"--"}`,`status ${u.status||"--"}`,`started ${Nu(u.startedAt)}`,`updated ${Nu(u.updatedAt)}`],data:u,onRaw:f,testId:"raw-pipeline-run"}),G(Tr,{title:"Node states",subtitle:`${l.length} nodes`,facts:[`running ${y.running||0}`,`succeeded ${y.succeeded||0}`,`failed ${y.failed||0}`,`pending ${y.pending||0}`],data:l,onRaw:f,testId:"raw-pipeline-run-nodes"}),G(Tr,{title:"Procedure run index",subtitle:`${r.length} procedure records`,facts:[`succeeded ${_.succeeded||0}`,`failed ${_.failed||0}`,`latest ${Nu(c)}`,`errors ${$.length}`],data:r,onRaw:f,testId:"raw-pipeline-run-procedures"}),G(Tr,{title:"OA submissions",subtitle:`${n.length} submission files`,facts:[`records ${n.length}`,`task ${j8(u.task)}`,"raw grouped by run"],data:n,onRaw:f,testId:"raw-pipeline-run-submissions"}),G(Tr,{title:"Worker log tail",subtitle:"hidden from main interface",facts:[`tail ${i.length} lines`,"display raw only after click",`updated ${Nu(u.updatedAt)}`],data:i,onRaw:f,testId:"raw-pipeline-run-worker-log"}))}function $S({diagnostics:u,onRaw:f}){let l=Vu(u?.runs).filter(Du),r=Vu(u?.forbiddenResiduals),n=Du(u?.guarantees)?u.guarantees:{},i=u?.hasNeutralNodeFinishedEvidence===!0&&u?.hasNoAuditPolicyEvidence===!0&&u?.hasAuditPolicyEvidence===!0,y=u?.ok===!0&&i&&r.length===0,_=l[0]||null,$=[{label:"中性完成事实",ok:n.neutralNodeFinished===!0,hint:"node-finished 不携带流程策略"},{label:"Config 策略判定",ok:n.auditPolicyFromConfig===!0,hint:"OA backend 读取当前 epoch 配置"},{label:"控制命令来自 OA",ok:n.runnerConsumesControlCommandsFromOaEvents===!0,hint:"runner 只消费 OA control.command"},{label:"无独立审核事件",ok:n.noIndependentAuditRequestEvent===!0,hint:"审核由 node-finished + policy 派生"},{label:"无批次门禁",ok:n.noBatchFinishedControlGate===!0,hint:"下游启动由每个 node 完成驱动"}];return G("div",{className:"pipeline-oa-panel","data-testid":"pipeline-oa-event-flow-panel"},G("div",{className:"metric-grid compact"},G(Xl,{label:"OA Flow",value:y?"100%":"--",hint:String(u?.mode||"waiting diagnostics"),tone:y?"ok":"warn"}),G(Xl,{label:"禁止残留",value:r.length,hint:r.length===0?"source scan clean":"needs cleanup",tone:r.length===0?"ok":"warn"}),G(Xl,{label:"No-audit",value:u?.hasNoAuditPolicyEvidence?"OK":"--",hint:"OA 下游策略证据",tone:u?.hasNoAuditPolicyEvidence?"ok":"warn"}),G(Xl,{label:"Monitor 审核",value:u?.hasAuditPolicyEvidence?"OK":"--",hint:"OA 控制事件闭环",tone:u?.hasAuditPolicyEvidence?"ok":"warn"})),G("div",{className:"pipeline-oa-guarantees"},$.map((c)=>G("article",{key:c.label,className:`pipeline-oa-guarantee ${c.ok?"ok":"warn"}`},G(xn,{status:c.ok?"online":"warn"},c.ok?"OK":"MISS"),G("div",null,G("strong",null,c.label),G("span",null,c.hint))))),G("div",{className:"pipeline-evidence-list compact"},l.slice(0,6).map((c)=>G(Tr,{key:c.runId,title:String(c.runId||"--"),subtitle:[Number(c.monitorAuditNodeFinishedCount||0)>0?"monitor audit":"",Number(c.noAuditPolicyCount||0)>0?"no-audit policy":""].filter(Boolean).join(" / ")||"event evidence",facts:[`events ${c.eventCount||0}`,`node-finished ${c.nodeFinishedCount||0}`,`policy-in-detail ${c.nodeFinishedWithPolicyCount||0}`,`queued ${c.controlQueuedCount||0}`,`applied ${c.controlAppliedCount||0}`],data:c,onRaw:f,testId:`raw-pipeline-oa-run-${String(c.runId||"run").replace(/[^a-zA-Z0-9_.-]+/g,"-")}`}))),_?G("p",{className:"muted paragraph"},`最新证据 ${_.runId}: ${_.nodeFinishedCount||0} 个 node-finished,${_.controlAppliedCount||0} 个控制结果。`):G(Ar,{title:"暂无 OA 事件流证据",text:"等待 Pipeline backend 暴露 diagnostics。"}),u?G("div",{className:"panel-actions inline-actions"},G(kr,{title:"Pipeline OA Event Flow Diagnostics",data:u,onOpen:f,testId:"raw-pipeline-oa-event-flow"})):null)}function tS({quota:u,onRaw:f}){let l=Du(u?.summary)?u.summary:{},r=Du(u?.target)?u.target:{},n=Du(u?.cache)?u.cache:{},i=u?.ok===!0,y=String(u?.modelId||l.modelName||r.modelName||"MiniMax-M2.7"),_=l.totalCount??r.currentIntervalTotalCount,$=l.usageCount??r.currentIntervalUsageCount,c=l.remainingCount??r.currentIntervalRemainingCount,A=l.remainingRatio??(Number.isFinite(Number(_))&&Number(_)>0&&Number.isFinite(Number(c))?Number(c)/Number(_):void 0),j=l.usageRatio??(Number.isFinite(Number(_))&&Number(_)>0&&Number.isFinite(Number($))?Number($)/Number(_):void 0),F=l.resetAt||r.endAt,U=l.remainsMs??r.remainsMs,Q=Number(c),w=!i||Number.isFinite(Q)&&Q<=0?"warn":"ok",L=[i?`endpoint ${u?.endpoint||"--"}`:"quota unavailable",`fetched ${A8(u?.fetchedAt)}`,n.hit?`cache ${Er(n.ageMs)}`:"live quota"];return G("div",{className:"pipeline-minimax-quota-panel","data-testid":"pipeline-minimax-quota-panel"},G("div",{className:"metric-grid compact"},G(Xl,{label:"MiniMax",value:i?y:"--",hint:u?.modelComponent||u?.error||"model/minimax-m27",tone:w}),G(Xl,{label:"当前窗口",value:`${F9($)}/${F9(_)}`,hint:`已用 ${hW(j)}`,tone:w}),G(Xl,{label:"剩余额度",value:F9(c),hint:`剩余 ${hW(A)}`,tone:w}),G(Xl,{label:"重置时间",value:A8(F),hint:U!==void 0?`约 ${Er(U)}`:Nu(F),tone:w})),G(B9,{items:L}),i?G("p",{className:"muted paragraph"},`MiniMax 限额来自 D601 Pipeline 后端实时查询;当前模型匹配 ${l.modelName||r.modelName||y}。`):G(yf,{error:u?.error||"MiniMax 限额查询失败"}),u?G("div",{className:"panel-actions inline-actions"},G(kr,{title:"Pipeline MiniMax Quota",data:u,onOpen:f,testId:"raw-pipeline-minimax-quota"})):null)}function cS({epochs:u,activeRun:f,activePipeline:l,pipelineNodes:r,pipelineEdges:n,runDetails:i,nodeDetails:y,nodeDetailsState:_,ganttScale:$=X$,onGanttScaleChange:c,onRunChange:A,onIntervalSelect:j,onMarkerSelect:F,selection:U,detailOpen:Q,onDetailOpenChange:w,onRaw:L}){let[J,N]=kl(RY),[q,W]=kl({startY:0,endY:0,startMs:0,endMs:0}),[z,Z]=kl(Date.now()),H=Cn(null),E=String(f?.runId||""),D=Boolean(Q),h=(Au)=>{if(typeof w==="function")w(Au)},B=hn($??X$),X=String(i?.runId||"")===E?i?.details:null,m=X?{...Du(f)?f:{},...Du(X)?X:{},runId:E,procedureRuns:Vu(X?.procedureRuns).length>0?X.procedureRuns:f?.procedureRuns}:f,O=ww(m,r,z),p=X?iS(X,m):{markers:[],arrows:[]},Y=Vu(p.markers),v=CY(m,O,Y),T=kY(v,B,O,z),S=String(T.source||"frontend-y"),k=O.map((Au)=>IY(Au,T,z)),I={startMs:Number(T.startMs),endMs:Number(T.endMs),durationMs:Math.max(1,Number(T.durationMs??Number(T.endMs)-Number(T.startMs)))},b=S9(B),o={...b,pxPerMinute:Number(T.pxPerMinute??b.pxPerMinute)},s=Math.round(Number(T.chartHeight||360)),x=O.some(m9);A0(()=>{if(!E||!x)return;let Au=window.setInterval(()=>Z(Date.now()),1000);return()=>window.clearInterval(Au)},[E,x]);let fu=BY(l,r,Array.isArray(n)?n:[]),$u=r.map((Au)=>String(Au?.id||"")).filter(Boolean),tu=k.map((Au)=>String(Au.nodeId||"")).filter(Boolean),ju=Y.map((Au)=>String(Au.nodeId||"")).filter(Boolean),Gu=Array.from(new Set([...fu,...$u,...tu,...ju])),qu={startY:0,endY:s,startMs:Number(I.startMs),endMs:Number(I.endMs)},P=Number(q?.endY||0)>0?q:qu,e=(Au)=>{return N8(Au,I,s,T)<=Number(P.endY)&&Z9(Au,I,s,T)>=Number(P.startY)},uu=(Au)=>{let vu=cr(Au,I,s,T);return vu>=Number(P.startY)&&vu<=Number(P.endY)},Wu=new Set(Gu.filter((Au)=>k.some((vu)=>vu.nodeId===Au&&e(vu))||Y.some((vu)=>vu.nodeId===Au&&uu(vu)))),g=J?Gu.filter((Au)=>Wu.has(Au)):Gu,Qu=`${A9}px ${g.length>0?g.map(()=>`${t0}px`).join(" "):"minmax(160px, 1fr)"}`,Tu=Vu(T.ticks).filter(Du),Zu=String(U?.mode==="interval"?U?.interval?.procedureRunId||"":""),Xu=String(U?.mode==="event"?U?.marker?.id||"":""),ff=()=>{let Au=H.current;if(!Au){W(qu);return}let vu=Math.max(0,Au.scrollTop-j9),Kl=Math.max(120,Au.clientHeight-j9),Su=Math.min(s,vu+Kl),pf={startY:vu,endY:Su,startMs:Number(I.startMs),endMs:Number(I.endMs)},Gl=Math.max(0,Math.min(1,vu/s)),zl=Math.max(Gl,Math.min(1,Su/s)),Pf=Math.max(1,Number(I.endMs)-Number(I.startMs));pf.startMs=Number(I.startMs)+Pf*Gl,pf.endMs=Number(I.startMs)+Pf*zl,W(pf)};A0(()=>{let Au=H.current,vu=window.setTimeout(ff,0);return Au?.addEventListener("scroll",ff),window.addEventListener("resize",ff),()=>{window.clearTimeout(vu),Au?.removeEventListener("scroll",ff),window.removeEventListener("resize",ff)}},[E,I.startMs,I.endMs,s]);let _f=Math.max(0,Gu.length-g.length),Jf=new Set(Y.filter((Au)=>g.includes(String(Au.nodeId||""))&&uu(Au)).map((Au)=>String(Au.id))),mf=new Map(Y.map((Au)=>[String(Au.id),Au])),Yl=Vu(p.arrows).filter((Au)=>{if(!Jf.has(String(Au.targetMarkerId||"")))return!1;if(String(Au.action||"")==="observe")return g.includes(String(Au.sourceNodeId||""));return Jf.has(String(Au.sourceMarkerId||""))}),Al=A9+Math.max(1,g.length)*t0,jl=(Au)=>{let vu=hn(Au.target.value);if(typeof c==="function")c(vu);window.setTimeout(ff,0)},Hr=()=>pY({title:`${l?.id||"pipeline"}-${E||"epoch"}-gantt`,meta:[`run ${E||"--"}`,`${Nu(I.startMs)} -> ${Nu(I.endMs)}`,`duration ${Er(I.durationMs)}`,`${o.label} / ${N9(o.pxPerMinute)} px/min`,`${g.length}/${Gu.length} nodes`,`${Y.length} markers`],visibleNodeIds:g,intervals:k,markers:Y.filter((Au)=>g.includes(String(Au.nodeId||""))),arrows:Yl,ticks:Tu,bounds:I,chartHeight:s,backendLayout:T}),al=Du(X?.gantt?.diagnostics)?X.gantt.diagnostics:null;return G(c0,{title:"Epoch 甘特图",eyebrow:`${l?.id||"pipeline"} / ${u.length} epochs`,className:"pipeline-wide-panel",loading:i?.loading,actions:G("div",{className:"pipeline-gantt-actions"},G("select",{value:E,disabled:u.length===0,onChange:(Au)=>A(Au.target.value),"data-testid":"pipeline-epoch-select"},u.map((Au)=>G("option",{key:Au.runId,value:Au.runId},T9(u,Au)))),G("label",{className:"pipeline-gantt-toggle"},G("input",{type:"checkbox","data-testid":"pipeline-gantt-auto-hide-idle",checked:J,onChange:(Au)=>{N(Boolean(Au.target.checked)),window.setTimeout(ff,0)}}),G("span",null,"自动隐藏空闲列")),G("label",{className:"pipeline-gantt-scale"},G("span",null,G("b",null,"时间尺度"),G("em",{"data-testid":"pipeline-gantt-scale-label"},`${o.label} · ${N9(o.pxPerMinute)} px/min`)),G("input",{type:"range",min:0,max:100,step:0.01,value:B,onChange:jl,"aria-label":"调整甘特图时间尺度","data-testid":"pipeline-gantt-time-scale"}),G("small",null,G("span",null,"全局"),G("span",null,"细节"))),f?G("button",{type:"button",className:"ghost-btn",onClick:Hr,disabled:g.length===0,"data-testid":"pipeline-export-gantt"},"导出甘特图"):null,f?G(kr,{title:`Pipeline Epoch ${f.runId}`,data:f,onOpen:L,testId:"raw-pipeline-epoch-gantt"}):null)},!f?G(Ar,{title:"暂无 Epoch",text:"当前 pipeline 还没有完整运行记录。"}):k.length===0?G(Ar,{title:"暂无时间区间",text:"等待 D601 Pipeline backend 在 procedure summary 中返回 startedAt / finishedAt。"}):G("div",{className:"pipeline-gantt-wrap"},G("div",{className:`pipeline-gantt-detail-layout ${D?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-gantt-detail-layout","data-sidebar-open":D?"true":"false"},G("div",{className:"pipeline-gantt-main"},G("div",{className:"pipeline-gantt-main-head"},G("div",{className:"pipeline-gantt-meta"},G("span",null,`time ${Nu(I.startMs)} -> ${Nu(I.endMs)}`),G("span",null,`duration ${Er(I.durationMs)}`),G("span",null,`scale ${o.label} / ${N9(o.pxPerMinute)} px/min`),G("span",null,`layout ${S}`),al?G("span",null,`align ${al.timeAxisAlignmentOk===!1?"check":"ok"}`):null,G("span",null,`visible ${g.length}/${Gu.length} nodes`),X?G("span",null,`markers ${Y.length}`):null,J&&_f>0?G("span",null,`hidden idle ${_f}`):null),!D?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!U?.mode,onClick:()=>h(!0),"data-testid":"pipeline-gantt-sidebar-toggle"},U?.mode?"展开详情":"点击甘特图元素展开详情"):null),G("div",{className:"pipeline-gantt-viewport",ref:H,"data-testid":"pipeline-epoch-gantt","data-pipeline-id":l?.id||"","data-run-id":E,"data-layout-source":S,"data-start-ms":String(I.startMs),"data-end-ms":String(I.endMs),"data-chart-height":String(s)},G("div",{className:"pipeline-gantt-board",style:{gridTemplateColumns:Qu,minWidth:`${Al}px`}},G("div",{className:"pipeline-gantt-head time"},"Time"),g.length===0?G("div",{className:"pipeline-gantt-head empty"},"当前时间窗无工作节点"):g.map((Au)=>G("div",{key:`head-${Au}`,className:"pipeline-gantt-head node",title:Au,"data-testid":"pipeline-gantt-head-node","data-node-id":Au},G(AY,{value:Au}))),G("div",{className:"pipeline-gantt-time-axis",style:{height:`${s}px`}},Tu.map((Au)=>{let vu=Ew(Au,I,s,T);return G("div",{key:`tick-${Au.ms}-${vu}`,className:"pipeline-gantt-tick",style:{top:`${vu}px`},"data-testid":"pipeline-gantt-tick","data-ms":String(Au.ms),"data-y":String(vu)},G("b",null,Nu(Au.ms)),G("span",null,`+${Er(Number(Au.offsetMs??Number(Au.ms)-Number(I.startMs)))}`))})),g.length>0?G("svg",{className:"pipeline-gantt-arrow-layer",width:g.length*t0,height:s,viewBox:`0 0 ${g.length*t0} ${s}`,style:{left:`${A9}px`,top:`${j9}px`,width:`${g.length*t0}px`,height:`${s}px`},"aria-hidden":"true"},G("defs",null,G("marker",{id:"pipeline-gantt-arrowhead",viewBox:"0 0 10 10",refX:9,refY:5,markerWidth:6,markerHeight:6,orient:"auto-start-reverse"},G("path",{d:"M 0 0 L 10 5 L 0 10 z",fill:"context-stroke"}))),Yl.map((Au)=>{let vu=mf.get(String(Au.targetMarkerId||""));if(!vu)return null;let Kl=mf.get(String(Au.sourceMarkerId||"")),Su=String(Kl?.nodeId||Au.sourceNodeId||""),pf=g.indexOf(Su),Gl=g.indexOf(String(vu.nodeId||""));if(pf<0||Gl<0)return null;let zl=pf*t0+t0/2,Pf=Gl*t0+t0/2,rf=Kl?cr(Kl,I,s,T):cr(vu,I,s,T),Ir=cr(vu,I,s,T);return G("path",{key:Au.id,className:`pipeline-gantt-arrow ${String(Au.sourceKind||"").toLowerCase()} ${String(Au.status||"").toLowerCase()} ${String(Au.action||"").toLowerCase()}`,d:Zw(zl,rf,Pf,Ir),markerEnd:"url(#pipeline-gantt-arrowhead)","data-testid":String(Au.action||"")==="observe"?"pipeline-gantt-observation-arrow":"pipeline-gantt-arrow","data-source-node-id":String(Au.sourceNodeId||""),"data-target-node-id":String(Au.targetNodeId||""),"data-target-marker-id":String(Au.targetMarkerId||""),"data-action":String(Au.action||""),"data-source-y":String(rf),"data-target-y":String(Ir)})})):null,g.length===0?G("div",{className:"pipeline-gantt-empty-col",style:{height:`${s}px`}},"滚动到有活动的时间段后,相关 node 列会自动出现。"):g.map((Au)=>{let vu=k.filter((Su)=>Su.nodeId===Au),Kl=Y.filter((Su)=>String(Su.nodeId||"")===Au);return G("div",{key:`col-${Au}`,className:"pipeline-gantt-node-col",style:{height:`${s}px`}},vu.map((Su)=>{let pf=N8(Su,I,s,T),Gl=Z9(Su,I,s,T),zl=Tw(Su,I,s,T),Pf=String(Su.procedureRunId||`${Au}-${Su.startMs}`);return G("button",{key:Pf,type:"button",className:`pipeline-gantt-bar ${Su.status} ${Su.live?"live":""} ${Zu===Pf?"selected":""}`,style:{top:`${pf}px`,height:`${zl}px`},title:`${Au} ${Su.status} ${Nu(Su.startedAt||Su.startMs)} -> ${Nu(Su.finishedAt||Su.endMs)}`,onClick:()=>j(Su),"data-testid":"pipeline-gantt-line","data-node-id":Au,"data-procedure-run-id":String(Su.procedureRunId||""),"data-status":String(Su.status||""),"data-live":Su.live?"true":"false","data-start-ms":String(Su.startMs||""),"data-end-ms":String(Su.endMs||""),"data-y1":String(pf),"data-y2":String(Gl),"data-natural-height":String(Math.max(0,Gl-pf))},G("strong",null,Su.status||"working"),G("span",null,Er(Su.durationMs)))}),Kl.map((Su)=>G("button",{key:Su.id,type:"button",className:`pipeline-gantt-marker ${Su.kind} ${Su.tone||""} ${Su.status||""} ${Xu===String(Su.id)?"selected":""}`,style:{top:`${cr(Su,I,s,T)}px`},title:`${Su.label||"event"} / ${Nu(Su.timestampIso||Su.timestamp||Su.ms)}`,onClick:()=>F(Su),"data-testid":Su.kind==="prompt"?"pipeline-gantt-prompt-marker":"pipeline-gantt-control-marker","data-marker-id":String(Su.id||""),"data-ms":String(Su.ms??Su.eventMs??""),"data-y":String(cr(Su,I,s,T))})))})))),D?G(cY,{selection:U,runDetails:i,nodeDetails:y,nodeDetailsState:_,onRaw:L,onCollapse:()=>h(!1)}):null)))}function R0(){return{loading:!1,actionLoading:"",error:"",message:"",details:null,fetchedAt:null,appendPrompt:"",guidePrompt:"",modifyPrompt:"",approveReason:"",redoReason:""}}function Mn(){return{mode:"",runId:"",interval:null,marker:null}}function W9(){return{runId:"",loading:!1,error:"",details:null,fetchedAt:null}}function E$(u,f){return`${u}/microservices/pipeline/proxy${f}`}function AS({activeRun:u,pipelineRuns:f,selectedRunId:l,onRunChange:r,selectedNodeId:n,selectedNodeConfig:i,selectedNodeRuntime:y,control:_,onControlChange:$,onFetch:c,onAction:A,onRaw:j,onCollapse:F}){let U=String(u?.runId||""),Q=String(y?.status||"pending"),w=!U||!n||_.loading||Boolean(_.actionLoading),L=(N)=>(q)=>$({[N]:q.target.value,error:"",message:""}),J=f.length>0?f:u?[u]:[];return G("aside",{className:"pipeline-node-control","data-testid":"pipeline-node-control"},G("div",{className:"pipeline-node-control-head"},G("div",null,G("p",{className:"panel-eyebrow"},"Manual Node Control"),G(nf,{title:n||"点击控制图中的 node",level:3,loading:_.loading||Boolean(_.actionLoading)})),G("div",{className:"pipeline-node-control-head-actions"},n?G(xn,{status:Q},Q):G(xn,{status:"pending"},"idle"),G("button",{type:"button",className:"ghost-btn mini",onClick:F,"data-testid":"pipeline-node-sidebar-collapse"},"收起"))),G("div",{className:"pipeline-control-runbar"},G("label",null,G("span",null,"目标 run"),G("select",{value:U||l,disabled:J.length===0,onChange:(N)=>r(N.target.value),"data-testid":"pipeline-node-run-select"},J.map((N)=>G("option",{key:N.runId,value:N.runId},`${N.runId||"--"} / ${N.status||"--"}`)))),G("button",{type:"button",className:"ghost-btn",disabled:w,onClick:c,"data-testid":"pipeline-node-fetch"},_.loading?"抓取中":"抓取过程"),_.details?G(kr,{title:`Pipeline Node ${n}`,data:_.details,onOpen:j,testId:"raw-pipeline-node-control"}):null),G("div",{className:"pipeline-control-meta"},G("span",null,G("b",null,"kind"),String(i?.kind||"--")),G("span",null,G("b",null,"procedure"),String(y?.currentProcedureRunId||"--")),G("span",null,G("b",null,"attempts"),String(y?.attempts??"--")),G("span",null,G("b",null,"updated"),Nu(u?.updatedAt))),!n?G(Ar,{title:"未选择 node",text:"点击 React Flow 控制图中的任意 node 后,可抓取执行过程、追加 prompt、下发引导、增量修改、审核通过或重做。"}):null,G(yf,{error:_.error,wide:!0}),G("div",{className:"pipeline-control-actions"},G("label",null,G("span",null,"实时追加 prompt(仅 running node)"),G("textarea",{value:_.appendPrompt,onChange:L("appendPrompt"),placeholder:"让当前执行中的 agent 继续、补充检查或调整当前步骤...",rows:4,disabled:!n,"data-testid":"pipeline-node-append-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:w||!String(_.appendPrompt||"").trim(),onClick:()=>A("append"),"data-testid":"pipeline-node-append-button"},_.actionLoading==="append"?"追加中":"追加到运行中 node")),G("label",null,G("span",null,"下次尝试引导 prompt"),G("textarea",{value:_.guidePrompt,onChange:L("guidePrompt"),placeholder:"给该 node 下一次 attempt 的执行提示;不会立即打断当前 session。",rows:4,disabled:!n,"data-testid":"pipeline-node-guide-input"}),G("button",{type:"button",className:"ghost-btn compact",disabled:w||!String(_.guidePrompt||"").trim(),onClick:()=>A("guide"),"data-testid":"pipeline-node-guide-button"},_.actionLoading==="guide"?"下发中":"下发 guide")),G("label",null,G("span",null,"完成后增量修改 prompt"),G("textarea",{value:_.modifyPrompt,onChange:L("modifyPrompt"),placeholder:"在该 node 已完成结果基础上追加修改要求;runner 会重跑目标 node,并保留同 node 既有 OA 输出作为上下文。",rows:4,disabled:!n,"data-testid":"pipeline-node-modify-input"}),G("button",{type:"button",className:"ghost-btn compact",disabled:w||!String(_.modifyPrompt||"").trim(),onClick:()=>A("modify"),"data-testid":"pipeline-node-modify-button"},_.actionLoading==="modify"?"排队中":"增量修改 node")),G("label",null,G("span",null,"Monitor 审核通过原因"),G("textarea",{value:_.approveReason,onChange:L("approveReason"),placeholder:"当流程配置开启 monitor 审核时,记录审核通过原因并释放后续 node。",rows:3,disabled:!n,"data-testid":"pipeline-node-approve-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:w||!String(_.approveReason||"").trim(),onClick:()=>A("approve"),"data-testid":"pipeline-node-approve-button"},_.actionLoading==="approve"?"提交中":"审核通过")),G("label",null,G("span",null,"重做 / restart 原因"),G("textarea",{value:_.redoReason,onChange:L("redoReason"),placeholder:"说明为什么需要重做;runner 会重置目标 node 以及非 rework 下游 node。",rows:4,disabled:!n,"data-testid":"pipeline-node-redo-input"}),G("button",{type:"button",className:"danger-btn compact",disabled:w||!String(_.redoReason||"").trim(),onClick:()=>A("redo"),"data-testid":"pipeline-node-redo-button"},_.actionLoading==="redo"?"排队中":"重做 node"))),G("div",{className:"pipeline-control-evidence"},G("strong",null,"Node 过程索引"),G(yS,{details:_.details,selectedNodeId:n,selectedNodeRuntime:y,control:_,onRaw:j})))}function Ow({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((lu)=>lu.id==="pipeline")||null,[n,i]=kl({loading:!1,error:"",health:null,snapshot:null,oaDiagnostics:null,minimaxQuota:null,refreshedAt:null}),[y,_]=kl(""),[$,c]=kl(""),[A,j]=kl(""),[F,U]=kl(R0()),[Q,w]=kl({}),[L,J]=kl(Mn()),[N,q]=kl(W9()),[W,z]=kl(X$),[Z,H]=kl(!1),[E,D]=kl(!1),h=Cn(0),{addNotification:B}=Bl(),X=Cn(!1),m=Cn(0),O=Cn(""),p=Cn({}),Y=Cn(""),v=Cn("");async function T(lu={}){let Ou=lu.silent===!0;if(!r)return;if(X.current)return;X.current=!0;let mu=h.current+1;if(h.current=mu,!Ou)i((ou)=>({...ou,loading:!0,error:""}));try{let ou=`__unideskArrayLimit=registry.components:80,runs:${IX}`,[Af,vf,pu]=await Promise.all([Pn(`${l}/microservices/pipeline/proxy/api/snapshot?${ou}`,{cache:"no-store"}),Pn(`${l}/microservices/pipeline/proxy/api/oa-event-flow/diagnostics`,{cache:"no-store"}).catch((J0)=>({ok:!1,error:Hu(J0,"OA event flow diagnostics failed")})),Pn(`${l}/microservices/pipeline/proxy/api/model-quota/minimax`,{cache:"no-store"}).catch((J0)=>({ok:!1,error:Hu(J0,"MiniMax quota failed")}))]);if(mu!==h.current)return;let ll={ok:Af?.ok!==!1,service:"pipeline-v2-control snapshot"};i({loading:!1,error:"",health:ll,snapshot:Af,oaDiagnostics:vf,minimaxQuota:pu,refreshedAt:new Date})}catch(ou){if(mu!==h.current)return;i((Af)=>({...Af,loading:!1,error:Hu(ou,"Pipeline 加载失败")}))}finally{X.current=!1}}A0(()=>{if(T(),!r)return;let lu=()=>{if(y8())T({silent:!0})},Ou=window.setInterval(()=>{lu()},CW),mu=()=>{if(y8())lu()};return document.addEventListener("visibilitychange",mu),()=>{window.clearInterval(Ou),document.removeEventListener("visibilitychange",mu)}},[r?.id,r?.runtime?.providerStatus,l]);let S=jY(r),k=JY(r),I=FY(r),b=n.snapshot||{},o=n.oaDiagnostics||null,s=n.minimaxQuota||null,{components:x,pipelines:fu,runs:$u}=UY(b),tu=String($u[0]?.pipelineId||""),ju=(tu?fu.find((lu)=>String(lu.id||"")===tu):null)||fu[0]||{},Gu=fu.find((lu)=>String(lu.id||"")===y)||ju,qu=String(Gu.id||""),P=Uw(Gu),e=D9(Gu),uu=lw($u,qu),Wu=MY($u,qu),g=Wu.find((lu)=>String(lu?.runId||"")===$)||uu,Qu=String(N.runId||"")===String(g?.runId||"")?WY(N.details):null,Tu=wY(g,Qu),Zu=String(Tu?.runId||""),Xu=P.find((lu)=>String(lu?.id||"")===A)||null,ff=A?Qw(Tu,A):null,_f=qY($u),Jf=zY(x),mf=Number(n.health?.components)||sW(b,"registry.components",x.length),Yl=sW(b,"runs",$u.length),Al=dW(Gu,Tu,x),jl={nodes:Al.nodes.map((lu)=>lu.id===A?{...lu,selected:!0,className:`${lu.className||""} selected-control-node`}:lu),edges:Al.edges},Hr=fu.map((lu)=>{let Ou=String(lu.id||"pipeline"),mu=lw($u,Ou);return{title:`${Ou}-${mu?.runId||"snapshot"}`,flow:dW(lu,mu,x)}}),al=String(L?.runId||Zu||""),Au=String(L?.interval?.nodeId||L?.marker?.nodeId||""),vu=al&&Au?Q[q9(al,Au)]||null:null,Kl=F8(F.details,al,Au),Su=F8(vu?.details,al,Au)||Kl,pf=al&&Au?{...Du(vu)?vu:{},runId:al,nodeId:Au,details:Su,loading:Boolean(vu?.loading)||!Su&&Boolean(F.loading)&&A===Au,error:String(vu?.error||""),fetchedAt:vu?.fetchedAt||(Kl?F.fetchedAt:null)}:null,Gl=Wu.map((lu)=>String(lu?.runId||"")).filter(Boolean).join("|"),zl=P.map((lu)=>String(lu?.id||"")).filter(Boolean).join("|");A0(()=>{Y.current=A},[A]),A0(()=>{v.current=Zu},[Zu]),A0(()=>{if(!$||Gl.split("|").includes($))return;c("")},[$,Gl]),A0(()=>{if(!A||zl.split("|").includes(A))return;j(""),U(R0()),J(Mn()),H(!1),D(!1)},[A,zl]),A0(()=>{if(!A)H(!1)},[A]),A0(()=>{if(!L.mode)D(!1)},[L.mode]);async function Pf(lu=Zu,Ou={}){if(!lu){q(W9());return}let mu=hn(Ou.scale??W??X$),ou=`${lu}:timeline`;if(O.current===ou)return;O.current=ou;let Af=Ou.silent===!0,vf=m.current+1;m.current=vf,q((pu)=>({runId:lu,scale:mu,loading:!Af||String(pu.runId||"")!==lu||!pu.details,error:"",details:Af&&pu.runId===lu?pu.details:pu.runId===lu?pu.details:null,fetchedAt:pu.runId===lu?pu.fetchedAt:null}));try{let[pu,ll]=await Promise.all([Pn(E$(l,`/api/node-control/runs/${encodeURIComponent(lu)}?tail=160&view=timeline`),{cache:"no-store",strictJson:!0}),Pn(E$(l,`/api/runs/${encodeURIComponent(lu)}`),{cache:"no-store"}).catch((J0)=>({ok:!1,runSummaryError:Hu(J0,"抓取评分失败")}))]);if(vf!==m.current)return;q({runId:lu,scale:mu,loading:!1,error:"",details:{...pu,run:Du(ll?.run)?ll.run:void 0,runSummaryError:ll?.runSummaryError},fetchedAt:new Date})}catch(pu){if(vf!==m.current)return;q((ll)=>({runId:lu,scale:mu,loading:!1,error:Hu(pu,"抓取 epoch 执行过程失败"),details:ll.runId===lu?ll.details:null,fetchedAt:ll.runId===lu?ll.fetchedAt:null}))}finally{if(O.current===ou)O.current=""}}function rf(lu,Ou,mu){let ou=q9(lu,Ou);w((Af)=>{let vf={...Af,[ou]:{...Du(Af?.[ou])?Af[ou]:{},runId:lu,nodeId:Ou,...mu}},pu=Object.keys(vf);if(pu.length>32)for(let ll of pu.slice(0,pu.length-32))delete vf[ll];return vf})}async function Ir(lu,Ou){if(!lu||!Ou)return;let mu=q9(lu,Ou),ou=Number(p.current?.[mu]||0)+1;p.current={...p.current,[mu]:ou},rf(lu,Ou,{loading:!0,error:""});try{let Af=await Pn(E$(l,`/api/node-control/runs/${encodeURIComponent(lu)}/nodes/${encodeURIComponent(Ou)}?tail=160`),{cache:"no-store",strictJson:!0});if(Number(p.current?.[mu]||0)!==ou)return;let vf=new Date;if(rf(lu,Ou,{loading:!1,details:Af,fetchedAt:vf,error:""}),Y.current===Ou&&v.current===lu)U((pu)=>({...pu,loading:!1,details:Af,fetchedAt:vf,error:""}))}catch(Af){if(Number(p.current?.[mu]||0)!==ou)return;rf(lu,Ou,{loading:!1,error:Hu(Af,"抓取 Gantt node 详情失败")})}}A0(()=>{if(!Zu){q(W9());return}Pf(Zu);let lu=()=>{if(y8())Pf(Zu,{silent:!0})},Ou=window.setInterval(()=>{lu()},CW),mu=()=>{if(y8())lu()};return document.addEventListener("visibilitychange",mu),()=>{window.clearInterval(Ou),document.removeEventListener("visibilitychange",mu)}},[Zu,l]);async function Fr(lu=Zu,Ou=A){if(!lu||!Ou){U((mu)=>({...mu,error:"请先选择 run 和 node",message:""}));return}U((mu)=>({...mu,loading:!0,error:"",message:""}));try{let mu=await Pn(E$(l,`/api/node-control/runs/${encodeURIComponent(lu)}/nodes/${encodeURIComponent(Ou)}?tail=160`),{cache:"no-store",strictJson:!0}),ou=new Date;U((Af)=>({...Af,loading:!1,details:mu,fetchedAt:ou,error:""})),rf(lu,Ou,{loading:!1,details:mu,fetchedAt:ou,error:""})}catch(mu){U((ou)=>({...ou,loading:!1,error:Hu(mu,"抓取 node 执行过程失败")}))}}async function x1(lu){let Ou=String(lu?.runId||Zu||""),mu=String(lu?.nodeId||"");if(J({mode:"interval",runId:Ou,interval:lu,marker:null}),D(!0),!Ou||!mu)return;if(Ou!==Zu)c(Ou);j(mu),U(R0()),Pf(Ou,{silent:!0}),Ir(Ou,mu)}async function gn(lu){let Ou=String(lu?.runId||Zu||""),mu=String(lu?.nodeId||"");if(J({mode:"event",runId:Ou,interval:null,marker:lu}),D(!0),!Ou)return;if(Ou!==Zu)c(Ou);if(Pf(Ou,{silent:!0}),!mu)return;j(mu),U(R0()),Ir(Ou,mu)}async function b0(lu){if(!Zu||!A){U((ou)=>({...ou,error:"请先选择 run 和 node",message:""}));return}let Ou=lu==="append"?"prompts":lu,mu=lu==="append"?F.appendPrompt:lu==="guide"?F.guidePrompt:lu==="modify"?F.modifyPrompt:lu==="approve"?F.approveReason:F.redoReason;if(!String(mu||"").trim()){U((ou)=>({...ou,error:"操作内容不能为空",message:""}));return}U((ou)=>({...ou,actionLoading:lu,error:"",message:""}));try{let ou=lu==="redo"||lu==="approve"?{reason:mu,source:"unidesk-frontend",sourceKind:"webui"}:{prompt:mu,source:"unidesk-frontend",sourceKind:"webui"},Af=await Pn(E$(l,`/api/node-control/runs/${encodeURIComponent(Zu)}/nodes/${encodeURIComponent(A)}/${Ou}`),{method:"POST",body:JSON.stringify(ou)});if(U((pu)=>({...pu,actionLoading:"",details:Af,fetchedAt:new Date,appendPrompt:lu==="append"?"":pu.appendPrompt,guidePrompt:lu==="guide"?"":pu.guidePrompt,modifyPrompt:lu==="modify"?"":pu.modifyPrompt,approveReason:lu==="approve"?"":pu.approveReason,redoReason:lu==="redo"?"":pu.redoReason,message:lu==="append"?"已追加到运行中 node":lu==="guide"?"已下发 guide,等待 runner 处理":lu==="modify"?"已排队增量修改命令":lu==="approve"?"已提交审核通过决策":"已排队重做命令"})),B("success",lu==="append"?"已追加到运行中 node":lu==="guide"?"已下发 guide,等待 runner 处理":lu==="modify"?"已排队增量修改命令":lu==="approve"?"已提交审核通过决策":"已排队重做命令"),await Fr(Zu,A),await Pf(Zu,{silent:!0}),lu!=="append")await T()}catch(ou){U((Af)=>({...Af,actionLoading:"",error:Hu(ou,"node 控制操作失败")}))}}if(!r)return G(Ar,{title:"Pipeline 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=pipeline"});return G("div",{className:"pipeline-page","data-testid":"pipeline-page"},G(c0,{title:"Pipeline v2 工作台",eyebrow:"D601 Snapshot 用户服务",loading:n.loading,actions:G("div",{className:"panel-actions"},G("button",{type:"button",className:"ghost-btn",onClick:T,disabled:n.loading,"data-testid":"pipeline-refresh-button"},n.loading?"刷新中":"刷新"),G(kr,{title:"Pipeline 用户服务",data:r,onOpen:f,testId:"raw-pipeline-service"}))},G("div",{className:"pipeline-hero"},G("div",null,G("div",{className:"node-version-line"},G(xn,{status:S.providerStatus==="online"?"online":"warn"},S.providerStatus||"unknown"),G("span",null,r.providerId),G("span",null,I.public?"公网暴露":"仅 UniDesk frontend 代理访问")),G("p",{className:"muted paragraph"},r.description)),G("div",{className:"microservice-ref-card"},G("span",null,"Repo"),G("strong",null,k.url||"--"),G("code",null,k.commitId||"--")),G("div",{className:"microservice-ref-card"},G("span",null,"D601 Docker"),G("strong",null,`${I.nodeBindHost||"--"}:${I.nodePort||"--"}`),G("code",null,`${k.composeFile||"--"} / ${k.composeService||"--"}`))),G(yf,{error:n.error,wide:!0})),G("div",{className:"pipeline-grid"},G(c0,{title:"控制图",eyebrow:`${Gu.id||"pipeline"} / run ${Tu?.status||"--"}`,className:"pipeline-wide-panel",loading:n.loading,actions:G("div",{className:"pipeline-toolbar"},G("select",{value:qu,disabled:fu.length===0,onChange:(lu)=>{_(lu.target.value),c(""),j(""),U(R0()),J(Mn()),H(!1),D(!1)},"data-testid":"pipeline-select"},fu.map((lu)=>G("option",{key:lu.id,value:lu.id},lu.id||lu.key))),G("select",{value:Zu,disabled:Wu.length===0,onChange:(lu)=>{if(c(lu.target.value),U(R0()),J(Mn()),H(!1),D(!1),A)Fr(lu.target.value,A)},"data-testid":"pipeline-run-select"},Wu.map((lu)=>G("option",{key:lu.runId,value:lu.runId},T9(Wu,lu)))),G("button",{type:"button",className:"ghost-btn",disabled:jl.nodes.length===0,onClick:()=>Ww(jl,`${Gu.id||"pipeline"}-${Tu?.runId||"snapshot"}`),"data-testid":"pipeline-export-graph"},"导出渲染图"),G("button",{type:"button",className:"ghost-btn",disabled:Hr.every((lu)=>lu.flow.nodes.length===0),onClick:()=>PY(Hr),"data-testid":"pipeline-export-all-graphs"},"批量导出"))},P.length===0?G(Ar,{title:"暂无控制图",text:"等待 D601 pipeline backend 返回 config.nodes / config.edges"}):G("div",{className:`pipeline-control-shell ${Z?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-control-shell","data-sidebar-open":Z?"true":"false"},G("div",{className:"pipeline-flow-frame","data-testid":"pipeline-react-flow"},G(XW,{nodes:jl.nodes,edges:jl.edges,nodeTypes:dX,edgeTypes:oX,fitView:!0,fitViewOptions:{padding:0.18},nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,minZoom:0.25,maxZoom:1.4,proOptions:{hideAttribution:!0},onNodeClick:(lu,Ou)=>{let mu=String(Ou.id);if(j(mu),U(R0()),H(!0),Zu)Fr(Zu,mu)}},G(SW,{gap:22,size:1,color:"rgba(215, 161, 58, 0.24)"}),G(pW,{showInteractive:!1})),!Z?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!A,onClick:()=>H(!0),"data-testid":"pipeline-node-sidebar-toggle"},A?"展开 node 控制":"点击 node 展开控制"):null),Z?G(AS,{activeRun:Tu,pipelineRuns:Wu,selectedRunId:$,onRunChange:(lu)=>{if(c(lu),U(R0()),J(Mn()),A)Fr(lu,A)},selectedNodeId:A,selectedNodeConfig:Xu,selectedNodeRuntime:ff,control:F,onControlChange:(lu)=>U((Ou)=>({...Ou,...lu})),onFetch:()=>Fr(),onAction:b0,onRaw:f,onCollapse:()=>H(!1)}):null),G("div",{className:"pipeline-flow-summary"},G("span",null,`${jl.nodes.length} nodes`),G("span",null,`${jl.edges.length} edges`),G("span",null,`${fu.length} pipelines`),G("span",null,`source config+components(${x.length})`),G("span",null,`run ${Tu?.runId||"--"}`),G("span",null,`score ${z9(Tu)}`),G("span",null,A?`selected ${A}`:"click node to control"))),G(cS,{epochs:Wu,activeRun:Tu,activePipeline:Gu,pipelineNodes:P,pipelineEdges:e,selection:L,detailOpen:E,onDetailOpenChange:D,runDetails:N,nodeDetails:Su,nodeDetailsState:pf,ganttScale:W,onGanttScaleChange:z,onIntervalSelect:x1,onMarkerSelect:gn,onRunChange:(lu)=>{if(c(lu),U(R0()),J(Mn()),D(!1),A)Fr(lu,A)},onRaw:f}),G(c0,{title:"观测指标",eyebrow:n.refreshedAt?`Updated ${$f(n.refreshedAt)}`:"Snapshot",loading:n.loading},G("div",{className:"metric-grid"},G(Xl,{label:"Health",value:n.health?.ok?"OK":"--",hint:n.health?.service||"D601 /health",tone:n.health?.ok?"ok":"warn"}),G(Xl,{label:"组件",value:mf,hint:"components registry",tone:b?.registry?.ok===!1?"warn":"ok"}),G(Xl,{label:"Pipeline",value:fu.length,hint:`${P.length} nodes / ${e.length} edges`}),G(Xl,{label:"运行记录",value:Yl,hint:`${_f.succeeded||0} succeeded / ${_f.running||0} running`}),G(Xl,{label:"OA 记录",value:Array.isArray(uu?.submissions)?uu.submissions.length:0,hint:uu?.runId||"latest run"}),G(Xl,{label:"Procedure",value:Array.isArray(uu?.procedureRuns)?uu.procedureRuns.length:0,hint:uu?.status||"no run"}),G(Xl,{label:"Score",value:z9(Tu),hint:Tu?.runId||"selected epoch",tone:Y9(Tu)})),G("div",{className:"panel-actions inline-actions"},G(kr,{title:"Pipeline Snapshot",data:b,onOpen:f,testId:"raw-pipeline-snapshot"}))),G(c0,{title:"评分器",eyebrow:Tu?.runId||"selected epoch",loading:n.loading},G(GY,{run:Tu,onRaw:f})),G(c0,{title:"MiniMax 限额",eyebrow:"model/minimax-m27 quota",loading:n.loading},G(tS,{quota:s,onRaw:f})),G(c0,{title:"OA 事件流",eyebrow:"100% event-driven diagnostics",className:"pipeline-wide-panel",loading:n.loading},G($S,{diagnostics:o,onRaw:f})),G(c0,{title:"组件矩阵",eyebrow:`${Jf.length} classes`,loading:n.loading},Jf.length===0?G(Ar,{title:"暂无组件",text:"等待 D601 pipeline backend 返回 registry.components"}):G("div",{className:"component-strata"},Jf.map((lu)=>G("article",{key:lu.name,className:"component-stratum"},G("span",null,lu.name),G("strong",null,lu.count)))),G("div",{className:"pipeline-component-list"},x.slice(0,12).map((lu)=>G("span",{key:lu.key,className:"data-chip"},G("b",null,lu.componentClass||"--"),G("span",null,lu.id||lu.key||"--"))))),G(c0,{title:"Epoch 列表",eyebrow:`${Wu.length}/${Yl} preview`,loading:n.loading},Wu.length===0?G(Ar,{title:"暂无运行记录",text:"当前 pipeline 在 .state/pipeline-runs 中还没有 epoch。"}):G("div",{className:"pipeline-run-list"},Wu.map((lu)=>{let Ou=String(lu?.runId||"")===Zu?Tu:lu;return G("article",{key:lu.runId,className:`pipeline-run-card ${String(lu.runId||"")===Zu?"active":""}`,role:"button",tabIndex:0,onClick:()=>{c(String(lu.runId||"")),J(Mn())},onKeyDown:(mu)=>{if(mu.key==="Enter"||mu.key===" ")c(String(lu.runId||"")),J(Mn())}},G("div",{className:"node-card-head"},G("strong",null,T9(Wu,lu)),G(xn,{status:lu.status},lu.status||"--")),G("div",{className:"docker-meta compact"},G("span",null,Ou?.pipelineId||"--"),G("span",null,`nodes ${Array.isArray(Ou?.nodes)?Ou.nodes.length:0}`),G("span",null,`oa ${Array.isArray(Ou?.submissions)?Ou.submissions.length:0}`),G("span",null,`procedures ${Array.isArray(Ou?.procedureRuns)?Ou.procedureRuns.length:0}`),G(KY,{run:Ou})),G("p",{className:"muted paragraph"},j8(Ou?.task)),G("span",{className:"pipeline-run-time"},Nu(Ou?.updatedAt)))}))),G(c0,{title:"运行材料索引",eyebrow:Tu?.runId||"selected epoch",className:"pipeline-wide-panel",loading:n.loading},G(_S,{activeRun:Tu,onRaw:f}))))}var z8=Mu(Qf(),1);var _u=z8.default.createElement,{useEffect:jS}=z8.default,K8=z8.default.useState,P9={id:"",sequenceNo:"",contractNo:"",name:"",currentStatus:"",pending:"",paymentStatus:"",notes:""};function FS({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return _u("span",{className:`status-badge ${l}`},f||u||"unknown")}function G8({label:u,value:f,hint:l,tone:r}){return _u("article",{className:`metric-card ${r||""}`},_u("div",{className:"metric-label"},u),_u("div",{className:"metric-value"},f),_u("div",{className:"metric-hint"},l))}function M9({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return _u("section",{className:`panel ${n||""}`},_u("div",{className:"panel-head"},_u("div",null,f?_u("p",{className:"panel-eyebrow"},f):null,_u(nf,{title:u,loading:i})),l?_u("div",{className:"panel-actions"},l):null),_u("div",{className:"panel-body"},r))}function Hw({title:u,data:f,onOpen:l,testId:r}){return _u("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function Bw({title:u,text:f}){return _u("div",{className:"empty-state"},_u("strong",null,u),_u("span",null,f))}function JS(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function US(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function QS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Uy(u,f){return`${u}/microservices/project-manager/proxy${f}`}function qS(u){return{id:String(u.id||""),sequenceNo:u.sequenceNo===null||u.sequenceNo===void 0?"":String(u.sequenceNo),contractNo:String(u.contractNo||""),name:String(u.name||""),currentStatus:String(u.currentStatus||""),pending:String(u.pending||""),paymentStatus:String(u.paymentStatus||""),notes:String(u.notes||"")}}function NS(u){return{sequenceNo:u.sequenceNo===""?null:Number(u.sequenceNo),contractNo:String(u.contractNo||"").trim(),name:String(u.name||"").trim(),currentStatus:String(u.currentStatus||"").trim(),pending:String(u.pending||"").trim(),paymentStatus:String(u.paymentStatus||"").trim(),paymentRatio:String(u.paymentStatus||"").trim(),notes:String(u.notes||"").trim()}}function C9(u){return String(u||"item").replace(/[^A-Za-z0-9_-]+/g,"-")}function WS(u){let f=new Uint8Array(u),l="",r=32768;for(let n=0;n_u("tr",{key:n.id,className:f===n.id?"active-row":"","data-testid":`project-manager-row-${C9(n.id)}`},_u("td",null,n.sequenceNo??"--"),_u("td",null,_u("strong",null,n.contractNo||"--"),_u("code",null,n.id||"--")),_u("td",null,_u("strong",null,n.name||"--"),_u("span",{className:"muted block"},n.sourceFile||"--")),_u("td",null,n.currentStatus||"--"),_u("td",null,_u("span",{className:"preline"},n.pending||"--")),_u("td",null,_u(FS,{status:Number(n.paymentRatio||0)>=1?"online":"warn"},n.paymentStatus||"--")),_u("td",null,n.notes||"--"),_u("td",null,_u("div",{className:"inline-actions"},_u("button",{type:"button",className:"ghost-btn",onClick:()=>l(n),"data-testid":`project-manager-edit-${C9(n.id)}`},"编辑"),_u(Hw,{title:`Project ${n.contractNo||n.id}`,data:n,onOpen:r,testId:`raw-project-${C9(n.id)}`}))))))))}function Vw({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((E)=>E.id==="project-manager")||null,[n,i]=K8({loading:!1,saving:!1,importing:!1,exporting:!1,error:"",notice:"",health:null,list:null,refreshedAt:null}),[y,_]=K8({...P9}),[$,c]=K8(""),[A,j]=K8("all"),{addNotification:F}=Bl();async function U(E=$,D=A){if(!r)return;i((h)=>({...h,loading:!0,error:""}));try{let h=new URLSearchParams({pageSize:"200",status:D});if(E.trim())h.set("q",E.trim());let[B,X]=await Promise.all([Eu(`${l}/microservices/project-manager/health`),Eu(Uy(l,`/api/projects?${h.toString()}`))]);i((m)=>({...m,loading:!1,health:B,list:X,refreshedAt:new Date,error:""}))}catch(h){i((B)=>({...B,loading:!1,error:Hu(h,"Project Manager 加载失败")}))}}jS(()=>{U()},[r?.id,r?.runtime?.providerStatus]);async function Q(E){E.preventDefault(),i((D)=>({...D,saving:!0,error:"",notice:""}));try{let D=NS(y);if(y.id)await Eu(Uy(l,`/api/projects/${encodeURIComponent(y.id)}`),{method:"PUT",body:JSON.stringify(D)});else await Eu(Uy(l,"/api/projects"),{method:"POST",body:JSON.stringify(D)});let h=y.id?"项目已更新":"项目已创建";i((B)=>({...B,saving:!1,notice:h})),F("success",h),await U()}catch(D){i((h)=>({...h,saving:!1,error:Hu(D,"保存项目失败")}))}}async function w(){if(!y.id)return;if(!window.confirm(`删除项目 ${y.contractNo||y.name||y.id} ?`))return;i((E)=>({...E,saving:!0,error:"",notice:""}));try{await Eu(Uy(l,`/api/projects/${encodeURIComponent(y.id)}`),{method:"DELETE"}),_({...P9});let E="项目已删除";i((D)=>({...D,saving:!1,notice:E})),F("success",E),await U()}catch(E){i((D)=>({...D,saving:!1,error:Hu(E,"删除项目失败")}))}}async function L(E){let D=E.target.files?.[0];if(!D)return;i((h)=>({...h,importing:!0,error:"",notice:""}));try{let h=WS(await D.arrayBuffer()),X=`Excel 已导入 ${(await Eu(Uy(l,"/api/import/excel"),{method:"POST",body:JSON.stringify({fileName:D.name,contentBase64:h,replace:!1})})).imported||0} 条项目`;i((m)=>({...m,importing:!1,notice:X})),F("success",X),E.target.value="",await U()}catch(h){i((B)=>({...B,importing:!1,error:Hu(h,"Excel 导入失败")}))}}async function J(){i((E)=>({...E,exporting:!0,error:""}));try{let E=await dJ(Uy(l,"/api/projects/export.xlsx")),D=URL.createObjectURL(E),h=document.createElement("a");h.href=D,h.download=`project-manager-${B7()}.xlsx`,document.body.appendChild(h),h.click(),h.remove(),URL.revokeObjectURL(D),i((B)=>({...B,exporting:!1,notice:"Excel 已导出"}))}catch(E){i((D)=>({...D,exporting:!1,error:Hu(E,"Excel 导出失败")}))}}if(!r)return _u(Bw,{title:"Project Manager 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=project-manager"});let N=JS(r),q=QS(r),W=US(r),z=Array.isArray(n.list?.projects)?n.list.projects:[],Z=n.list?.summary||{},H=n.health||{};return _u("div",{className:"project-manager-page","data-testid":"project-manager-page"},_u(M9,{title:"项目管理工作台",eyebrow:"Main Server PostgreSQL 用户服务",loading:n.loading||n.exporting,actions:_u("div",{className:"panel-actions"},_u("button",{type:"button",className:"ghost-btn",disabled:n.loading,onClick:()=>U(),"data-testid":"project-manager-refresh-button"},n.loading?"刷新中":"刷新"),_u("button",{type:"button",className:"ghost-btn",disabled:n.exporting,onClick:J,"data-testid":"project-manager-export-button"},n.exporting?"导出中":"导出 Excel"),_u(Hw,{title:"Project Manager 用户服务",data:r,onOpen:f,testId:"raw-project-manager-service"}))},_u("div",{className:"project-manager-hero"},_u(G8,{label:"项目总数",value:Z.total??z.length,hint:`PG 表 ${H.storage?.table||"project_manager_projects"}`,tone:"ok"}),_u(G8,{label:"进行中",value:Z.active??"--",hint:"当前状态未完全完成"}),_u(G8,{label:"已完成",value:Z.completed??"--",hint:"按 完成 关键字统计",tone:"ok"}),_u(G8,{label:"未全款",value:Z.unpaid??"--",hint:"付款比例 < 1",tone:Number(Z.unpaid||0)>0?"warn":"ok"})),_u(yf,{error:n.error}),n.notice?_u("div",{className:"form-success"},n.notice):null),_u("div",{className:"project-manager-hero"},_u("div",{className:"microservice-ref-card"},_u("span",null,"Repo"),_u("strong",null,q.url||"--"),_u("code",null,q.commitId||"--")),_u("div",{className:"microservice-ref-card"},_u("span",null,"Main Server Docker"),_u("strong",null,`${W.nodeBindHost||"--"}:${W.nodePort||"--"}`),_u("code",null,`${q.composeService||"--"} / ${q.containerName||"--"}`)),_u("div",{className:"microservice-ref-card"},_u("span",null,"Runtime"),_u("strong",null,N.providerName||r.providerId),_u("code",null,`Health ${H.ok?"OK":"--"} / ${n.refreshedAt?$f(n.refreshedAt):"--"}`)),_u("div",{className:"microservice-ref-card"},_u("span",null,"Import Source"),_u("strong",null,"D601 WeChat Excel"),_u("code",null,"合作项目列表_I_20260309.xlsx"))),_u("div",{className:"project-manager-layout"},_u(M9,{title:"项目清单",eyebrow:"CRUD + Excel Export",loading:n.loading||n.importing||n.exporting,actions:_u("div",{className:"inline-actions project-manager-filters"},_u("input",{value:$,onChange:(E)=>c(E.target.value),placeholder:"搜索合同号 / 项目名称 / 状态","data-testid":"project-manager-search"}),_u("select",{value:A,onChange:(E)=>{j(E.target.value),U($,E.target.value)},"data-testid":"project-manager-status-filter"},_u("option",{value:"all"},"全部"),_u("option",{value:"active"},"进行中"),_u("option",{value:"completed"},"已完成"),_u("option",{value:"unpaid"},"未全款")),_u("button",{type:"button",className:"ghost-btn",onClick:()=>U($,A)},"筛选"))},_u(wS,{projects:z,activeId:y.id,onSelect:(E)=>_(qS(E)),onRaw:f})),_u(M9,{title:y.id?"编辑项目":"新建项目",eyebrow:"PostgreSQL Write Path",loading:n.saving||n.importing},_u("form",{className:"stack-form project-manager-form",onSubmit:Q,"data-testid":"project-manager-form"},y.id?_u("label",null,"项目 ID",_u("input",{value:y.id,disabled:!0})):null,_u("label",null,"序号",_u("input",{type:"number",value:y.sequenceNo,onChange:(E)=>_((D)=>({...D,sequenceNo:E.target.value}))})),_u("label",null,"合同号",_u("input",{value:y.contractNo,onChange:(E)=>_((D)=>({...D,contractNo:E.target.value})),required:!0})),_u("label",null,"项目名称",_u("input",{value:y.name,onChange:(E)=>_((D)=>({...D,name:E.target.value})),required:!0})),_u("label",null,"当前状况",_u("textarea",{value:y.currentStatus,onChange:(E)=>_((D)=>({...D,currentStatus:E.target.value}))})),_u("label",null,"待完成",_u("textarea",{value:y.pending,onChange:(E)=>_((D)=>({...D,pending:E.target.value}))})),_u("label",null,"付款情况",_u("input",{value:y.paymentStatus,onChange:(E)=>_((D)=>({...D,paymentStatus:E.target.value})),placeholder:"例如 1 / 0.5 / 50%"})),_u("label",null,"其它",_u("input",{value:y.notes,onChange:(E)=>_((D)=>({...D,notes:E.target.value}))})),_u("div",{className:"inline-actions"},_u("button",{type:"submit",className:"primary-btn",disabled:n.saving,"data-testid":"project-manager-save-button"},n.saving?"保存中":y.id?"保存修改":"创建项目"),_u("button",{type:"button",className:"ghost-btn",onClick:()=>_({...P9})},"清空"),y.id?_u("button",{type:"button",className:"danger-btn",disabled:n.saving,onClick:w,"data-testid":"project-manager-delete-button"},"删除"):null)),_u("div",{className:"project-manager-import"},_u("p",{className:"muted paragraph"},"浏览器只访问 UniDesk frontend;后端通过同源用户服务代理写入主 PostgreSQL,不暴露 4233 公网端口。"),_u("label",{className:"file-import"},n.importing?"导入中...":"导入 Excel",_u("input",{type:"file",accept:".xlsx",onChange:L,disabled:n.importing,"data-testid":"project-manager-import-input"}))))))}var Z8=Mu(Qf(),1);var cu=Z8.default.createElement,{useEffect:LS}=Z8.default,gl=Z8.default.useState;function KS({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return cu("span",{className:`status-badge ${l}`},f||u||"unknown")}function T8({label:u,value:f,hint:l,tone:r}){return cu("article",{className:`metric-card ${r||""}`},cu("div",{className:"metric-label"},u),cu("div",{className:"metric-value"},f),cu("div",{className:"metric-hint"},l))}function R9({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return cu("section",{className:`panel ${n||""}`},cu("div",{className:"panel-head"},cu("div",null,f?cu("p",{className:"panel-eyebrow"},f):null,cu(nf,{title:u,loading:i})),l?cu("div",{className:"panel-actions"},l):null),cu("div",{className:"panel-body"},r))}function Dw({title:u,data:f,onOpen:l,testId:r}){return cu("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function E8({title:u,text:f}){return cu("div",{className:"empty-state"},cu("strong",null,u),cu("span",null,f))}function GS(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function zS(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function TS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Yw(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function ES(u){if(!Number.isFinite(u))return"--";return`${u.toFixed(1)}%`}function Qy(u,f){return`${u}/microservices/todo-note/proxy${f}`}function Sw(u){return u.reduce((f,l)=>{let r=Sw(Array.isArray(l.children)?l.children:[]),n=Boolean(l.completed);return{total:f.total+1+r.total,completed:f.completed+(n?1:0)+r.completed,active:f.active+(n?0:1)+r.active}},{total:0,completed:0,active:0})}function h9(u,f){let l=f==="all"||(f==="completed"?Boolean(u.completed):!u.completed),r=Array.isArray(u.children)?u.children:[];return l||r.some((n)=>h9(n,f))}function Xw(u){return Array.isArray(u?.instances)?u.instances:[]}function x9(u,f){for(let l of u){if(l?.id===f)return Array.isArray(l.children)?l.children:[];let r=x9(Array.isArray(l?.children)?l.children:[],f);if(r.length>0)return r}return[]}function mw({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((g)=>g.id==="todo-note")||null,[n,i]=gl(null),[y,_]=gl(null),[$,c]=gl(""),[A,j]=gl(null),[F,U]=gl("all"),[Q,w]=gl(13),[L,J]=gl(""),[N,q]=gl(""),[W,z]=gl(""),[Z,H]=gl(""),[E,D]=gl(""),[h,B]=gl(!1),[X,m]=gl(""),[O,p]=gl(null),Y=Xw(y),v=Sw(Array.isArray(A?.todos)?A.todos:[]),T=r?GS(r):{},S=r?TS(r):{},k=r?zS(r):{};async function I(g=$){let[Qu,Tu]=await Promise.all([Eu(`${l}/microservices/todo-note/health`),Eu(Qy(l,"/api/instances"))]);i(Qu),_(Tu);let Zu=Xw(Tu),Xu=Zu.some((ff)=>ff.id===g)?g:Zu[0]?.id||"";return c(Xu),Xu}async function b(g=$){if(!g){j(null);return}let Qu=await Eu(Qy(l,`/api/instances/${encodeURIComponent(g)}`));j(Qu)}async function o(g=$){if(!r)return;B(!0),m("");try{let Qu=await I(g);await b(Qu),p(new Date)}catch(Qu){m(Hu(Qu,"Todo Note 加载失败"))}finally{B(!1)}}async function s(g){if(!$)return null;m("");try{let Qu=await Eu(Qy(l,`/api/instances/${encodeURIComponent($)}/actions`),{method:"POST",body:JSON.stringify({action:g})});return j(Qu),await I($),Qu}catch(Qu){return m(Hu(Qu,"Todo 操作失败")),null}}async function x(g){g.preventDefault();let Qu=L.trim();if(!Qu)return;B(!0),m("");try{let Tu=await Eu(Qy(l,"/api/instances"),{method:"POST",body:JSON.stringify({name:Qu})});J(""),await o(Tu.id)}catch(Tu){m(Hu(Tu,"创建清单失败"))}finally{B(!1)}}async function fu(g){if(!window.confirm("确认删除这个 Todo Note 清单?"))return;B(!0),m("");try{await Eu(Qy(l,`/api/instances/${encodeURIComponent(g)}`),{method:"DELETE"}),await o($===g?"":$)}catch(Qu){m(Hu(Qu,"删除清单失败"))}finally{B(!1)}}async function $u(g){g.preventDefault();let Qu=N.trim();if(!Qu)return;q(""),await s({type:"addTodo",title:Qu})}async function tu(g){if(!$)return;m("");try{let Qu=await Eu(Qy(l,`/api/instances/${encodeURIComponent($)}/${g}`),{method:"POST",body:JSON.stringify({})});j(Qu),await I($)}catch(Qu){m(Hu(Qu,`${g} 失败`))}}function ju(g){z(g.id),H(String(g.title||""))}async function Gu(g){let Qu=Z.trim();if(z(""),H(""),Qu)await s({type:"updateTodoTitle",todoId:g,title:Qu})}async function qu(g){let Tu=window.prompt("新增子任务标题")?.trim();if(!Tu)return;let Zu=x9(Array.isArray(A?.todos)?A.todos:[],g),Xu=new Set(Zu.map((mf)=>mf.id)),ff=await s({type:"addTodo",title:Tu,parentId:g,targetIndex:0});if(!ff)return;let _f=x9(Array.isArray(ff?.todos)?ff.todos:[],g),Jf=_f.find((mf)=>!Xu.has(mf.id));if(Jf&&_f[0]?.id!==Jf.id)await s({type:"moveTodo",todoId:Jf.id,targetParentId:g,targetIndex:0})}async function P(g,Qu){if(!E)return;let Tu={type:"moveTodo",todoId:E,targetIndex:Qu};if(g)Tu.targetParentId=g;D(""),await s(Tu)}if(LS(()=>{o()},[r?.id,r?.runtime?.providerStatus]),!r)return cu(E8,{title:"Todo Note 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=todo-note"});let e=Y.find((g)=>g.id===$)||null,uu=Array.isArray(A?.todos)?A.todos:[],Wu=uu.map((g,Qu)=>({todo:g,index:Qu})).filter((g)=>h9(g.todo,F));return cu("div",{className:"todo-note-page","data-testid":"todo-note-page"},cu(R9,{title:"Todo Note 工作台",eyebrow:"Main Server 用户服务",loading:h,actions:cu("div",{className:"panel-actions"},cu("button",{type:"button",className:"ghost-btn",disabled:h,onClick:()=>o($),"data-testid":"todo-note-refresh-button"},h?"刷新中":"刷新"),cu(Dw,{title:"Todo Note 用户服务",data:r,onOpen:f,testId:"raw-todo-note-service"}))},cu("div",{className:"todo-note-hero"},cu("div",null,cu("div",{className:"node-version-line"},cu(KS,{status:T.providerStatus==="online"?"online":"warn"},T.providerStatus||"unknown"),cu("span",null,r.providerId),cu("span",null,k.public?"公网暴露":"仅 UniDesk frontend 代理访问"),cu("span",null,n?.ok?"Health OK":"Health --")),cu("p",{className:"muted paragraph"},r.description)),cu("div",{className:"microservice-ref-card"},cu("span",null,"Repo"),cu("strong",null,S.url||"--"),cu("code",null,S.commitId||"--")),cu("div",{className:"microservice-ref-card"},cu("span",null,"Main Server Docker"),cu("strong",null,`${k.nodeBindHost||"--"}:${k.nodePort||"--"}`),cu("code",null,`${S.composeService||"--"} / ${S.containerName||"--"}`))),cu(yf,{error:X,wide:!0})),cu("div",{className:"todo-note-layout"},cu(R9,{title:"清单",eyebrow:`${Y.length} Instances`,className:"todo-list-panel",loading:h},cu("form",{className:"todo-create-list",onSubmit:x},cu("input",{placeholder:"新清单名称",value:L,onChange:(g)=>J(g.target.value),"aria-label":"新清单名称"}),cu("button",{type:"submit",className:"ghost-btn",disabled:h||!L.trim()},"创建")),Y.length===0?cu(E8,{title:"暂无清单",text:"迁移或创建清单后会出现在这里"}):cu("div",{className:"todo-instance-list"},Y.map((g)=>cu("button",{key:g.id,type:"button",className:`todo-instance-row ${$===g.id?"active":""}`,onClick:()=>{c(g.id),b(g.id)},"data-testid":`todo-instance-${Yw(g.id)}`},cu("strong",null,g.name),cu("span",null,`${g.completedCount??0}/${g.todoCount??0} 完成`),cu("code",null,g.id))))),cu("div",{className:"todo-main-stack"},cu(R9,{title:e?.name||"待选择清单",eyebrow:O?`Updated ${$f(O)}`:"Todo Tree",loading:h,actions:A?cu("div",{className:"panel-actions"},cu("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"renameInstance",name:window.prompt("清单新名称",A.name)||A.name})},"重命名"),cu("button",{type:"button",className:"ghost-btn danger",onClick:()=>fu($)},"删除清单"),cu(Dw,{title:`Todo Instance ${$}`,data:A,onOpen:f,testId:"raw-todo-instance"})):null},!A?cu(E8,{title:"未选择清单",text:"左侧选择一个 Todo Note 清单"}):cu("div",{className:"todo-workbench",style:{"--todo-font-size":`${Q}px`}},cu("div",{className:"todo-toolbar"},cu("form",{className:"todo-add-form",onSubmit:$u},cu("input",{placeholder:"新增根任务",value:N,onChange:(g)=>q(g.target.value),"aria-label":"新增根任务"}),cu("button",{type:"submit",className:"ghost-btn",disabled:!N.trim()},"新增")),cu("div",{className:"todo-filter-strip"},["all","active","completed"].map((g)=>cu("button",{key:g,type:"button",className:`todo-filter ${F===g?"active":""}`,onClick:()=>U(g)},g==="all"?"全部":g==="active"?"未完成":"已完成"))),cu("div",{className:"todo-toolbar-actions"},cu("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"setAllTodosExpanded",expanded:!0})},"全部展开"),cu("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"setAllTodosExpanded",expanded:!1})},"全部收起"),cu("button",{type:"button",className:"ghost-btn",onClick:()=>tu("undo")},"撤销"),cu("button",{type:"button",className:"ghost-btn",onClick:()=>tu("redo")},"重做"),cu("label",{className:"todo-font-control"},"字号",cu("input",{type:"range",min:11,max:18,value:Q,onChange:(g)=>w(Number(g.target.value))})))),cu("div",{className:"todo-stats-grid"},cu(T8,{label:"总任务",value:v.total,hint:`${Y.length} lists`}),cu(T8,{label:"已完成",value:v.completed,hint:`${ES(v.total?v.completed/v.total*100:0)}`,tone:"ok"}),cu(T8,{label:"未完成",value:v.active,hint:F==="active"?"当前筛选":"active tasks",tone:v.active>0?"warn":"ok"}),cu(T8,{label:"历史指针",value:A.historyPointer??0,hint:"undo / redo"})),cu("div",{className:"todo-root-drop",onDragOver:(g)=>g.preventDefault(),onDrop:(g)=>{g.preventDefault(),P(null,uu.length)}},"拖到这里可移为根任务末尾"),cu("div",{className:"todo-tree","data-testid":"todo-note-tree"},Wu.length===0?cu(E8,{title:"没有匹配任务",text:"调整筛选或新增任务"}):Wu.map(({todo:g,index:Qu})=>cu(pw,{key:g.id,todo:g,depth:0,parentId:null,index:Qu,siblingCount:uu.length,filter:F,editingId:W,editingTitle:Z,setEditingTitle:H,beginEdit:ju,saveEdit:Gu,applyTodoAction:s,addChild:qu,dragTodoId:E,setDragTodoId:D,dropTodo:P}))))))))}function pw(u){let{todo:f,depth:l,parentId:r,index:n,siblingCount:i,filter:y,editingId:_,editingTitle:$,setEditingTitle:c,beginEdit:A,saveEdit:j,applyTodoAction:F,addChild:U,dragTodoId:Q,setDragTodoId:w,dropTodo:L}=u,J=Array.isArray(f.children)?f.children:[],N=J.map((z,Z)=>({child:z,childIndex:Z})).filter((z)=>h9(z.child,y)),q=_===f.id,W=r||null;return cu("div",{className:"todo-row-wrap"},cu("article",{className:`todo-row ${f.completed?"completed":""} ${Q===f.id?"dragging":""}`,style:{"--todo-depth":l},draggable:!0,onDragStart:(z)=>{w(f.id),z.dataTransfer.effectAllowed="move"},onDragOver:(z)=>z.preventDefault(),onDrop:(z)=>{z.preventDefault(),L(f.id,J.length)},"data-testid":`todo-row-${Yw(f.id)}`},cu("button",{type:"button",className:"todo-expand",disabled:J.length===0,onClick:()=>F({type:"toggleTodoExpanded",todoId:f.id})},J.length===0?"·":f.expanded?"▾":"▸"),cu("input",{type:"checkbox",checked:Boolean(f.completed),onChange:()=>F({type:"toggleTodoCompleted",todoId:f.id}),"aria-label":`完成 ${f.title}`}),cu("div",{className:"todo-title-cell",onDoubleClick:()=>A(f)},q?cu("div",{className:"todo-edit-inline"},cu("input",{value:$,autoFocus:!0,onChange:(z)=>c(z.target.value),onKeyDown:(z)=>{if(z.key==="Enter")j(f.id);if(z.key==="Escape")A({id:"",title:""})}}),cu("button",{type:"button",className:"ghost-btn",onClick:()=>j(f.id)},"保存")):cu("strong",null,f.title||"Untitled"),cu("div",{className:"todo-meta-line"},cu("span",null,`子项 ${J.length}`),cu("span",null,`更新 ${Nu(f.updatedAt)}`),f.reminderAt?cu("span",{className:"todo-reminder"},`提醒 ${Nu(f.reminderAt)}`):cu("span",null,"无提醒"))),cu("input",{className:"todo-reminder-input",type:"datetime-local",value:a8(f.reminderAt),onChange:(z)=>F({type:"setTodoReminder",todoId:f.id,reminderAt:V7(z.target.value)})}),cu("div",{className:"todo-row-actions"},cu("button",{type:"button",className:"ghost-btn",onClick:()=>A(f)},"编辑"),cu("button",{type:"button",className:"ghost-btn",onClick:()=>U(f.id)},"子项"),cu("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:n-1})},"上移"),cu("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:0})},"置顶"),cu("button",{type:"button",className:"ghost-btn",disabled:n>=i-1,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:n+1})},"下移"),cu("button",{type:"button",className:"ghost-btn",disabled:!r,onClick:()=>F({type:"moveTodo",todoId:f.id,targetIndex:9999})},"提升"),cu("button",{type:"button",className:"ghost-btn danger",onClick:()=>F({type:"deleteTodo",todoId:f.id})},"删除"))),f.expanded&&N.length>0?cu("div",{className:"todo-children"},N.map(({child:z,childIndex:Z})=>cu(pw,{key:z.id,todo:z,depth:l+1,parentId:f.id,index:Z,siblingCount:J.length,filter:y,editingId:_,editingTitle:$,setEditingTitle:c,beginEdit:A,saveEdit:j,applyTodoAction:F,addChild:U,dragTodoId:Q,setDragTodoId:w,dropTodo:L}))):null)}var Pw=Mu(Qf(),1),bn=Pw.default.createElement;function Mw({title:u,items:f,actions:l,className:r,testId:n}){let i=Array.isArray(f)?f:[];return bn("section",{className:`top-status-bar ${r||""}`,"data-testid":n},bn("div",{className:"top-status-main"},u?bn("strong",{className:"top-status-title"},u):null,bn("div",{className:"top-status-chips"},i.map((y,_)=>bn("span",{key:y?.key||`${y?.label||"status"}-${_}`,className:`top-status-chip ${y?.tone||""}`,"data-testid":y?.testId},y?.label?bn("b",null,y.label):null,bn("span",null,y?.value??"--"))))),l?bn("div",{className:"top-status-actions"},l):null)}var S$=Mu(Qf(),1);var hf=S$.default.createElement;function Cw({onClose:u}){let{notifications:f,removeNotification:l,clearNotifications:r}=Bl(),n=S$.default.useRef(null);if(S$.default.useEffect(()=>{let i=(y)=>{if(n.current&&!n.current.contains(y.target))u()};return document.addEventListener("mousedown",i),()=>document.removeEventListener("mousedown",i)},[u]),f.length===0)return hf("div",{className:"notification-popup",ref:n},hf("div",{className:"notification-popup-header"},hf("span",null,"通知"),hf("button",{className:"notification-popup-close",onClick:u},"×")),hf("div",{className:"notification-popup-empty"},"暂无通知"));return hf("div",{className:"notification-popup",ref:n},hf("div",{className:"notification-popup-header"},hf("span",null,`通知 (${f.length})`),hf("div",{className:"notification-popup-actions"},hf("button",{className:"notification-popup-clear",onClick:r},"清空"),hf("button",{className:"notification-popup-close",onClick:u},"×"))),hf("div",{className:"notification-popup-list"},f.slice().reverse().map((i)=>hf("div",{key:i.id,className:`notification-item ${i.type}`},hf("span",{className:"notification-item-icon"},i.type==="success"?"✓":"×"),hf("span",{className:"notification-item-message"},i.message),hf("button",{className:"notification-item-dismiss",onClick:()=>l(i.id)},"×")))))}function Rw({notification:u}){let{removeNotification:f}=Bl();return S$.default.useEffect(()=>{let l=setTimeout(()=>{f(u.id)},3000);return()=>clearTimeout(l)},[u.id,f]),hf("div",{className:`notification-banner ${u.type}`,role:"alert"},hf("span",{className:"notification-banner-icon"},u.type==="success"?"✓":"×"),hf("span",{className:"notification-banner-message"},u.message),hf("button",{className:"notification-banner-dismiss",onClick:()=>f(u.id)},"×"))}function ew(u,f){let l=document.getElementById("root")?.getAttribute(u);if(!l)return f;try{let r=JSON.parse(l);return typeof r==="object"&&r!==null&&!Array.isArray(r)?r:f}catch{return f}}var gu=ew("data-config",{apiBaseUrl:"/api",authUsername:"admin"}),ZS=ew("data-codex-overview",null),t=kn.default.createElement,{useEffect:j0,useMemo:P$}=kn.default,bu=kn.default.useState,I9=kn.default.createContext(!1),Or=pQ(u6),OS={id:"code-queue",name:"Code Queue",providerId:"main-server",description:"Code Queue",repository:{containerName:"code-queue-backend"},backend:{nodeBaseUrl:"http://code-queue:4222",nodeBindHost:"code-queue",nodePort:4222,public:!1},runtime:{providerStatus:"loading",providerName:"main-server"}};function xw(){return typeof document>"u"||document.visibilityState!=="hidden"}function HS(u,f){if(u==="ops"&&f==="status")return 5000;if(u==="nodes"&&f==="monitor")return 5000;if(u==="tasks"&&(f==="dispatch"||f==="scheduled"||f==="pending"))return 5000;if(u==="nodes"||u==="ops")return 1e4;if(u==="apps")return 15000;if(u==="tasks")return 15000;return 30000}async function BS(u){if(!u?._summaryOnly||!u?.id)return u;return(await Eu(`${gu.apiBaseUrl}/tasks/${encodeURIComponent(String(u.id))}`))?.task||u}function M$(u){return u?._summaryOnly?{...u,_loadRaw:()=>BS(u)}:u}function x0(u){if(!Number.isFinite(u))return"--";let f=Math.max(0,u);if(f===0)return"0s";if(f<0.01)return"<0.01s";if(f<0.1)return`${f.toFixed(2)}s`;if(f<1)return`${f.toFixed(1)}s`;if(f<10&&!Number.isInteger(f))return`${f.toFixed(1)}s`;if(f<60)return`${Math.round(f)}s`;let l=Math.floor(f);if(l<3600)return`${Math.floor(l/60)}m ${l%60}s`;return`${Math.floor(l/3600)}h ${Math.floor(l%3600/60)}m`}function jr(u){let f=Number(u);if(!Number.isFinite(f))return"--";if(f<1)return`${Math.max(0,f).toFixed(1)}ms`;if(f<10)return`${f.toFixed(1)}ms`;if(f<1000)return`${Math.round(f)}ms`;return x0(f/1000)}function Ll(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=["B","KB","MB","GB","TB"],r=f,n=0;while(r>=1024&&n0)return l[r]}return"任务失败但 provider 未返回明确原因"}function R1(u){if(u===null||u===void 0)return"--";if(typeof u==="boolean")return u?"是":"否";if(typeof u==="number")return String(u);if(typeof u==="string")return u.length>80?`${u.slice(0,77)}...`:u;if(Array.isArray(u))return`${u.length} 项`;if(typeof u==="object")return`${Object.keys(u).length} 字段`;return String(u)}function DS(u,f){let l=u.replace(/[-_\s]/g,"").toLowerCase(),r=l==="ts"||l.endsWith("at")||l.endsWith("timestamp")||l.endsWith("heartbeat");if((typeof f==="string"||typeof f==="number")&&r){let n=Nu(f);if(n!=="--")return n}if(u==="bodyText"&&typeof f==="string")return`${/^\s*[{[]/.test(f)?"JSON":"HTTP"} body ${f.length} chars`;return R1(f)}function lL(u){if(!u||typeof u!=="object"||Array.isArray(u))return[];return Object.entries(u)}function sl(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function s9(u,f){return u&&typeof u==="object"&&!Array.isArray(u)?u[f]:void 0}function H8(u,f,l="未知"){let r=s9(u?.labels,f);return typeof r==="string"&&r.length>0?r:l}function rL(u){return H8(u,"providerGatewayVersion")}function p$(u){return H8(u,"providerGatewayUpgradePolicy")}function hw(u){return H8(u,"providerGatewayStartedAt","")}function nL(u){let f=s9(u?.labels,"unideskCapabilities");if(typeof f==="string")return f.split(",").map((l)=>l.trim()).filter(Boolean);return Array.isArray(f)?f.filter((l)=>typeof l==="string"):[]}function iL(u,f){return nL(u).includes(f)}function bw(u,f){let l=s9(u?.labels,f);return l===!0||l==="true"||l==="1"}function XS(u){if(!iL(u,"host.ssh"))return{tone:"fail",label:"不可用",detail:"未声明 host.ssh"};if(!bw(u,"hostSshConfigured"))return{tone:"warn",label:"未配置",detail:"缺少 SSH 环境变量"};if(!bw(u,"hostSshKeyPresent"))return{tone:"warn",label:"缺 key",detail:"私钥未挂载"};return{tone:"ok",label:"可用",detail:H8(u,"hostSshTarget","host.ssh ready")}}function YS(u){if(!iL(u,"provider.upgrade"))return{tone:"fail",label:"不可用",detail:"未声明 provider.upgrade"};let f=p$(u);if(f!=="always-enabled")return{tone:"warn",label:"待确认",detail:`策略 ${f}`};return{tone:"ok",label:"可用",detail:"always-enabled"}}function a9(u){let f=typeof u==="string"&&u.length>0?u:"未知";if(f==="未知")return"版本未知";return f.startsWith("v")?f:`v${f}`}function yL(u){return u?.payload&&typeof u.payload==="object"&&!Array.isArray(u.payload)?u.payload:{}}function B8(u){return u?.result&&typeof u.result==="object"&&!Array.isArray(u.result)?u.result:{}}function O8(u){let f=yL(u),l=B8(u);return(f.mode??l.mode)==="schedule"?"schedule":"plan"}function SS(u){let f=yL(u).source;return typeof f==="string"&&f.length>0?f:"unknown"}function mS(u){let f=B8(u),l=f.plan&&typeof f.plan==="object"&&!Array.isArray(f.plan)?f.plan:{},r=f.policy??l.policy;return typeof r==="string"&&r.length>0?r:"--"}function _L(u){let f=B8(u),l=f.plan&&typeof f.plan==="object"&&!Array.isArray(f.plan)?f.plan:{},r=f.targetProviderGatewayVersion??f.providerGatewayVersion??l.targetProviderGatewayVersion??l.providerGatewayVersion;return typeof r==="string"&&r.length>0?a9(r):"版本未知"}function $L(u){if(String(u?.status||"").toLowerCase()==="failed")return fL(u);if(Ny(u))return"等待 provider 回传升级终态";let l=B8(u);if(typeof l.updaterContainerId==="string"&&l.updaterContainerId.length>0)return`updater ${l.updaterContainerId.slice(0,18)}`;if(typeof l.message==="string"&&l.message.length>0)return l.message;if(l.plan)return"升级计划已生成";return"无升级结果摘要"}function tL(u,f){return u.filter((l)=>l?.providerId===f&&l?.command==="provider.upgrade").sort((l,r)=>(F0(r.updatedAt)??0)-(F0(l.updatedAt)??0))}function pS(u){return u.find((f)=>O8(f)==="schedule")||u[0]||null}function cL(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function vw(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function PS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Wf({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return t("span",{className:`status-badge ${l}`},f||u||"unknown")}function cf({label:u,value:f,hint:l,tone:r,onClick:n,testId:i}){let y=typeof n==="function";return t("article",{className:`metric-card ${r||""} ${y?"clickable":""}`,role:y?"button":void 0,tabIndex:y?0:void 0,"data-testid":i,onClick:n,onKeyDown:y?(_)=>{if(_.key==="Enter"||_.key===" ")_.preventDefault(),n()}:void 0},t("div",{className:"metric-label"},u),t("div",{className:"metric-value"},f),t("div",{className:"metric-hint"},l))}function au({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){let y=kn.default.useContext(I9),_=Boolean(i)||y;return t("section",{className:`panel ${n||""}`},t("div",{className:"panel-head"},t("div",null,f?t("p",{className:"panel-eyebrow"},f):null,t(nf,{title:u,loading:_})),l?t("div",{className:"panel-actions"},l):null),t("div",{className:"panel-body"},r))}function bf({title:u,data:f,onOpen:l,testId:r}){let[n,i]=bu(!1),y=f&&typeof f==="object"&&typeof f._loadRaw==="function"?f._loadRaw:null;async function _(){if(!y){l(u,f);return}i(!0);try{l(u,await y())}catch($){l(u,{ok:!1,error:Hu($,"读取原始 JSON 失败"),fallback:f})}finally{i(!1)}}return t("button",{type:"button",className:"ghost-btn","data-testid":r,disabled:n,onClick:()=>void _()},n?"读取中":"查看原始JSON")}function MS({raw:u,onClose:f}){if(!u)return null;return t("div",{className:"modal-backdrop",role:"presentation"},t("section",{className:"raw-dialog",role:"dialog","aria-modal":"true","aria-label":u.title},t("div",{className:"raw-dialog-head"},t("h2",null,u.title),t("button",{type:"button",className:"ghost-btn",onClick:f},"关闭")),t("pre",{className:"raw-json","data-testid":"raw-json"},JSON.stringify(u.data,null,2))))}function AL({labels:u,limit:f=8}){let l=lL(u).slice(0,f);if(l.length===0)return t("span",{className:"muted"},"无标签");return t("div",{className:"chip-row"},l.map(([r,n])=>t("span",{key:r,className:"data-chip"},t("b",null,r),t("span",null,R1(n)))))}function qy({node:u}){let f=rL(u);return t("span",{className:`version-chip ${f==="未知"?"unknown":""}`,"data-testid":`gateway-version-${sl(u?.providerId||"unknown")}`},a9(f))}function kw({title:u,state:f,testId:l}){return t("span",{className:`capability-badge ${f.tone}`,title:f.detail,"data-testid":l},t("b",null,u),t("strong",null,f.label),t("small",null,f.detail))}function o9({node:u}){let f=sl(u?.providerId||"unknown");return t("div",{className:"node-availability-strip"},t(kw,{title:"SSH 透传",state:XS(u),testId:`ssh-availability-${f}`}),t(kw,{title:"远程更新",state:YS(u),testId:`upgrade-availability-${f}`}))}function In({data:u,empty:f="无数据"}){if(u===null||u===void 0)return t("span",{className:"muted"},f);if(typeof u!=="object")return t("span",{className:"summary-value"},R1(u));if(Array.isArray(u))return t("span",{className:"summary-value"},`${u.length} 项列表`);let l=Object.entries(u).slice(0,5);if(l.length===0)return t("span",{className:"muted"},f);return t("div",{className:"summary-grid"},l.map(([r,n])=>t("span",{key:r,className:"summary-item"},t("b",null,r),t("span",null,DS(r,n)))))}function Ff({title:u,text:f}){return t("div",{className:"empty-state"},t("strong",null,u),t("span",null,f))}function CS({onLogin:u}){let[f,l]=bu(gu.authUsername||"admin"),[r,n]=bu(""),[i,y]=bu(""),[_,$]=bu(!1);async function c(A){A.preventDefault(),$(!0),y("");try{let j=await Eu("/login",{method:"POST",body:JSON.stringify({username:f,password:r})});u(j)}catch(j){y(Hu(j,"登录失败"))}finally{$(!1)}}return t("main",{className:"login-screen","data-testid":"login-screen"},t("section",{className:"login-card"},t("div",{className:"login-brand"},t("span",{className:"brand-mark"},"UD"),t("div",null,t("h1",null,"UniDesk"),t("p",null,"Control Plane Login"))),t("form",{className:"login-form",onSubmit:c},t("label",null,"账号",t("input",{name:"username",autoComplete:"username",value:f,onChange:(A)=>l(A.target.value)})),t("label",null,"密码",t("input",{name:"password",type:"password",autoComplete:"current-password",value:r,onChange:(A)=>n(A.target.value)})),t(yf,{error:i}),t("button",{type:"submit",disabled:_},_?"登录中":"登录")),t("div",{className:"login-note"},"默认账号由 config.json 注入;公网入口只暴露前端登录面。")))}function RS({connection:u,lastRefresh:f,onRefresh:l,onLogout:r,session:n,clock:i,activeStatusItems:y=[],onNotificationToggle:_,unreadCount:$=0}){let c=[{key:"core",label:"核心",value:u.text,tone:u.ok?"ok":"fail",testId:"conn-text"},...Array.isArray(y)?y:[],{key:"refresh",label:"刷新",value:f?$f(f):"未刷新"},{key:"clock",label:it,value:$f(i)},{key:"user",label:"用户",value:n?.user?.username||"--",tone:"user"}];return t("header",{className:"topbar"},t("div",null,t("p",{className:"eyebrow"},"Distributed Work Platform"),t("h1",null,"UniDesk 控制平面")),t(Mw,{className:"global-top-status",title:"状态",items:c,actions:[t("button",{key:"notification",type:"button",className:`notification-icon-btn ${$>0?"has-unread":""}`,onClick:_,"aria-label":"通知"},"\uD83D\uDD14",$>0?t("span",{key:"badge",className:"notification-badge"},$>99?"99+":$):null),t("button",{key:"refresh",type:"button",className:"ghost-btn",onClick:l},"刷新"),t("button",{key:"logout",type:"button",className:"ghost-btn danger",onClick:r},"退出")]}))}function xS(u){return!u.defaultPrevented&&u.button===0&&!u.metaKey&&!u.altKey&&!u.ctrlKey&&!u.shiftKey&&u.currentTarget.target!=="_blank"}function jL({moduleId:u,tabId:f,className:l,active:r=!1,title:n,testId:i,onNavigate:y,children:_}){let $=f6(Or,u,f);return t("a",{href:$,role:"button",className:l,title:n,"aria-current":r?"page":void 0,"data-testid":i,"data-route":$,onClick:(c)=>{if(!xS(c))return;c.preventDefault(),y(u,f)}},_)}function hS({activeModule:u,activeTabs:f,onNavigate:l,collapsed:r,onToggle:n}){return t("aside",{className:`rail ${r?"collapsed":""}`,"aria-label":"主模块"},t("div",{className:"brand"},t("span",{className:"brand-mark"},"UD"),t("span",{className:"brand-text"},"UniDesk"),t("button",{type:"button",className:"rail-toggle",onClick:n,"aria-label":r?"展开左侧边栏":"收起左侧边栏","data-testid":"rail-toggle"},r?"»":"«")),u6.map((i)=>{let y=f[i.id]||b_[i.id]||i.tabs[0]?.id||"";return t(jL,{key:i.id,moduleId:i.id,tabId:y,className:`module ${u===i.id?"active":""}`,active:u===i.id,title:i.label,onNavigate:l},t("span",{className:"module-code"},i.code),t("span",null,i.label))}))}function bS({module:u,activeTab:f,onNavigate:l}){return t("nav",{className:"tabs","aria-label":`${u.label} 子功能`},u.tabs.map((r)=>t(jL,{key:r.id,moduleId:u.id,tabId:r.id,className:`tab ${f===r.id?"active":""}`,active:f===r.id,onNavigate:l},r.label)))}function vS({data:u,onRaw:f,onNavigate:l}){let r=u.overview||{},n=u.nodes.filter((U)=>U.status==="online"),i=u.pendingTasks||u.tasks.filter(Ny),y=r.pendingTaskCount??i.length,_=u.tasks.slice(0,5),$=r.pgdata||{},c=r.microserviceAvailability||{},A=Cu(c.totalCount),j=Cu(c.healthyCount),F=Cu(c.unhealthyCount);return t("div",{className:"page-grid overview-grid","data-testid":"overview-page"},t(au,{title:"核心指标",eyebrow:"Control"},t("div",{className:"metric-grid"},t(cf,{label:"数据库",value:r.dbReady?"READY":"WAIT",hint:"PostgreSQL internal network",tone:r.dbReady?"ok":"warn"}),t(cf,{label:"PGDATA",value:Ll($.databaseBytes),hint:`${$.volumeName||"unidesk_pgdata_10gb"} / ${$.databasePretty||"--"}`,tone:"ok",testId:"pgdata-usage-card"}),t(cf,{label:"在线节点",value:r.onlineNodeCount??0,hint:`${r.nodeCount??0} registered`,tone:"ok"}),t(cf,{label:"WebSocket",value:r.activeSocketCount??0,hint:"Provider ingress sockets"}),t(cf,{label:"用户服务可用",value:A>0?`${j}/${A}`:"--",hint:A>0?`healthyCount ${j} · unhealthyCount ${F}`:"strict /health probes",tone:A>0&&F===0?"ok":"warn",testId:"microservice-availability-card"}),t(cf,{label:"待处理任务",value:y,hint:y>0?"点击查看具体任务":`timeout ${x0(Math.floor((r.taskPendingTimeoutMs??0)/1000))}`,tone:y>0?"warn":"ok",onClick:()=>l("tasks","pending"),testId:"pending-task-card"}))),t(au,{title:"本机 Provider",eyebrow:"Self Connected"},n.length===0?t(Ff,{title:"暂无在线节点",text:"provider-gateway 未完成自接入"}):t("div",{className:"node-card-list"},n.slice(0,4).map((U)=>t(kS,{key:U.providerId,node:U,onRaw:f})))),t(au,{title:"待处理任务明细",eyebrow:`${y} Pending`,actions:t("button",{type:"button",className:"ghost-btn",onClick:()=>l("tasks","pending"),"data-testid":"pending-task-detail-link"},"进入任务调度")},i.length===0?t(Ff,{title:"当前无待处理",text:"queued / dispatched / running 超时后会自动转为 failed,避免总览长期卡住"}):t("div",{className:"compact-list"},i.slice(0,5).map((U)=>t(aw,{key:U.id,task:U,onRaw:f})))),t(au,{title:"最近任务",eyebrow:"Dispatch"},_.length===0?t(Ff,{title:"暂无任务",text:"可以在任务调度模块发起 docker.ps 或 echo"}):t("div",{className:"compact-list"},_.map((U)=>t(aw,{key:U.id,task:U,onRaw:f})))))}function kS({node:u,onRaw:f}){return t("article",{className:"node-card"},t("div",{className:"node-card-head"},t("div",null,t("strong",null,u.name),t("code",null,u.providerId)),t(Wf,{status:u.status})),t("div",{className:"node-version-line"},t(qy,{node:u}),t("span",null,`升级策略 ${p$(u)}`)),t(o9,{node:u}),t(AL,{labels:u.labels,limit:6}),t("div",{className:"node-card-foot"},t("span",null,`心跳 ${Nu(u.lastHeartbeat)}`),t(bf,{title:`Provider ${u.providerId}`,data:u,onOpen:f,testId:`raw-node-${sl(u.providerId)}`})))}function IS({events:u,onRaw:f}){return t(au,{title:"事件摘要",eyebrow:"Latest 100"},u.length===0?t(Ff,{title:"暂无事件",text:"Provider 注册、心跳超时和任务状态会写入事件流"}):t("div",{className:"table-wrap"},t("table",null,t("thead",null,t("tr",null,t("th",null,"ID"),t("th",null,"类型"),t("th",null,"来源"),t("th",null,"摘要"),t("th",null,"时间"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.id},t("td",null,t("code",null,l.id)),t("td",null,t(Wf,{status:l.type},l.type)),t("td",null,t("code",null,l.source)),t("td",null,t(In,{data:l.payload})),t("td",null,Nu(l.createdAt)),t("td",null,t(bf,{title:`Event ${l.id}`,data:l,onOpen:f}))))))))}function gS({logs:u,onRaw:f}){return t(au,{title:"服务日志",eyebrow:"Core Recent"},u.length===0?t(Ff,{title:"暂无日志",text:"backend-core 内存日志会在请求和 provider 事件后出现"}):t("div",{className:"log-list"},u.slice(-80).reverse().map((l,r)=>t("article",{key:r,className:`log-row ${l.level||"info"}`},t("span",null,Nu(l.ts)),t("b",null,l.level||"info"),t("strong",null,l.message||"log"),t(In,{data:l.data,empty:"无附加字段"}),t(bf,{title:`Log ${l.message||r}`,data:l,onOpen:f})))))}function sS({nodes:u,onRaw:f}){return t(au,{title:"节点清单",eyebrow:`${u.length} Providers`},u.length===0?t(Ff,{title:"暂无 Provider 节点",text:"确认 provider-gateway 已连接 provider ingress"}):t("div",{className:"table-wrap"},t("table",{className:"node-list-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"Provider"),t("th",null,"网关版本"),t("th",null,"运维可用性"),t("th",null,"资源标签"),t("th",null,"连接时间"),t("th",null,"最后心跳"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.providerId},t("td",null,t(Wf,{status:l.status})),t("td",null,t("strong",null,l.name),t("code",null,l.providerId)),t("td",null,t("div",{className:"gateway-cell"},t(qy,{node:l}),t("span",null,p$(l)))),t("td",null,t(o9,{node:l})),t("td",null,t(AL,{labels:l.labels,limit:5})),t("td",null,Nu(l.connectedAt)),t("td",null,Nu(l.lastHeartbeat)),t("td",null,t(bf,{title:`Provider ${l.providerId}`,data:l,onOpen:f,testId:`raw-node-table-${sl(l.providerId)}`}))))))))}function aS({nodes:u}){let f=P$(()=>{let l=[];for(let r of u)for(let[n,i]of lL(r.labels))l.push({providerId:r.providerId,name:r.name,key:n,value:i});return l},[u]);return t(au,{title:"资源标签",eyebrow:"Structured Labels"},f.length===0?t(Ff,{title:"暂无标签",text:"provider-gateway 注册消息会同步资源标签"}):t("div",{className:"label-matrix"},f.map((l)=>t("article",{key:`${l.providerId}-${l.key}`,className:"label-card"},t("span",null,l.key),t("strong",null,R1(l.value)),t("code",null,l.providerId)))))}function oS({nodes:u}){return t(au,{title:"心跳状态",eyebrow:"Provider Liveness"},u.length===0?t(Ff,{title:"无心跳",text:"等待 provider 注册和 heartbeat"}):t("div",{className:"heartbeat-list"},u.map((f)=>t("article",{key:f.providerId,className:"heartbeat-row"},t("span",{className:`pulse ${f.status}`}),t("div",null,t("strong",null,f.name),t("code",null,f.providerId)),t("div",null,t("span",null,"connected"),t("b",null,Nu(f.connectedAt))),t("div",null,t("span",null,"last heartbeat"),t("b",null,Nu(f.lastHeartbeat)))))))}function dS({nodes:u,systemStatuses:f,tasks:l,onRaw:r,refresh:n}){let[i,y]=bu(""),_=P$(()=>u.map((w)=>{let L=f.find((J)=>J.providerId===w.providerId);return{...w,systemCurrent:L?.current||null,systemHistory:L?.history||[],systemUpdatedAt:L?.updatedAt||null}}),[u,f]),$=_.find((w)=>w.providerId===i)||_[0]||null;if(j0(()=>{if(!i&&_[0])y(_[0].providerId)},[_.length,i]),!$)return t(Ff,{title:"暂无资源监控",text:"等待 provider 上报 CPU、内存和硬盘指标"});let c=$.systemCurrent,A=$.systemHistory||[],j=c?.cpu||{},F=c?.memory||{},U=c?.disk||{},Q=A.length>0?A:c?[{at:c.collectedAt,cpuPercent:Cu(j.percent),memoryPercent:Cu(F.percent),diskPercent:Cu(U.percent)}]:[];return t("div",{className:"monitor-page","data-testid":"node-monitor-page"},t("div",{className:"docker-node-strip"},_.map((w)=>t("button",{key:w.providerId,type:"button",className:`docker-node-tile ${$.providerId===w.providerId?"active":""}`,onClick:()=>y(w.providerId)},t("span",{className:`pulse ${w.status}`}),t("strong",null,w.name),t("code",null,w.providerId),t("span",null,w.systemCurrent?`CPU ${vn(w.systemCurrent.cpu?.percent)} / MEM ${vn(w.systemCurrent.memory?.percent)}`:"等待指标")))),t("div",{className:"monitor-layout"},t(au,{title:"任务管理器视图",eyebrow:$.name,className:"monitor-main-panel",actions:c?t(bf,{title:`System ${$.providerId}`,data:{current:c,history:A},onOpen:r}):null},!c?t(Ff,{title:"系统指标未上报",text:"provider-gateway 会周期性采集 /proc 与 df,并保存历史曲线"}):t("div",null,t("div",{className:"monitor-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Node Performance"),t("h3",null,$.name),t("div",{className:"docker-meta"},t("span",null,`${j.cores||0} CPU cores`),t("span",null,`load ${Cu(j.load1).toFixed(2)} / ${Cu(j.load5).toFixed(2)} / ${Cu(j.load15).toFixed(2)}`),t("span",null,`memory actual ${Ll(F.usedBytes)} / ${Ll(F.totalBytes)}`),t("span",null,`disk ${Ll(U.usedBytes)} / ${Ll(U.totalBytes)}`))),t(Wf,{status:c.ok?"online":"warn"},c.ok?"METRICS READY":"METRICS DEGRADED")),t("div",{className:"monitor-chart-grid"},t(v9,{title:"CPU",metricKey:"cpuPercent",current:j.percent,points:Q,detail:`${j.cores||0} cores / load ${Cu(j.load1).toFixed(2)}`,tone:"cpu",testId:"metric-chart-cpu"}),t(v9,{title:"Memory",metricKey:"memoryPercent",current:F.percent,points:Q,detail:`${Ll(F.usedBytes)} actual / ${Ll(F.cacheBytes)} cache excluded`,tone:"memory",testId:"metric-chart-memory"}),t(v9,{title:"Disk",metricKey:"diskPercent",current:U.percent,points:Q,detail:`${U.path||"/"} mounted ${U.mount||"--"}`,tone:"disk",testId:"metric-chart-disk"})),t("div",{className:"monitor-summary-grid"},t(cf,{label:"CPU 当前",value:vn(j.percent),hint:`history ${Q.length} samples`,tone:"ok"}),t(cf,{label:"实际内存",value:Ll(F.usedBytes),hint:`${vn(F.percent)} 不含缓存`}),t(cf,{label:"硬盘已用",value:Ll(U.usedBytes),hint:vn(U.percent)}),t(cf,{label:"更新时间",value:Nu($.systemUpdatedAt||c.collectedAt),hint:$.providerId})),t(eS,{current:c,onRaw:r}))),t("div",{className:"monitor-side-stack"},t(_m,{provider:$,refresh:n,onRaw:r}),t($m,{provider:$,tasks:l,onRaw:r,limit:5}),t(au,{title:"采样说明",eyebrow:"Retention"},t("div",{className:"monitor-note-list"},t("article",null,t("b",null,"CPU"),t("span",null,"从 /proc/stat 计算相邻采样差值,首个采样用 load/cores 近似")),t("article",null,t("b",null,"Memory"),t("span",null,"实际内存 = MemTotal - MemFree - Buffers - Cached - SReclaimable + Shmem,不把 page cache / buffer 计入占用")),t("article",null,t("b",null,"Disk"),t("span",null,"使用 df -PB1 对配置路径采样,默认监控根文件系统")),t("article",null,t("b",null,"Process"),t("span",null,"从 /proc/[pid] 采集进程 CPU、实际内存 RSS、线程数和磁盘 I/O 速率;表格默认按内存占用降序")))))))}function Iw(u,f){if(f==="memory")return Cu(u.rssBytes);if(f==="cpu")return Cu(u.cpuPercent);if(f==="disk")return Cu(u.readBytesPerSecond)+Cu(u.writeBytesPerSecond);if(f==="pid")return Cu(u.pid);if(f==="threads")return Cu(u.threads);if(f==="runtime")return Cu(u.elapsedSeconds);if(f==="user")return String(u.user||"");return String(u.name||u.command||"")}function gw({value:u,label:f,tone:l}){let r=Math.max(1,Math.min(100,Cu(u)));return t("div",{className:`process-meter ${l||""}`},t("span",{style:{width:`${r}%`}}),t("b",null,f))}function eS({current:u,onRaw:f}){let[l,r]=bu({key:"memory",direction:"desc"}),n=kn.default.useContext(I9),i=u?.processSummary&&typeof u.processSummary==="object"?u.processSummary:{},y=Array.isArray(u?.processes)?u.processes:[],_=P$(()=>{let c=l.direction==="asc"?1:-1;return[...y].sort((A,j)=>{let F=Iw(A,l.key),U=Iw(j,l.key);if(typeof F==="string"||typeof U==="string")return String(F).localeCompare(String(U),"zh-CN")*c;return(F-U)*c||Cu(A.pid)-Cu(j.pid)})},[y,l.key,l.direction]),$=(c,A)=>{let j=l.key===A,F=j?l.direction==="asc"?"ascending":"descending":"none";return t("th",{"aria-sort":F},t("button",{type:"button",className:`process-sort-button ${j?"active":""}`,"data-testid":`process-sort-${A}`,onClick:()=>r((U)=>({key:A,direction:U.key===A&&U.direction==="desc"?"asc":"desc"}))},c,t("span",null,j?l.direction==="desc"?"↓":"↑":"↕")))};return t("section",{className:"process-resource-panel","data-testid":"process-resource-panel"},t("div",{className:"process-resource-head"},t("div",null,t("p",{className:"panel-eyebrow"},"Windows Resource Monitor Style"),t(nf,{title:"进程资源占用",level:3,loading:n})),t("div",{className:"process-resource-actions"},t("span",{className:"data-chip"},"默认按内存排序"),t("span",{className:"data-chip"},`${Cu(i.visible,_.length)} / ${Cu(i.total,_.length)} 进程`),t(bf,{title:"Process Resource Snapshot",data:{processSummary:i,processes:y},onOpen:f,testId:"raw-process-resources"}))),_.length===0?t(Ff,{title:"暂无进程资源数据",text:"等待 provider-gateway 上报 /proc/[pid] 采样;旧版 provider 需要先升级到支持进程资源表的版本"}):t("div",{className:"process-table-wrap"},t("table",{className:"process-resource-table","data-testid":"process-resource-table"},t("thead",null,t("tr",null,$("进程","name"),$("PID","pid"),$("用户","user"),t("th",null,"状态"),$("CPU","cpu"),$("内存","memory"),t("th",null,"RSS"),$("磁盘 I/O","disk"),$("线程","threads"),$("运行时长","runtime"))),t("tbody",null,_.map((c)=>{let A=Cu(c.readBytesPerSecond)+Cu(c.writeBytesPerSecond);return t("tr",{key:`${c.pid}-${c.startedAt}`,"data-testid":`process-row-${sl(c.pid)}`,"data-memory-bytes":String(Cu(c.rssBytes)),"data-cpu-percent":String(Cu(c.cpuPercent)),"data-disk-bps":String(A),"data-pid":String(Cu(c.pid))},t("td",null,t("div",{className:"process-name-cell"},t("strong",null,c.name||"--"),t("span",{className:"process-command"},c.command||"--"))),t("td",null,t("code",null,c.pid||"--")),t("td",null,c.user||`uid:${c.uid??"--"}`),t("td",null,t("span",{className:`process-state state-${sl(c.state||"unknown")}`},c.state||"?")),t("td",null,t(gw,{value:c.cpuPercent,label:VS(c.cpuPercent),tone:"cpu"})),t("td",null,t(gw,{value:c.memoryPercent,label:vn(c.memoryPercent),tone:"memory"})),t("td",null,Ll(c.rssBytes)),t("td",null,t("div",{className:"process-io-cell"},t("strong",null,b9(A)),t("span",null,`R ${b9(c.readBytesPerSecond)} / W ${b9(c.writeBytesPerSecond)}`))),t("td",null,c.threads||0),t("td",null,x0(Cu(c.elapsedSeconds))))})))))}function v9({title:u,metricKey:f,current:l,points:r,detail:n,tone:i,testId:y}){let _=r.map((F)=>Math.max(0,Math.min(100,Cu(F[f])))),$=_.length>1?_:[_[0]||0,_[0]||0],c=$.length<=1?100:100/($.length-1),A=$.map((F,U)=>`${(U*c).toFixed(2)},${(46-F*0.42).toFixed(2)}`).join(" "),j=`0,48 ${A} 100,48`;return t("article",{className:`metric-chart ${i}`,"data-testid":y},t("div",{className:"metric-chart-head"},t("div",null,t("span",null,u),t("strong",null,vn(l))),t("code",null,`${r.length} pts`)),t("svg",{viewBox:"0 0 100 48",preserveAspectRatio:"none",role:"img","aria-label":`${u} usage curve`},t("polygon",{points:j}),t("polyline",{points:A}),t("line",{x1:"0",x2:"100",y1:"24",y2:"24"})),t("div",{className:"metric-chart-foot"},t("span",null,"0%"),t("span",null,n),t("span",null,"100%")))}function h0(u){return Array.isArray(u)?u:[]}function um(u){let f=h0(u?.core?.requests?.componentSummary);return[...h0(u?.frontend?.requests?.componentSummary),...f].sort((r,n)=>Cu(n.requestCount)-Cu(r.requestCount))}function fm(u){let f=h0(u?.core?.operations?.summary);return[...h0(u?.frontend?.operations?.summary),...f].sort((r,n)=>Cu(n.count)-Cu(r.count))}function lm(u){let f=h0(u?.core?.requests?.recentFailures).map((r)=>({source:"backend",...r}));return[...h0(u?.frontend?.requests?.recentFailures).map((r)=>({source:"frontend",...r})),...f].sort((r,n)=>(F0(n.at)??0)-(F0(r.at)??0)).slice(0,20)}function rm(u){let f=h0(u?.core?.operations?.recentSlowOperations);return[...h0(u?.frontend?.operations?.recentSlowOperations),...f].sort((r,n)=>Cu(n.durationMs)-Cu(r.durationMs)).slice(0,20)}function nm(u){let f=performance.memory,l=Number(f?.usedJSHeapSize);if(Number.isFinite(l)&&l>0)return l;let r=Number(u?.appBundleBytes);if(Number.isFinite(r)&&r>0)return r;return Cu(u?.process?.heapUsedBytes)}function im({points:u}){let f=h0(u),l=f.map((F)=>Cu(F.mb)),r=Math.max(1,...l),n=Math.max(0,Math.min(...l,0)),i=Math.max(1,r-n),y=f.length>1?f:[...f,...f],_=y.length<=1?100:100/(y.length-1),$=y.map((F,U)=>{let Q=Cu(F.mb);return`${(U*_).toFixed(2)},${(48-(Q-n)/i*42).toFixed(2)}`}).join(" "),c=`0,50 ${$} 100,50`,A=f.at(-1),j=f[0];return t("article",{className:"performance-memory-card","data-testid":"performance-memory-chart"},t("div",{className:"performance-memory-head"},t("strong",null,`Bwebui: ${A?`${Cu(A.mb).toFixed(1)}MB`:"--"}`),t("span",null,f.length>0?`${f.length} samples`:"等待采样")),t("svg",{viewBox:"0 0 100 50",preserveAspectRatio:"none",role:"img","aria-label":"Bwebui memory trend"},t("polygon",{points:c}),t("polyline",{points:$}),t("line",{x1:"0",x2:"100",y1:"25",y2:"25"})),t("div",{className:"performance-axis-row"},t("span",null,j?$f(new Date(j.at)):"--"),t("span",null,"时间"),t("span",null,A?$f(new Date(A.at)):"--")),t("div",{className:"performance-axis-row"},t("span",null,`${n.toFixed(1)}`),t("span",null,"(MB)"),t("span",null,`${r.toFixed(1)}`)))}function ym({onRaw:u}){let[f,l]=bu({core:null,frontend:null}),[r,n]=bu([]),[i,y]=bu(""),[_,$]=bu(!1),[c,A]=bu(null),[j,F]=bu(!1);async function U(){$(!0),y("");try{let[X,m]=await Promise.all([Eu(`${gu.apiBaseUrl}/performance`,{cache:"no-store"}),Eu(`${gu.apiBaseUrl}/frontend-performance`,{cache:"no-store"})]);l({core:X,frontend:m});let O=nm(m);n((p)=>[...p,{at:new Date().toISOString(),mb:O/1048576}].slice(-80))}catch(X){y(Hu(X,"性能指标加载失败"))}finally{$(!1)}}j0(()=>{U();let X=setInterval(()=>void U(),5000);return()=>clearInterval(X)},[]);async function Q(){F(!0),y(""),A(null);try{let X=await Eu(`${gu.apiBaseUrl}/code-queue-load-test`,{method:"POST",body:JSON.stringify({targetMs:1000,timeoutMs:90000,url:gu.frontendPublicUrl||window.location.origin})});A(X),U()}catch(X){y(Hu(X,"Code Queue Playwright 测量失败"))}finally{F(!1)}}let w=um(f),L=lm(f),J=fm(f),N=rm(f),q=f.core?.process||{},W=f.frontend?.process||{},z=f.core?.database?.codeQueueStorage||{},Z=Cu(z.total),H=c?.result||{},E=Cu(H.wallMs,NaN),D=Cu(H.networkIdleMs,NaN),h=H.withinTarget===!0,B=j?"running":c===null?"idle":c.measurementOk===!0?h?"passed":"slow":"failed";return t("div",{className:"performance-page","data-testid":"performance-page"},t("div",{className:"performance-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Unified Performance"),t(nf,{title:"性能面板",loading:_||j}),t("p",null,"按组件统计 HTTP 请求、失败率、P95 延迟,并汇总 backend/frontend 内部操作耗时。")),t("div",{className:"inline-actions"},t("button",{type:"button",className:"ghost-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-button"},j?"测试中...":"测试 Code Queue 加载"),t("button",{type:"button",className:"ghost-btn",onClick:()=>void U(),disabled:_,"data-testid":"performance-refresh-button"},_?"刷新中":"刷新"),t(bf,{title:"Performance Snapshot",data:f,onOpen:u,testId:"raw-performance"}))),t(yf,{error:i}),t("div",{className:"performance-top-grid"},t(im,{points:r}),t("div",{className:"performance-metric-stack"},t(cf,{label:"backend RSS",value:Ll(q.rssBytes),hint:`heap ${Ll(q.heapUsedBytes)}`}),t(cf,{label:"frontend RSS",value:Ll(W.rssBytes),hint:`bundle ${Ll(f.frontend?.appBundleBytes)}`}),t(cf,{label:"Codex PG 任务",value:Z||"--",hint:z.ok?"unidesk_code_queue_tasks":"等待表初始化",tone:z.ok?"ok":"warn"}),t(cf,{label:"请求样本",value:Cu(f.core?.requests?.sampleCount)+Cu(f.frontend?.requests?.sampleCount),hint:"rolling window 3000"}))),t(au,{title:"Code Queue 加载基准",eyebrow:"Playwright / target <1s",className:"codex-load-test-panel",loading:j,actions:t("div",{className:"panel-actions"},t("button",{type:"button",className:"primary-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-panel-button"},j?"正在运行 Playwright...":"手动触发测试"),c?t(bf,{title:"Code Queue Load Test",data:c,onOpen:u,testId:"raw-code-queue-load-test"}):null)},t("div",{className:"codex-load-test-grid","data-testid":"code-queue-load-test-result"},t(cf,{label:"总耗时",value:j?"运行中":Number.isFinite(E)?jr(E):"--",hint:c===null?"点击按钮启动远端 Playwright":`目标 ${jr(H.targetMs||1000)} / ${H.url||"Code Queue"}`,tone:B==="passed"?"ok":B==="failed"||B==="slow"?"warn":""}),t(cf,{label:"判定",value:j?"RUNNING":B==="passed"?"PASS <1s":B==="slow"?"SLOW":B==="failed"?"FAILED":"--",hint:c?.measurementOk===!1?String(c.error||H.error||"measurement failed").slice(0,120):"导航开始 -> DOMContentLoaded -> data-load-state=complete",tone:B==="passed"?"ok":B==="idle"||B==="running"?"":"fail"}),t(cf,{label:"Network idle",value:Number.isFinite(D)?jr(D):"--",hint:`DOMContentLoaded ${jr(H.domContentLoadedMs)} / ${H.networkIdleReached===!1?"未在 5s 内空闲":"已空闲"}`,tone:Number.isFinite(D)&&D<=1000?"ok":"warn"}),t(cf,{label:"组件耗时",value:Number.isFinite(Cu(H.componentLoadMs,NaN))?jr(H.componentLoadMs):"--",hint:`queue ${jr(H.queueMs)} / detail ${jr(H.detailMs)}`,tone:Cu(H.componentLoadMs)>1000?"warn":"ok"}),t(cf,{label:"Trace 规模",value:Number.isFinite(Cu(H.transcriptRows,NaN))?String(H.transcriptRows):"--",hint:`${H.visibleTaskCount??0} visible tasks / ${H.partial?"preview":"complete"}`})),j?t("div",{className:"performance-empty-line"},"正在通过 main-server Host SSH 启动 Playwright,完成后会显示 wall time、组件耗时和最慢 API。"):null,c&&Array.isArray(H.slowestApi)&&H.slowestApi.length>0?t("div",{className:"table-wrap performance-table-wrap compact codex-load-api-table"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["API","状态","耗时"].map((X)=>t("th",{key:X},X)))),t("tbody",null,H.slowestApi.slice(0,5).map((X,m)=>t("tr",{key:`${X.url}-${m}`},t("td",null,t("code",null,X.url)),t("td",null,X.status),t("td",null,jr(X.durationMs))))))):null),t("div",{className:"performance-grid"},t(au,{title:"组件汇总",eyebrow:"Requests",loading:_},w.length===0?t(Ff,{title:"暂无请求样本",text:"刷新几次或打开页面后会自动形成组件统计"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["组件","请求数","失败数","失败率","平均延迟","P95"].map((X)=>t("th",{key:X},X)))),t("tbody",null,w.map((X)=>t("tr",{key:X.component},t("td",null,t("code",null,X.component)),t("td",null,X.requestCount),t("td",null,X.failureCount),t("td",null,vn(Cu(X.failureRate)*100)),t("td",null,jr(X.averageLatencyMs)),t("td",null,jr(X.p95LatencyMs)))))))),t(au,{title:"最近失败请求",eyebrow:"Failures",loading:_},L.length===0?t("div",{className:"performance-empty-line"},"最近没有失败请求"):t("div",{className:"table-wrap performance-table-wrap compact"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["时间","来源","组件","状态","路径"].map((X)=>t("th",{key:X},X)))),t("tbody",null,L.map((X,m)=>t("tr",{key:`${X.at}-${m}`},t("td",null,Nu(X.at)),t("td",null,X.source),t("td",null,t("code",null,X.component)),t("td",null,t(Wf,{status:"failed"},X.status)),t("td",null,t("code",null,X.path)))))))),t(au,{title:"内部操作汇总",eyebrow:"Operations",loading:_},J.length===0?t(Ff,{title:"暂无内部操作样本",text:"API 查询和代理请求会自动记录内部操作耗时"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["服务","操作","次数","平均延迟","P95"].map((X)=>t("th",{key:X},X)))),t("tbody",null,J.map((X)=>t("tr",{key:`${X.service}-${X.operation}`},t("td",null,X.service),t("td",null,t("code",null,X.operation)),t("td",null,X.count),t("td",null,jr(X.averageLatencyMs)),t("td",null,jr(X.p95LatencyMs)))))))),t(au,{title:"最近慢操作",eyebrow:"Slowest",loading:_},N.length===0?t(Ff,{title:"暂无慢操作",text:"后端会记录最近窗口内耗时最高的内部操作"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["时间","操作","耗时","结果","细节"].map((X)=>t("th",{key:X},X)))),t("tbody",null,N.map((X,m)=>t("tr",{key:`${X.at}-${X.operation}-${m}`},t("td",null,Nu(X.at)),t("td",null,t("code",null,X.operation)),t("td",null,jr(X.durationMs)),t("td",null,X.ok?"成功":"失败"),t("td",null,X.detail||"-")))))))))}function _m({provider:u,refresh:f,onRaw:l}){let[r,n]=bu(""),[i,y]=bu(null),[_,$]=bu("");async function c(A){n(A),$("");try{let j=await Eu(`${gu.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:u.providerId,command:"provider.upgrade",payload:{mode:A,source:"frontend-resource-monitor",requestedAt:new Date().toISOString()}})});y({mode:A,...j}),await f()}catch(j){$(Hu(j,"升级命令下发失败"))}finally{n("")}}return t(au,{title:"Provider Gateway 升级",eyebrow:"Remote Control",loading:Boolean(r)},t("div",{className:"upgrade-control","data-testid":"provider-upgrade-control"},t("p",null,"通过 UniDesk WebSocket 向当前计算节点下发 provider.upgrade;预检只生成升级计划,执行升级会调度节点本地 updater 容器。"),t("div",{className:"upgrade-target-line"},t("span",null,"指定 Provider"),t("code",null,u.providerId),t(qy,{node:u})),t("div",{className:"upgrade-actions"},t("button",{type:"button",className:"ghost-btn",disabled:Boolean(r),onClick:()=>c("plan"),"data-testid":"upgrade-plan-button"},r==="plan"?"预检中":"预检升级"),t("button",{type:"button",className:"ghost-btn danger",disabled:Boolean(r),onClick:()=>c("schedule"),"data-testid":"upgrade-schedule-button"},r==="schedule"?"调度中":"执行升级")),t(yf,{error:_}),i?t("div",{className:"upgrade-result"},t(Wf,{status:i.status||"queued"},i.status||"queued"),t("span",null,`${i.mode==="schedule"?"执行升级":"预检升级"} 已下发`),t("span",null,`指定版本 ${a9(rL(u))}`),t("code",null,i.taskId||"--"),t(bf,{title:"Provider Upgrade Dispatch",data:i,onOpen:l})):t("span",{className:"muted"},"升级任务结果会进入任务历史;执行升级可能导致 provider 短暂重连。")))}function FL({records:u,onRaw:f,compact:l=!1}){if(u.length===0)return t(Ff,{title:"暂无远程更新记录",text:"该节点还没有 provider.upgrade 任务;执行预检或升级后会在这里形成结构化记录"});return t("div",{className:`upgrade-record-table-wrap table-wrap ${l?"compact":""}`},t("table",{className:"upgrade-record-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"模式"),t("th",null,"任务"),t("th",null,"来源"),t("th",null,"耗时"),t("th",null,"策略"),t("th",null,"Gateway 版本"),t("th",null,"结果记录"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,u.map((r)=>t("tr",{key:r.id,"data-testid":`gateway-upgrade-record-${sl(r.id)}`},t("td",null,t(Wf,{status:r.status})),t("td",null,t("span",{className:`mode-chip ${O8(r)}`},O8(r)==="schedule"?"执行升级":"预检")),t("td",null,t("strong",null,"provider.upgrade"),t("code",null,r.id)),t("td",null,SS(r)),t("td",null,t(UL,{task:r})),t("td",null,mS(r)),t("td",null,t("span",{className:"version-chip"},_L(r))),t("td",null,t("span",{className:`upgrade-outcome ${String(r.status||"").toLowerCase()}`},$L(r))),t("td",null,Nu(r.updatedAt)),t("td",null,t(bf,{title:`Provider Upgrade Task ${r.id}`,data:M$(r),onOpen:f})))))))}function $m({provider:u,tasks:f,onRaw:l,limit:r=5}){let n=tL(f,u.providerId).slice(0,r);return t(au,{title:"远程更新记录",eyebrow:u.providerId,actions:t(qy,{node:u}),className:"provider-upgrade-records-panel"},t("div",{"data-testid":`provider-upgrade-records-${sl(u.providerId)}`},t(FL,{records:n,onRaw:l,compact:!0})))}function tm({nodes:u,tasks:f,onRaw:l}){let r=P$(()=>u.map((i)=>{let y=tL(f,i.providerId);return{node:i,records:y,latest:pS(y),capabilities:nL(i)}}),[u,f]),n=r.reduce((i,y)=>i+y.records.length,0);return t("div",{className:"gateway-page","data-testid":"gateway-version-page"},t(au,{title:"Provider Gateway 版本",eyebrow:`${u.length} Providers / ${n} 更新记录`},u.length===0?t(Ff,{title:"暂无 Provider 节点",text:"等待 provider-gateway 注册后显示版本号和升级记录"}):t("div",{className:"table-wrap gateway-version-table-wrap"},t("table",{className:"gateway-version-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"Provider"),t("th",null,"Gateway 版本"),t("th",null,"升级策略"),t("th",null,"运维可用性"),t("th",null,"运行时间"),t("th",null,"能力"),t("th",null,"最近远程更新"),t("th",null,"操作"))),t("tbody",null,r.map((i)=>t("tr",{key:i.node.providerId},t("td",null,t(Wf,{status:i.node.status})),t("td",null,t("strong",null,i.node.name),t("code",null,i.node.providerId)),t("td",null,t(qy,{node:i.node})),t("td",null,p$(i.node)),t("td",null,t(o9,{node:i.node})),t("td",null,hw(i.node)?Nu(hw(i.node)):"待新版上报"),t("td",null,t("div",{className:"capability-row"},i.capabilities.length===0?t("span",{className:"muted"},"未声明"):i.capabilities.slice(0,5).map((y)=>t("span",{key:y,className:"data-chip"},y)))),t("td",null,i.latest?t("div",{className:"latest-upgrade-cell"},t(Wf,{status:i.latest.status}),t("span",null,`${O8(i.latest)==="schedule"?"执行升级":"预检"} / ${Nu(i.latest.updatedAt)}`),t("small",null,`Gateway ${_L(i.latest)}`),t("small",null,$L(i.latest))):t("span",{className:"muted"},"暂无记录")),t("td",null,t(bf,{title:`Provider ${i.node.providerId}`,data:i.node,onOpen:l})))))))),t(au,{title:"远程更新记录",eyebrow:"Structured provider.upgrade records"},u.length===0?t(Ff,{title:"暂无记录",text:"没有 provider 节点时不会生成远程更新记录"}):t("div",{className:"gateway-record-grid"},r.map((i)=>t("article",{key:i.node.providerId,className:"gateway-record-card","data-testid":`gateway-records-${sl(i.node.providerId)}`},t("div",{className:"gateway-record-head"},t("div",null,t("strong",null,i.node.name),t("code",null,i.node.providerId)),t(qy,{node:i.node})),t("div",{className:"gateway-record-meta"},t("span",null,`心跳 ${Nu(i.node.lastHeartbeat)}`),t("span",null,`策略 ${p$(i.node)}`),t("span",null,`${i.records.length} 条记录`)),t(FL,{records:i.records.slice(0,8),onRaw:l,compact:!0}))))))}function cm(u){if(u==="running")return"online";if(u==="paused"||u==="restarting")return"warn";if(u==="exited"||u==="dead")return"offline";return"internal"}function JL(u){return/^[a-f0-9]{48,64}$/i.test(u)}function m$(u){let f=String(u?.name||""),l=String(u?.labels||"");return f==="unidesk_pgdata_10gb"||l.includes("com.docker.compose.volume=unidesk_pgdata_10gb")||f.toLowerCase().includes("pgdata")}function sw(u){let f=String(u?.name||""),l=String(u?.labels||"");if(m$(u))return 0;if(l.includes("com.docker.compose.project=unidesk"))return 1;if(!JL(f))return 2;return 3}function Am(u){return[...u].sort((f,l)=>{let r=sw(f)-sw(l);if(r!==0)return r;return String(f.name||"").localeCompare(String(l.name||""))})}function jm({nodes:u,dockerStatuses:f,onRaw:l}){let[r,n]=bu(""),i=P$(()=>u.map((N)=>{let q=f.find((W)=>W.providerId===N.providerId);return{...N,dockerStatus:q?.dockerStatus||null,dockerUpdatedAt:q?.updatedAt||null}}),[u,f]),y=i.find((N)=>N.providerId===r)||i[0]||null;if(j0(()=>{if(!r&&i[0])n(i[0].providerId)},[i.length,r]),!y)return t(Ff,{title:"暂无 Docker 节点",text:"等待 provider 上报 Docker daemon 状态"});let _=y.dockerStatus,$=y.providerId==="main-server",c=_?.counts||{},A=_?.daemon||{},j=_?.containers||[],F=_?.images||[],U=Am(_?.volumes||[]),Q=$?U.find(m$):null,w=_?.networks||[],L=j.filter((N)=>N.state==="running"),J=j.filter((N)=>N.state!=="running");return t("div",{className:"docker-page","data-testid":"docker-status-page"},t("div",{className:"docker-node-strip"},i.map((N)=>t("button",{key:N.providerId,type:"button",className:`docker-node-tile ${y.providerId===N.providerId?"active":""}`,onClick:()=>n(N.providerId)},t("span",{className:`pulse ${N.status}`}),t("strong",null,N.name),t("code",null,N.providerId),t("span",null,N.dockerStatus?`Docker ${N.dockerStatus.ok?"ready":"degraded"}`:"等待上报")))),t("div",{className:"docker-layout"},t(au,{title:"Docker Desktop 视图",eyebrow:y.name,className:"docker-main-panel",actions:_?t(bf,{title:`Docker ${y.providerId}`,data:_,onOpen:l}):null},!_?t(Ff,{title:"Docker 状态未上报",text:"provider-gateway 会在连接后周期性采集 docker info / ps / images / volume / network"}):t("div",null,t("div",{className:"docker-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Daemon"),t("h3",null,A.name||y.providerId),t("div",{className:"docker-meta"},t("span",null,A.serverVersion?`Engine ${A.serverVersion}`:"Engine --"),t("span",null,A.operatingSystem||"OS --"),t("span",null,A.architecture||"arch --"),t("span",null,`${A.cpus||0} CPU / ${Ll(A.memoryBytes)}`))),t(Wf,{status:_.ok?"online":"warn"},_.ok?"Docker Ready":"Docker Degraded")),t("div",{className:"docker-metrics"},t(cf,{label:"Containers",value:c.containers??j.length,hint:`${c.running??L.length} running / ${c.stopped??J.length} stopped`,tone:"ok"}),t(cf,{label:"Images",value:c.images??F.length,hint:`${c.daemonImages??c.images??F.length} daemon images`}),t(cf,{label:"Volumes",value:c.volumes??U.length,hint:$?Q?"database volume visible":"database volume missing":"node local volumes",tone:Q?"ok":""}),t(cf,{label:"Networks",value:c.networks??w.length,hint:A.driver?`driver ${A.driver}`:"docker networks"})),$?t(Fm,{volume:Q,volumeCount:U.length}):null,t("div",{className:"docker-section-head"},t("h3",null,"Containers"),t("span",null,`updated ${Nu(y.dockerUpdatedAt||_.collectedAt)}`)),t("div",{className:"docker-container-table table-wrap","data-testid":"docker-container-table"},t("table",null,t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"容器"),t("th",null,"镜像"),t("th",null,"端口"),t("th",null,"运行时间"),t("th",null,"重启策略"),t("th",null,"PID"),t("th",null,"大小"))),t("tbody",null,j.length===0?t("tr",null,t("td",{colSpan:8},"暂无容器")):j.map((N)=>t("tr",{key:`${N.id}-${N.name}`},t("td",null,t(Wf,{status:cm(N.state)},N.state||"unknown")),t("td",null,t("strong",null,N.name||"--"),t("code",null,N.id||"--")),t("td",null,N.image||"--"),t("td",null,N.ports||t("span",{className:"muted"},"未发布")),t("td",null,N.runningFor||N.status||"--"),t("td",null,N.restartPolicy?t(Wf,{status:N.restartPolicy==="always"?"online":"warn"},N.restartPolicy):"--"),t("td",null,N.pidMode?t("code",null,N.pidMode):"--"),t("td",null,N.size||"--")))))))),t("div",{className:"docker-side-stack"},t(k9,{title:"Images",items:F,render:(N)=>t("article",{key:`${N.id}-${N.repository}`,className:"docker-side-row"},t("strong",null,`${N.repository}:${N.tag}`),t("span",null,N.size||"--"),t("code",null,N.id||"--"))}),t(k9,{title:"Volumes",items:U,limit:U.length,render:(N)=>t("article",{key:N.name,className:`docker-side-row volume-row ${$&&m$(N)?"database-volume":""}`,"data-testid":$&&m$(N)?"database-volume-row":void 0},t("strong",null,N.name),t("span",null,$&&m$(N)?"PostgreSQL":JL(String(N.name||""))?"anonymous":"named"),t("code",null,N.mountpoint||N.driver||N.scope||"--"))}),t(k9,{title:"Networks",items:w,render:(N)=>t("article",{key:N.id||N.name,className:"docker-side-row"},t("strong",null,N.name),t("span",null,N.driver||"--"),t("code",null,N.id||"--"))}))))}function Fm({volume:u,volumeCount:f}){return t("section",{className:`docker-volume-focus ${u?"ready":"missing"}`,"data-testid":"database-volume-card"},t("div",{className:"volume-focus-head"},t("span",{className:"panel-eyebrow"},"Database Named Volume"),t(Wf,{status:u?"online":"warn"},u?"FOUND":"MISSING")),u?t("div",{className:"volume-focus-body"},t("strong",null,u.name),t("span",null,"PostgreSQL data volume for unidesk-database"),t("div",{className:"volume-route"},t("code",null,u.mountpoint||"/var/lib/docker/volumes/unidesk_pgdata_10gb/_data"),t("span",null,"->"),t("code",null,"unidesk-database:/var/lib/postgresql/data")),t("div",{className:"docker-meta compact"},t("span",null,`driver ${u.driver||"--"}`),t("span",null,`scope ${u.scope||"--"}`),t("span",null,`${f} volumes reported`))):t("div",{className:"volume-focus-body"},t("strong",null,"unidesk_pgdata_10gb"),t("span",null,"当前 Docker 快照没有发现数据库命名卷;请检查 provider-gateway 的 Docker volume 上报。")))}function k9({title:u,items:f,render:l,limit:r}){let n=f.slice(0,r??12),i=Math.max(0,f.length-n.length);return t(au,{title:u,eyebrow:`${f.length} items`,className:"docker-side-panel"},f.length===0?t(Ff,{title:`暂无 ${u}`,text:"等待 Docker 状态采集"}):t("div",{className:"docker-side-list"},n.map(l),i>0?t("div",{className:"docker-side-more"},`+ ${i} more`):null))}function Jm({microservices:u,onRaw:f,onNavigate:l}){let r=u.filter((n)=>vw(n).public===!1);return t("div",{className:"microservice-page","data-testid":"microservice-catalog-page"},t(au,{title:"用户服务目录",eyebrow:"Provider Mounted User Services"},t("div",{className:"metric-grid"},t(cf,{label:"服务总数",value:u.length,hint:"config.json 用户服务登记"}),t(cf,{label:"私有后端",value:r.length,hint:"不直接暴露公网",tone:"ok"}),t(cf,{label:"D601 服务",value:u.filter((n)=>n.providerId==="D601").length,hint:"compute-node docker"}),t(cf,{label:"集成前端",value:u.filter((n)=>n.frontend?.integrated).length,hint:"UniDesk React 页面"}))),t(au,{title:"服务映射",eyebrow:"Repo Reference + Runtime"},u.length===0?t(Ff,{title:"暂无用户服务",text:"在 config.json 的 microservices 中登记用户服务的 provider、仓库引用和后端映射"}):t("div",{className:"table-wrap"},t("table",{className:"microservice-table"},t("thead",null,t("tr",null,t("th",null,"服务"),t("th",null,"Provider"),t("th",null,"代码引用"),t("th",null,"Docker 引用"),t("th",null,"后端映射"),t("th",null,"开发入口"),t("th",null,"运行态"),t("th",null,"操作"))),t("tbody",null,u.map((n)=>{let i=cL(n),y=PS(n),_=vw(n),$=i.availability||{},c=$.status||(i.providerStatus==="online"?"unknown":"unhealthy");return t("tr",{key:n.id,"data-testid":`microservice-row-${sl(n.id)}`},t("td",null,t("strong",null,n.name),t("code",null,n.id)),t("td",null,t("strong",null,i.providerName||n.providerId),t("code",null,n.providerId)),t("td",null,t("span",null,y.url||"--"),t("code",null,y.commitId||"--")),t("td",null,t("span",null,y.composeFile||"--"),t("code",null,`${y.composeService||"--"} / ${y.containerName||"--"}`)),t("td",null,t(Wf,{status:_.public?"warn":"online"},_.public?"public":"private"),t("code",null,`${_.nodeBindHost||"--"}:${_.nodePort||"--"} -> ${_.proxyMode||"--"}`)),t("td",null,t("span",null,n.development?.sshPassthrough?"SSH 透传":"未配置"),t("code",null,n.development?.worktreePath||"--")),t("td",null,t(Wf,{status:c==="healthy"?"online":c==="unknown"?"warn":"failed"},c),t("span",null,$.reason||i.providerStatus||"unknown"),t(In,{data:i.container,empty:"容器快照未上报"})),t("td",null,t("div",{className:"microservice-actions"},n.id==="findjob"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","findjob"),"data-testid":"open-findjob-button"},"打开"):null,n.id==="pipeline"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","pipeline"),"data-testid":"open-pipeline-button"},"打开"):null,n.id==="todo-note"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","todo-note"),"data-testid":"open-todo-note-button"},"打开"):null,n.id==="met-nonlinear"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","met-nonlinear"),"data-testid":"open-met-nonlinear-button"},"打开"):null,n.id==="claudeqq"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","claudeqq"),"data-testid":"open-claudeqq-button"},"打开"):null,n.id==="baidu-netdisk"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","baidu-netdisk"),"data-testid":"open-baidu-netdisk-button"},"打开"):null,n.id==="oa-event-flow"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","oa-event-flow"),"data-testid":"open-oa-event-flow-button"},"打开"):null,n.id==="code-queue"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","code-queue"),"data-testid":"open-code-queue-button"},"打开"):null,n.id==="project-manager"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","project-manager"),"data-testid":"open-project-manager-button"},"打开"):null,t(bf,{title:`用户服务 ${n.id}`,data:n,onOpen:f}))))}))))))}function Um({nodes:u,onDispatched:f,onRaw:l}){let r=u.filter((B)=>B.status==="online"),[n,i]=bu(r[0]?.providerId||u[0]?.providerId||""),[y,_]=bu("docker.ps"),[$,c]=bu("frontend"),[A,j]=bu("operator-check"),[F,U]=bu("normal"),[Q,w]=bu(!1),[L,J]=bu(""),[N,q]=bu(!1),[W,z]=bu(null),[Z,H]=bu("");j0(()=>{if(!n&&(r[0]?.providerId||u[0]?.providerId))i(r[0]?.providerId||u[0].providerId)},[u.length,r.length,n]);function E(){return{source:$,note:A,priority:F}}function D(){J(JSON.stringify(E(),null,2)),w(!0)}async function h(B){B.preventDefault(),q(!0),H("");try{let X=Q?JSON.parse(L||"{}"):E(),m=await Eu(`${gu.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:n,command:y,payload:X})});z(m),await f()}catch(X){H(Hu(X,"下发失败"))}finally{q(!1)}}return t("div",{className:"page-grid dispatch-grid"},t(au,{title:"下发任务",eyebrow:"Real WebSocket Dispatch"},t("form",{className:"dispatch-form",onSubmit:h},t("label",null,"Provider",t("select",{value:n,onChange:(B)=>i(B.target.value)},u.map((B)=>t("option",{key:B.providerId,value:B.providerId},`${B.name} / ${B.providerId}`)))),t("label",null,"Command",t("select",{value:y,onChange:(B)=>_(B.target.value)},t("option",{value:"docker.ps"},"docker.ps"),t("option",{value:"host.ssh"},"host.ssh"),t("option",{value:"microservice.http"},"microservice.http"),t("option",{value:"echo"},"echo"))),t("label",null,"来源",t("input",{value:$,onChange:(B)=>c(B.target.value)})),t("label",null,"备注",t("input",{value:A,onChange:(B)=>j(B.target.value)})),t("label",null,"优先级",t("select",{value:F,onChange:(B)=>U(B.target.value)},t("option",{value:"normal"},"normal"),t("option",{value:"low"},"low"),t("option",{value:"urgent"},"urgent"))),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",onClick:D},"查看原始JSON"),t("button",{type:"submit",disabled:N||!n},N?"下发中":"下发任务")),Q?t("label",{className:"raw-editor-label"},"高级 Payload",t("textarea",{className:"raw-editor",value:L,onChange:(B)=>J(B.target.value)})):null,t(yf,{error:Z,wide:!0}))),t(au,{title:"下发结果",eyebrow:"Response"},W?t("div",{className:"result-card"},t(Wf,{status:W.status||"queued"},W.status||"queued"),t("dl",null,t("dt",null,"Task ID"),t("dd",null,t("code",null,W.taskId||"--")),t("dt",null,"Provider 在线"),t("dd",null,R1(W.providerOnline))),t(bf,{title:"Dispatch Response",data:W,onOpen:l})):t(Ff,{title:"等待操作",text:"任务响应会以结构化结果卡展示"})))}function aw({task:u,onRaw:f}){return t("article",{className:"compact-row"},t(Wf,{status:u.status}),t("div",null,t("strong",null,u.command),t("code",null,u.id)),t("span",null,Ny(u)?`已等待 ${g9(u.updatedAt)}`:`耗时 ${x0(uL(u)??0)}`),t(bf,{title:`Task ${u.id}`,data:M$(u),onOpen:f}))}function UL({task:u}){let f=uL(u),l=Ny(u);return t("div",{className:"task-duration"},t("strong",null,f===null?"--":x0(f)),t("span",null,l?`已运行 / 创建 ${Nu(u.createdAt)}`:`创建 ${Nu(u.createdAt)}`))}function Qm({task:u}){let f=String(u?.status||"").toLowerCase(),l=u?.result,r=l&&typeof l==="object"&&!Array.isArray(l)?l:{},i=["exitCode","code","signal","timeoutMs","previousStatus","mode"].filter((y)=>r[y]!==void 0&&r[y]!==null);if(f==="failed"){let y=fL(u);return t("div",{className:"task-diagnostic failed"},t("b",null,"失败原因"),t("span",{className:"diagnostic-reason"},R1(y)),i.length>0?t("div",{className:"diagnostic-meta"},i.map((_)=>t("span",{key:_,className:"data-chip"},t("b",null,_),t("span",null,R1(r[_]))))):null)}if(Ny(u))return t("div",{className:"task-diagnostic warn"},t("b",null,"等待终态"),t("span",null,`最后更新 ${g9(u.updatedAt)} 前`));return t("div",{className:"task-diagnostic ok"},t("b",null,"完成摘要"),t(In,{data:l,empty:"无执行输出"}))}function qm({tasks:u,onRaw:f}){let l=u.filter(Ny);return t("div",{"data-testid":"pending-task-page"},t(au,{title:"待处理任务",eyebrow:`${l.length} Pending`},l.length===0?t(Ff,{title:"当前无待处理任务",text:"queued / dispatched / running 会在超时后自动转为 failed;历史记录仍可在任务历史中查看"}):t("div",{className:"table-wrap","data-testid":"pending-task-table"},t("table",null,t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"Provider"),t("th",null,"已等待"),t("th",null,"载荷摘要"),t("th",null,"操作"))),t("tbody",null,l.map((r)=>t("tr",{key:r.id},t("td",null,t(Wf,{status:r.status})),t("td",null,t("strong",null,r.command),t("code",null,r.id)),t("td",null,t("code",null,r.providerId)),t("td",null,g9(r.updatedAt)),t("td",null,t(In,{data:r.payload})),t("td",null,t(bf,{title:`Pending Task ${r.id}`,data:M$(r),onOpen:f})))))))))}function Nm({tasks:u,onRaw:f}){return t("div",{"data-testid":"task-history-page"},t(au,{title:"任务历史",eyebrow:`${u.length} Tasks`},u.length===0?t(Ff,{title:"暂无任务",text:"下发任务后会在这里看到生命周期"}):t("div",{className:"table-wrap"},t("table",{className:"task-history-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"Provider"),t("th",null,"任务耗时"),t("th",null,"载荷摘要"),t("th",null,"诊断信息"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.id,"data-testid":`task-row-${sl(l.id)}`},t("td",null,t(Wf,{status:l.status})),t("td",null,t("strong",null,l.command),t("code",null,l.id)),t("td",null,t("code",null,l.providerId)),t("td",null,t(UL,{task:l})),t("td",null,t(In,{data:l.payload})),t("td",null,t(Qm,{task:l})),t("td",null,Nu(l.updatedAt)),t("td",null,t(bf,{title:`Task ${l.id}`,data:M$(l),onOpen:f})))))))))}function Wm({tasks:u,onRaw:f}){let l=u.filter((r)=>["succeeded","failed"].includes(r.status));return t(au,{title:"执行结果",eyebrow:"Finished Tasks"},l.length===0?t(Ff,{title:"暂无结果",text:"任务完成后展示 provider 返回的结构化摘要"}):t("div",{className:"result-grid"},l.map((r)=>t("article",{key:r.id,className:"result-card"},t("div",{className:"node-card-head"},t("strong",null,r.command),t(Wf,{status:r.status})),t("code",null,r.id),t(In,{data:r.result,empty:"无执行输出"}),t(bf,{title:`Task Result ${r.id}`,data:M$(r),onOpen:f})))))}function wm(u){if(!u||typeof u!=="object")return"--";if(u.type==="interval")return`每 ${x0(Number(u.everySeconds||0))}`;return`每天 ${u.timeOfDay||"03:00"} UTC`}function Lm(u){if(!u||typeof u!=="object")return"--";if(u.type==="pgdata_backup")return`PGDATA -> ${u.remoteBaseDir||"/SERVER_DATA/UNIDESK_PG_DATA"}`;if(u.type==="dispatch")return`${u.providerId||"--"} / ${u.command||"--"}`;return String(u.type||"--")}function Km(u){let f=String(u||"").toLowerCase();if(f==="succeeded")return"online";if(f==="failed")return"failed";if(f==="running"||f==="queued")return"warn";return f}function Gm(u){let f=Number(u?.durationMs);if(Number.isFinite(f)&&f>=0)return x0(f/1000);let l=F0(u?.startedAt||u?.createdAt);if(l===null)return"--";let n=F0(u?.finishedAt)??Date.now();return x0(Math.max(0,(n-l)/1000))}function ow(u){return{id:"unidesk-pgdata-baidu-daily",name:"PGDATA daily Baidu Netdisk backup",description:"Daily PostgreSQL physical base backup uploaded to Baidu Netdisk /SERVER_DATA with monthly rotation.",enabled:!0,timeOfDay:"03:30",actionType:"pgdata_backup",providerId:u[0]?.providerId||"main-server",command:"echo",payloadJson:JSON.stringify({source:"scheduled-task",message:"hello from scheduler"},null,2),remoteBaseDir:"/SERVER_DATA/UNIDESK_PG_DATA",stagingSubdir:"server-data/unidesk-pg-data",timeoutMs:"3600000"}}function zm({schedules:u,scheduleRuns:f,nodes:l,refresh:r,onRaw:n}){let[i,y]=bu(ow(l||[])),[_,$]=bu(!1),[c,A]=bu(""),[j,F]=bu(""),U=[...f||[]].sort((W,z)=>(F0(z.updatedAt)??0)-(F0(W.updatedAt)??0));function Q(W,z){y((Z)=>({...Z,[W]:z}))}function w(W){let z=W?.action||{};y({id:W?.id||"",name:W?.name||"",description:W?.description||"",enabled:W?.enabled!==!1,timeOfDay:W?.schedule?.timeOfDay||"03:30",actionType:z.type||"dispatch",providerId:z.providerId||l[0]?.providerId||"main-server",command:z.command||"echo",payloadJson:JSON.stringify(z.payload||{source:"scheduled-task"},null,2),remoteBaseDir:z.remoteBaseDir||"/SERVER_DATA/UNIDESK_PG_DATA",stagingSubdir:z.stagingSubdir||"server-data/unidesk-pg-data",timeoutMs:String(z.timeoutMs||3600000)}),F(`正在编辑 ${W?.id||""}`)}function L(){let W={id:i.id,name:i.name,description:i.description,enabled:i.enabled,concurrencyPolicy:"skip",schedule:{type:"daily",timeOfDay:i.timeOfDay,timezone:"Etc/UTC"}};if(i.actionType==="pgdata_backup")return{...W,action:{type:"pgdata_backup",volumeName:"unidesk_pgdata_10gb",remoteBaseDir:i.remoteBaseDir,stagingSubdir:i.stagingSubdir,timeoutMs:Number(i.timeoutMs)||3600000,cleanupLocal:!0}};return{...W,action:{type:"dispatch",providerId:i.providerId,command:i.command,payload:JSON.parse(i.payloadJson||"{}"),timeoutMs:Number(i.timeoutMs)||600000}}}async function J(W){W.preventDefault(),$(!0),A(""),F("");try{let z=L(),Z=encodeURIComponent(String(z.id));await Eu(`${gu.apiBaseUrl}/schedules/${Z}`,{method:"PUT",body:JSON.stringify(z)}),F("定时任务已保存"),await r()}catch(z){A(Hu(z,"保存定时任务失败"))}finally{$(!1)}}async function N(W){if(!W?.id)return;$(!0),A(""),F("");try{await Eu(`${gu.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}`,{method:"DELETE"}),F(`已删除 ${W.id}`),await r()}catch(z){A(Hu(z,"删除定时任务失败"))}finally{$(!1)}}async function q(W){if(!W?.id)return;$(!0),A(""),F("");try{let z=await Eu(`${gu.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}/run`,{method:"POST",body:"{}"});F(`已触发 ${W.id} / ${z?.run?.id||"run"}`),await r()}catch(z){A(Hu(z,"触发定时任务失败"))}finally{$(!1)}}return t("div",{className:"page-grid scheduled-task-page","data-testid":"scheduled-task-page"},t(au,{title:"定时任务",eyebrow:`${(u||[]).length} Schedules`},(u||[]).length===0?t(Ff,{title:"暂无定时任务",text:"创建 daily / dispatch / PGDATA backup 任务后会在这里展示下一次执行时间和最近结果"}):t("div",{className:"schedule-card-grid"},(u||[]).map((W)=>t("article",{key:W.id,className:"schedule-card","data-testid":`schedule-row-${sl(W.id)}`},t("div",{className:"node-card-head"},t("strong",null,W.name||W.id),t(Wf,{status:W.enabled?"online":"warn"},W.enabled?"enabled":"disabled")),t("code",null,W.id),t("dl",null,t("dt",null,"计划"),t("dd",null,wm(W.schedule)),t("dt",null,"动作"),t("dd",null,Lm(W.action)),t("dt",null,"下次执行"),t("dd",null,Nu(W.nextRunAt)),t("dt",null,"最近执行"),t("dd",null,W.lastRunAt?`${Nu(W.lastRunAt)} / ${W.lastRunId||"--"}`:"--")),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>w(W)},"编辑"),t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>q(W),"data-testid":`schedule-run-${sl(W.id)}`},"手动触发"),t("button",{type:"button",className:"ghost-btn danger",disabled:_,onClick:()=>N(W)},"删除"),t(bf,{title:`Schedule ${W.id}`,data:W,onOpen:n})))))),t(au,{title:i.id?"配置定时任务":"新建定时任务",eyebrow:"CRUD"},t("form",{className:"dispatch-form schedule-form",onSubmit:J},t("label",null,"ID",t("input",{value:i.id,onChange:(W)=>Q("id",W.target.value)})),t("label",null,"名称",t("input",{value:i.name,onChange:(W)=>Q("name",W.target.value)})),t("label",null,"每日执行时间 UTC",t("input",{value:i.timeOfDay,placeholder:"03:30",onChange:(W)=>Q("timeOfDay",W.target.value)})),t("label",null,"启用",t("select",{value:i.enabled?"true":"false",onChange:(W)=>Q("enabled",W.target.value==="true")},t("option",{value:"true"},"enabled"),t("option",{value:"false"},"disabled"))),t("label",null,"动作类型",t("select",{value:i.actionType,onChange:(W)=>Q("actionType",W.target.value)},t("option",{value:"pgdata_backup"},"PGDATA 备份到百度网盘"),t("option",{value:"dispatch"},"Provider Dispatch"))),i.actionType==="pgdata_backup"?[t("label",{key:"remote"},"网盘根目录",t("input",{value:i.remoteBaseDir,onChange:(W)=>Q("remoteBaseDir",W.target.value)})),t("label",{key:"staging"},"本地 staging 子目录",t("input",{value:i.stagingSubdir,onChange:(W)=>Q("stagingSubdir",W.target.value)}))]:[t("label",{key:"provider"},"Provider",t("select",{value:i.providerId,onChange:(W)=>Q("providerId",W.target.value)},(l||[]).map((W)=>t("option",{key:W.providerId,value:W.providerId},`${W.name} / ${W.providerId}`)))),t("label",{key:"command"},"Command",t("select",{value:i.command,onChange:(W)=>Q("command",W.target.value)},t("option",{value:"echo"},"echo"),t("option",{value:"docker.ps"},"docker.ps"),t("option",{value:"host.ssh"},"host.ssh"),t("option",{value:"microservice.http"},"microservice.http"))),t("label",{key:"payload",className:"raw-editor-label"},"Payload JSON",t("textarea",{className:"raw-editor",value:i.payloadJson,onChange:(W)=>Q("payloadJson",W.target.value)}))],t("label",null,"超时 ms",t("input",{value:i.timeoutMs,onChange:(W)=>Q("timeoutMs",W.target.value)})),t("label",{className:"raw-editor-label"},"描述",t("textarea",{className:"raw-editor compact",value:i.description,onChange:(W)=>Q("description",W.target.value)})),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>y(ow(l||[]))},"重置"),t("button",{type:"submit",disabled:_||!i.id},_?"保存中":"保存任务")),j?t("p",{className:"muted paragraph"},j):null,t(yf,{error:c,wide:!0}))),t(au,{title:"历史执行记录",eyebrow:`${U.length} Runs`},U.length===0?t(Ff,{title:"暂无执行记录",text:"定时触发或手动触发后会生成 run history"}):t("div",{className:"table-wrap"},t("table",{className:"task-history-table schedule-run-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"触发"),t("th",null,"耗时"),t("th",null,"结果摘要"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,U.map((W)=>t("tr",{key:W.id,"data-testid":`schedule-run-row-${sl(W.id)}`},t("td",null,t(Wf,{status:Km(W.status)},W.status)),t("td",null,t("strong",null,W.scheduleId),t("code",null,W.id),W.taskId?t("code",null,W.taskId):null),t("td",null,W.trigger||"--"),t("td",null,Gm(W)),t("td",null,t(In,{data:W.result||W.error,empty:"无结果"})),t("td",null,Nu(W.updatedAt)),t("td",null,t(bf,{title:`Schedule Run ${W.id}`,data:W,onOpen:n})))))))))}function Tm({data:u}){let f=u.overview||{};return t("div",{className:"page-grid topology-grid"},t(au,{title:"公开入口",eyebrow:"Public"},t("div",{className:"endpoint-list"},t("article",null,t("b",null,"Frontend"),t("span",null,gu.frontendPublicUrl||window.location.origin),t(Wf,{status:"online"},"public")),t("article",null,t("b",null,"Provider Ingress"),t("span",null,gu.providerIngressPublicUrl||"ws://public/ws/provider"),t(Wf,{status:"online"},"public")))),t(au,{title:"内部服务",eyebrow:"Docker Network Only"},t("div",{className:"endpoint-list"},t("article",null,t("b",null,"backend-core API"),t("span",null,"http://backend-core:8080"),t(Wf,{status:"internal"},"internal")),t("article",null,t("b",null,"database"),t("span",null,"postgres://database:5432/unidesk"),t(Wf,{status:"internal"},"internal")))),t(au,{title:"运行态",eyebrow:"Runtime"},t("div",{className:"metric-grid"},t(cf,{label:"DB Ready",value:f.dbReady?"YES":"NO",hint:"internal health"}),t(cf,{label:"Online Nodes",value:f.onlineNodeCount??0,hint:"provider-gateway self-link"}))))}function Em({session:u}){return t(au,{title:"认证策略",eyebrow:"Frontend Login"},t("div",{className:"policy-grid"},t("article",null,t("span",null,"默认账号"),t("strong",null,gu.authUsername||"admin")),t("article",null,t("span",null,"当前会话"),t("strong",null,u?.user?.username||"--")),t("article",null,t("span",null,"Session TTL"),t("strong",null,`${gu.sessionTtlSeconds||0}s`)),t("article",null,t("span",null,"API 访问"),t("strong",null,"同源 Cookie 保护"))),t("p",{className:"muted paragraph"},"浏览器只访问 frontend 同源接口;frontend 容器使用 Docker 内网代理 backend-core API。"))}function Zm(){return t(au,{title:"安全边界",eyebrow:"Exposure Rule"},t("div",{className:"security-board"},t("article",{className:"allow"},t("b",null,"允许公网"),t("span",null,"frontend 登录入口"),t("span",null,"provider ingress WebSocket/health")),t("article",{className:"deny"},t("b",null,"禁止公网"),t("span",null,"backend-core REST API"),t("span",null,"PostgreSQL database")),t("article",null,t("b",null,"数据库卷"),t("span",null,"named volume unidesk_pgdata_10gb"),t("span",null,"CLI stop/start 不删除数据卷"))))}function Om({activeModule:u,activeTab:f,data:l,session:r,refresh:n,onRaw:i,onNavigate:y}){if(u==="ops"&&f==="status")return t(vS,{data:l,onRaw:i,onNavigate:y});if(u==="ops"&&f==="performance")return t(ym,{onRaw:i});if(u==="ops"&&f==="events")return t(IS,{events:l.events,onRaw:i});if(u==="ops"&&f==="logs")return t(gS,{logs:l.logs,onRaw:i});if(u==="nodes"&&f==="list")return t(sS,{nodes:l.nodes,onRaw:i});if(u==="nodes"&&f==="monitor")return t(dS,{nodes:l.nodes,systemStatuses:l.systemStatuses,tasks:l.tasks,onRaw:i,refresh:n});if(u==="nodes"&&f==="docker")return t(jm,{nodes:l.nodes,dockerStatuses:l.dockerStatuses,onRaw:i});if(u==="nodes"&&f==="gateway")return t(tm,{nodes:l.nodes,tasks:l.tasks,onRaw:i});if(u==="nodes"&&f==="labels")return t(aS,{nodes:l.nodes});if(u==="nodes"&&f==="heartbeats")return t(oS,{nodes:l.nodes});if(u==="tasks"&&f==="dispatch")return t(Um,{nodes:l.nodes,onDispatched:n,onRaw:i});if(u==="tasks"&&f==="scheduled")return t(zm,{schedules:l.schedules,scheduleRuns:l.scheduleRuns,nodes:l.nodes,refresh:n,onRaw:i});if(u==="tasks"&&f==="pending")return t(qm,{tasks:l.pendingTasks,onRaw:i});if(u==="tasks"&&f==="history")return t(Nm,{tasks:l.tasks,onRaw:i});if(u==="tasks"&&f==="results")return t(Wm,{tasks:l.tasks,onRaw:i});if(u==="apps"&&f==="catalog")return t(Jm,{microservices:l.microservices,onRaw:i,onNavigate:y});if(u==="apps"&&f==="todo-note")return t(mw,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="findjob")return t(HQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="pipeline")return t(Ow,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="met-nonlinear")return t(YQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="claudeqq")return t(yU,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="baidu-netdisk")return t(rU,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="filebrowser")return t(OQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="oa-event-flow")return t(RQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="code-queue")return t(KQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl,initialTasksData:ZS});if(u==="apps"&&f==="project-manager")return t(Vw,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="config"&&f==="topology")return t(Tm,{data:l});if(u==="config"&&f==="auth")return t(Em,{session:r});if(u==="config"&&f==="security")return t(Zm);return t(Ff,{title:"未找到页面",text:"请选择左侧主模块和顶部子功能标签"})}function Hm({session:u,onLogout:f}){let l=n5(Or,window.location.pathname),[r,n]=bu(l.moduleId),[i,y]=bu({...b_,[l.moduleId]:l.tabId}),[_,$]=bu({overview:null,nodes:[],systemStatuses:[],dockerStatuses:[],microservices:[],events:[],tasks:[],pendingTasks:[],schedules:[],scheduleRuns:[],logs:[]}),[c,A]=bu({ok:!1,text:"连接中"}),[j,F]=bu(null),[U,Q]=bu(new Date),[w,L]=bu(null),[J,N]=bu(!1),[q,W]=bu(!1),z=kn.default.useRef(!1),Z=Or.moduleById[r]||Or.modules[0],H=i[r]||b_[r]||Z.tabs[0].id,E=Array.isArray(_.microservices)?_.microservices:[],D=E.length===0&&r==="apps"&&H==="code-queue"?[OS]:E,h=D===E?_:{..._,microservices:D},B=r==="apps"?D.find((o)=>String(o?.id||"")===H):null,X=B?cL(B):{},m=Z.tabs.find((o)=>o.id===H)?.label||H,O=B?[{key:"microservice",label:"用户服务",value:`${m} ${X.providerStatus==="online"?"在线":X.providerStatus||"未知"}`,tone:X.providerStatus==="online"?"ok":"warn",testId:"active-microservice-status"}]:[];async function p(){if(z.current)return;z.current=!0,W(!0);try{let o=[],s=(ju,Gu)=>{o.push([ju,Eu(Gu)])},x=r==="ops"&&H==="status",fu=x||r==="config"&&H==="topology",$u=x||r==="nodes"||r==="tasks"&&(H==="dispatch"||H==="scheduled"),tu=r==="apps"&&H!=="code-queue";if(fu)s("overview",`${gu.apiBaseUrl}/overview`);if($u)s("nodes",`${gu.apiBaseUrl}/nodes`);if(r==="nodes"&&H==="monitor")s("systemStatuses",`${gu.apiBaseUrl}/nodes/system-status?limit=60`),s("tasks",`${gu.apiBaseUrl}/tasks?limit=120&summary=1`);else if(r==="nodes"&&H==="docker")s("dockerStatuses",`${gu.apiBaseUrl}/nodes/docker-status`);else if(r==="nodes"&&H==="gateway")s("tasks",`${gu.apiBaseUrl}/tasks?limit=300&summary=1`);else if(r==="tasks"&&H==="scheduled")s("schedules",`${gu.apiBaseUrl}/schedules?limit=100`),s("scheduleRuns",`${gu.apiBaseUrl}/schedules/runs?limit=100`);else if(r==="tasks"&&H==="pending")s("pendingTasks",`${gu.apiBaseUrl}/tasks?status=pending&limit=100&summary=1`);else if(r==="tasks"&&(H==="history"||H==="results"))s("tasks",`${gu.apiBaseUrl}/tasks?limit=300&summary=1`);else if(x)s("tasks",`${gu.apiBaseUrl}/tasks?limit=8&lite=1`),s("pendingTasks",`${gu.apiBaseUrl}/tasks?status=pending&limit=20&lite=1`);if(tu)s("microservices",`${gu.apiBaseUrl}/microservices`);if(r==="ops"&&H==="events")s("events",`${gu.apiBaseUrl}/events?limit=100`);if(r==="ops"&&H==="logs")s("logs","/logs?limit=100");await Promise.all(o.map(async([ju,Gu])=>{let qu=await Gu,P={};if(ju==="overview")P.overview=qu;if(ju==="nodes")P.nodes=qu.nodes||[];if(ju==="systemStatuses")P.systemStatuses=qu.systemStatuses||[];if(ju==="dockerStatuses")P.dockerStatuses=qu.dockerStatuses||[];if(ju==="microservices")P.microservices=qu.microservices||[];if(ju==="events")P.events=qu.events||[];if(ju==="tasks")P.tasks=qu.tasks||[];if(ju==="pendingTasks")P.pendingTasks=qu.tasks||[];if(ju==="schedules")P.schedules=qu.schedules||[];if(ju==="scheduleRuns")P.scheduleRuns=qu.runs||[];if(ju==="logs")P.logs=qu.logs||[];$((e)=>({...e,...P}))})),A({ok:!0,text:"核心在线"}),F(new Date)}catch(o){if(A({ok:!1,text:Hu(o,"连接失败")}),o.status===401)f(!1)}finally{z.current=!1,W(!1)}}j0(()=>{let o=()=>{if(!xw())return;p()};o();let s=setInterval(o,HS(r,H)),x=()=>{if(xw())o()};return document.addEventListener("visibilitychange",x),()=>{clearInterval(s),document.removeEventListener("visibilitychange",x)}},[r,H]),j0(()=>{let o=setInterval(()=>Q(new Date),1000);return()=>clearInterval(o)},[]),j0(()=>{let o=PQ(Or,window.location.pathname);if(o&&window.location.pathname!==o)window.history.replaceState(null,"",o)},[]),j0(()=>{let o=()=>{let s=n5(Or,window.location.pathname);n(s.moduleId),y((x)=>({...x,[s.moduleId]:s.tabId})),L(null)};return window.addEventListener("popstate",o),()=>window.removeEventListener("popstate",o)},[]),j0(()=>{window.scrollTo({top:0,left:0,behavior:"auto"})},[r,H]);function Y(o,s,x="push"){let fu=Or.moduleById[o]?o:Or.fallbackTarget.moduleId,$u=Or.moduleById[fu]?.tabs.some((ju)=>ju.id===s)?s:b_[fu]||Or.moduleById[fu]?.tabs[0]?.id||Or.fallbackTarget.tabId;n(fu),y((ju)=>({...ju,[fu]:$u}));let tu=f6(Or,fu,$u);if(window.location.pathname!==tu){let ju=x==="replace"?"replaceState":"pushState";window.history[ju](null,"",tu)}}function v(o,s){L({title:o,data:s})}let[T,S]=bu(!1),{unreadCount:k,notifications:I}=Bl(),b=I.length>0?I[I.length-1]:null;return t("div",{className:`shell ${J?"rail-collapsed":""}`,"data-testid":"app-shell"},t(hS,{activeModule:r,activeTabs:i,onNavigate:Y,collapsed:J,onToggle:()=>N((o)=>!o)}),t("main",{className:"workspace"},t(RS,{connection:c,lastRefresh:j,onRefresh:p,onLogout:()=>f(!0),session:u,clock:U,activeStatusItems:O,onNotificationToggle:()=>S((o)=>!o),unreadCount:k}),t(bS,{module:Z,activeTab:H,onNavigate:Y}),t(I9.Provider,{value:q},t(Om,{activeModule:r,activeTab:H,data:h,session:u,refresh:p,onRaw:v,onNavigate:Y}))),t(MS,{raw:w,onClose:()=>L(null)}),b&&t(Rw,{key:b.id,notification:b}),T&&t(Cw,{onClose:()=>S(!1)}))}function Bm(){let[u,f]=bu(!0),[l,r]=bu(null);async function n(){f(!0);try{let y=await Eu("/api/session");r(y.authenticated?y:null)}catch{r(null)}finally{f(!1)}}async function i(y){if(y)try{await Eu("/logout",{method:"POST"})}catch{}r(null)}if(j0(()=>{n()},[]),u)return t("main",{className:"loading-screen"},t("div",{className:"brand-mark"},"UD"),t("span",null,"加载会话"));if(!l)return t(CS,{onLogin:r});return t(lU,null,t(Hm,{session:l,onLogout:i}))}var QL=document.getElementById("root");if(QL===null)throw Error("root element not found");dw.createRoot(QL).render(t(Bm));})(); + ${h} + ${p} + ${m} + ${O} + ${X} + `,width:L,height:w}}function q8(u,f){let l=URL.createObjectURL(u),r=document.createElement("a");r.href=l,r.download=f,r.click(),setTimeout(()=>URL.revokeObjectURL(l),1000)}async function zL(u,f){let l=GL(f,"pipeline"),{svg:r,width:n,height:i}=xY(u,f),y=new Blob([r],{type:"image/svg+xml;charset=utf-8"}),_=URL.createObjectURL(y);try{let $=new Image;await new Promise((F,U)=>{$.onload=()=>F(),$.onerror=()=>U(Error("svg image load failed")),$.src=_});let A=document.createElement("canvas");A.width=n,A.height=i;let c=A.getContext("2d");if(!c)throw Error("canvas unavailable");c.drawImage($,0,0);let j=await new Promise((F)=>A.toBlob(F,"image/png"));if(!j)throw Error("png export failed");q8(j,`${l}.png`)}catch{q8(y,`${l}.svg`)}finally{URL.revokeObjectURL(_)}}async function IY(u){let f=GL(String(u?.title||"pipeline-gantt"),"pipeline-gantt"),{svg:l,width:r,height:n}=kY(u),i=new Blob([l],{type:"image/svg+xml;charset=utf-8"}),y=URL.createObjectURL(i);try{let _=new Image;await new Promise((j,F)=>{_.onload=()=>j(),_.onerror=()=>F(Error("gantt svg image load failed")),_.src=y});let $=document.createElement("canvas");$.width=r,$.height=n;let A=$.getContext("2d");if(!A)throw Error("canvas unavailable");A.drawImage(_,0,0);let c=await new Promise((j)=>$.toBlob(j,"image/png"));if(!c)throw Error("gantt png export failed");q8(c,`${f}.png`)}catch{q8(i,`${f}.svg`)}finally{URL.revokeObjectURL(y)}}async function gY(u){for(let f of u){if(f.flow.nodes.length===0)continue;await zL(f.flow,f.title),await new Promise((l)=>setTimeout(l,750))}}function _L(u,f){return u.find((l)=>String(l?.pipelineId||"")===f)||null}function $L(u){return vu(u?.startedAt)??vu(u?.artifact?.startedAt)??vu(u?.request?.createdAt)??vu(u?.updatedAt)??0}function sY(u,f){return u.filter((l)=>String(l?.pipelineId||"")===f).slice().sort((l,r)=>$L(l)-$L(r)||String(l?.runId||"").localeCompare(String(r?.runId||"")))}function Z9(u,f){let l=String(f?.runId||""),r=u.findIndex((y)=>String(y?.runId||"")===l),n=r>=0?r+1:u.length,i=String(f?.status||"--");return`Epoch ${n} / ${l||"--"} / ${i}`}function Br(u){return String(u?.procedureRunId||u?.runId||"")}function w8(u,f){let l=String(u?.nodeId||u?.request?.nodeId||"");if(l)return l;let r=Br(u),n=`${f}__`;if(r.startsWith(n))return r.slice(n.length).replace(/__\d+$/u,"");return""}function $8(u,f){let l=Du(u?.artifact)?u.artifact:{},r=Du(u?.request)?u.request:{};return Y$(u?.startedAt,l.startedAt,r.createdAt,r.startedAt,u?.createdAt,u?.updatedAt,f?.startedAt,f?.request?.createdAt)}function t8(u,f){let l=String(u?.status?.status||u?.artifact?.status||u?.status||"").toLowerCase(),r=Du(u?.artifact)?u.artifact:{},n=V9(l);return Y$(u?.finishedAt,r.finishedAt,u?.completedAt,n?u?.updatedAt:void 0,n?r.updatedAt:void 0,n?f?.updatedAt:void 0)}function TL(u,f,l=Date.now()){let r=String(u?.runId||""),n=new Set(f.map((i)=>String(i?.id||"")).filter(Boolean));return Vu(u?.procedureRuns).flatMap((i)=>{let y=w8(i,r);if(!y)return[];let _=String(i?.status?.status||i?.artifact?.status||i?.status||"unknown").toLowerCase(),$=$8(i,u),A=vu($);if(A===null)return[];let c=t8(i,u),j=vu(c)??(V9(_)?vu(i?.updatedAt)??A+1000:l),F=Math.max(A+1000,j);return[{nodeId:y,knownNode:n.has(y),procedureRunId:Br(i),status:_,startMs:A,endMs:F,startedAt:V$(A),finishedAt:V$(F),durationMs:F-A,runId:r,raw:i}]}).sort((i,y)=>i.startMs-y.startMs||i.endMs-y.endMs||i.nodeId.localeCompare(y.nodeId))}function aY(u,f,l=[]){let r=f.map((c)=>Number(c.startMs)).filter(Number.isFinite),n=f.map((c)=>Number(c.endMs)).filter(Number.isFinite);for(let c of l){let j=Vf(c?.eventMs??c?.ms);if(j!==null)r.push(j),n.push(j)}let i=vu(u?.startedAt)??vu(u?.artifact?.startedAt)??vu(u?.request?.createdAt),y=vu(u?.finishedAt)??vu(u?.artifact?.finishedAt)??vu(u?.updatedAt);if(i!==null)r.push(i);if(y!==null)n.push(y);let _=Date.now(),$=r.length>0?Math.min(...r):_-60000,A=Math.max($+60000,n.length>0?Math.max(...n):_);return{startMs:$,endMs:A,durationMs:A-$}}var A8=12,EL=20,O9=100,oY=!1;function Rn(u){let f=Number(u);if(!Number.isFinite(f))return 0;return Math.max(0,Math.min(100,Math.round(f*100)/100))}function dY(u){let f=Math.max(A8,Number(u||A8)),l=Math.log(f/A8)/Math.log(EL);return Rn(l*100)}var X$=dY(O9);function m9(u){let f=Rn(u)/100,l=A8*Math.pow(EL,f),r=f<0.24?"全局":f<0.64?"均衡":"细节";return{value:Rn(f*100),pxPerMinute:l,label:r}}function L9(u){let f=Math.round(Number(u));return Math.abs(f-O9)<=1?O9:f}function eY(u,f=X$){let l=Math.max(1,Number(u.durationMs||0)/60000),r=m9(f);return Math.round(Math.max(360,Math.min(7200,l*Number(r.pxPerMinute||48))))}function uS(u,f=7){let l=Math.max(1,Number(u.endMs||0)-Number(u.startMs||0));return Array.from({length:f},(r,n)=>{let i=f===1?0:n/(f-1);return{ms:Number(u.startMs)+l*i,percent:i*100}})}function fS(u,f){let l=Math.max(1,Number(f.endMs)-Number(f.startMs));return Math.max(0,Math.min(100,(u-Number(f.startMs))/l*100))}function Vf(u){let f=Number(u);return Number.isFinite(f)?f:null}function P9(u){return jL(u?.status)&&!V9(u?.status)}function ZL(u,f,l,r){let n=Math.max(1,l-f),i=Math.max(0,Math.min(1,(u-f)/n));return Number((i*r).toFixed(3))}function tL(u,f){if(!f)return null;let l=Vf(f?.startMs),r=Vf(f?.endMs),n=Vf(f?.chartHeight);if(l===null||r===null||n===null)return null;return ZL(u,l,r,n)}function OL(u,f){let l=Vf(u?.rawStartMs??u?.startMs)??Vf(u?.startMs)??f,r=Vf(u?.endMs)??l+1000;if(!P9(u))return Math.max(l+1000,r);return Math.max(l+1000,r,f)}function lS(u,f,l,r){let n=Vf(u?.startMs)??r-60000,i=Vf(u?.endMs)??r,y=l.reduce((Q,L)=>Math.max(Q,OL(L,r)),i),_=Math.max(n+60000,i,y),$=Math.max(1,_-n),A={startMs:n,endMs:_,durationMs:$},c=eY(A,f),j=m9(f),F=Math.max(5,Math.min(18,Math.round(c/150))),U=uS(A,F).map((Q)=>{let L=Number(Q.ms),w=ZL(L,n,_,c);return{...Q,y:w,timestamp:V$(L),offsetMs:L-n}});return{source:"frontend-y",startMs:n,endMs:_,durationMs:$,chartHeight:c,scale:Rn(f),normalizedScale:Number((Rn(f)/100).toFixed(3)),pxPerMinute:Number(Number(j.pxPerMinute||0).toFixed(3)),ticks:U}}function rS(u,f,l){if(!P9(u))return u;let r=Vf(u?.rawStartMs??u?.startMs)??Vf(u?.startMs)??l,n=OL(u,l),i=tL(r,f),y=tL(n,f),_=Vf(i??u?.y1??u?.startY)??0,$=Vf(y??u?.y2??u?.endY)??_+10,A=Math.max(24,$-_);return{...u,live:!0,startMs:r,endMs:n,durationMs:Math.max(1000,n-r),finishedAt:V$(n),y1:_,y2:$,startY:_,endY:$,height:A}}function M9(u,f,l){return fS(u,f)/100*l}function Jy(u){return Boolean(u&&String(u?.source||"")!=="frontend-y")}function HL(u,f,l,r,n){if(Jy(r))for(let y of n){let _=Vf(u?.[y]);if(_!==null)return _}let i=Vf(u?.ms??u?.eventMs??u?.startMs);return M9(i??Number(f.startMs),f,l)}function N8(u,f,l,r){return HL(u,f,l,r,["y1","startY"])}function H9(u,f,l,r){if(Jy(r)){let i=Vf(u?.y2??u?.endY);if(i!==null)return i}let n=Vf(u?.endMs)??Number(f.endMs);return M9(n,f,l)}function BL(u,f,l,r){if(Jy(r)){let i=Vf(u?.height);if(i!==null)return Math.max(1,i)}let n=u?.live?24:10;return Math.max(n,H9(u,f,l,r)-N8(u,f,l,r))}function Jr(u,f,l,r){return HL(u,f,l,r,["y","timeAxisY"])}function VL(u,f,l,r){if(Jy(r)||String(r?.source||"")==="frontend-y"){let y=Vf(u?.y);if(y!==null)return y}let n=Vf(u?.percent);if(n!==null)return n/100*l;let i=Vf(u?.ms)??Number(f.startMs);return M9(i,f,l)}function nS(u){let f=String(u?.promptEvent||u?.raw?.promptEvent||u?.event||"").toLowerCase();if(!["node-long-running-observation","node-finished"].includes(f))return"";let l=String(u?.sourceNodeId||u?.raw?.sourceNodeId||u?.raw?.detail?.nodeId||""),r=String(u?.nodeId||u?.targetNodeId||"");return l&&l!==r?l:""}function iS(u,f){let l=new Set(f.map((n)=>[String(n.sourceNodeId||""),String(n.targetNodeId||""),String(n.targetMarkerId||""),String(n.action||"")].join(":"))),r=[...f];for(let n of u){let i=nS(n),y=String(n?.nodeId||""),_=String(n?.id||"");if(!i||!y||!_)continue;let $=[i,y,_,"observe"].join(":");if(l.has($))continue;l.add($),r.push({id:`observation-arrow:${_}:${i}:${y}`,commandId:String(n?.commandId||n?.eventId||_),sourceNodeId:i,targetNodeId:y,sourceMarkerId:"",targetMarkerId:_,sourceKind:"monitor",action:"observe",status:"observation"})}return{markers:u,arrows:r}}function yS(u){let f=Ir(u),l=String(u?.promptEvent||"");if(f==="initial-prompt-delivered")return"initial";if(l==="node-finished"||l==="node-long-running-observation"||l.startsWith("monitor-"))return"monitor";if(f==="monitor-prompt-delivered"||String(u?.sourceKind||"").toLowerCase()==="monitor")return"monitor";return"append"}function _S(u){return Vu(u?.tags||u?.raw?.tags).map((f)=>String(f||"")).filter(Boolean)}function $S(u){let f=Ir(u),l=String(u?.promptEvent||"");if(f==="initial-prompt-delivered")return"初始 prompt";if(l==="node-long-running-observation")return"长任务观察";if(l==="node-finished")return _S(u).includes("monitor.audit")?"节点完成 / OA 审核":"节点完成";if(l==="monitor-interval")return"Monitor observation";if(l==="monitor-start")return"Monitor start";if(l==="monitor-stop")return"Monitor stop";if(f==="monitor-prompt-delivered")return"Monitor prompt";if(f==="append-prompt-queued")return"追加 prompt 已排队";return"追加 prompt"}function AL(u){let f=Ir(u);if(f==="control-command-applied")return 3;if(f==="control-command-ignored")return 2;if(f==="control-command-queued")return 1;return 0}function tS(u,f){let l=String(u?.commandId||"");if(l)return`command:${l}`;return["control-event",cy(u)||Y$(u?.createdAt,u?.timestamp)||`index-${f}`,String(u?.sourceKind||""),String(u?.sourceNodeId||""),String(u?.targetNodeId||""),P1(u)].join(":")}function AS(u){return T9([u?.targetNodeId,...Vu(u?.resetNodeIds)])}function cS(u,f){let l=H$(u),r=Ir(u),n=String(u?.targetNodeId||""),i=Boolean(n)&&f!==n;if(r==="control-command-applied")return i?`${l} 波及`:`${l} 生效`;if(r==="control-command-ignored")return`${l} 忽略`;if(r==="control-command-queued")return`${l} 已发起`;return i?`${l} 波及`:l}function jS(u){if(Ir(u)==="control-command-ignored")return"ignored";let l=P1(u);if(l==="restart"||l==="redo")return"restart";if(l==="modify")return"modify";if(l==="approve")return"approve";if(l==="guide")return"guide";return"pending"}function FS(u){let f=String(u?.sourceKind||"").toLowerCase();if(f==="monitor")return"monitor";if(f==="webui")return"webui";if(f==="cli")return"cli";return"system"}function JS(u,f,l,r){let n=u.filter((A)=>String(A.nodeId||"")===f).sort((A,c)=>Number(A.startMs)-Number(c.startMs)),i=n.find((A)=>l>=Number(A.startMs)-1000&&l<=Number(A.endMs)+1000);if(i)return{ms:l,onInterval:!0,snapReason:"inside-interval",procedureRunId:String(i.procedureRunId||"")};let y=P1(r),_=n.slice().reverse().find((A)=>Number(A.endMs)<=l+1000);if(_&&y==="approve")return{ms:Number(_.endMs),onInterval:!0,snapReason:"previous-interval-end",procedureRunId:String(_.procedureRunId||"")};let $=n.find((A)=>Number(A.startMs)>=l-1000);if($&&["guide","modify","restart","redo"].includes(y))return{ms:Number($.startMs),onInterval:!0,snapReason:"next-interval-start",procedureRunId:String($.procedureRunId||"")};return{ms:l,onInterval:!1,snapReason:"event-time",procedureRunId:String(r?.procedureRunId||"")}}function DL(u,f,l,r){let n=Math.hypot(l-u,r-f),i=n>kW?kW:0,y=i>0?l-(l-u)/n*i:l,_=i>0?r-(r-f)/n*i:r,$=y-u,A=Math.max(16,Math.min(42,Math.abs($)*0.45+12)),c=$===0?1:Math.sign($);return`M ${u},${f} C ${u+c*A},${f} ${y-c*A},${_} ${y},${_}`}function US(u,f){let l=String(u?.runId||f?.runId||""),r=TL({...Du(f)?f:{},...Du(u)?u:{},runId:l,procedureRuns:Vu(u?.procedureRuns).length>0?u.procedureRuns:f?.procedureRuns},[]),n=[],i=[],y=[],_=new Set,$=new Map,A=(F,U)=>{if(!F.nodeId||!Number.isFinite(Number(F.ms)))return;if(_.has(F.id))return;_.add(F.id),U.push(F)};for(let F of Vu(u?.procedureRuns)){let U=w8(F,l),Q=Br(F);if(!U)continue;for(let L of Vu(F?.attempts)){let w=L8(L);for(let J of z9(L?.controlEventRecords)){let N=Ir(J);if(!["initial-prompt-delivered","append-prompt-delivered","monitor-prompt-delivered"].includes(N))continue;let q=cy(J),W=vu(q);if(W===null)continue;let z=String(J?.eventId||"");A({id:`prompt:${z||`${Q}:${w}:${N}:${W}`}`,runId:l,nodeId:U,procedureRunId:Q,attempt:w,kind:"prompt",tone:yS(J),status:"delivered",label:$S(J),ms:W,timestampIso:q,sourceKind:String(J?.sourceKind||""),sourceNodeId:String(J?.sourceNodeId||""),targetNodeId:U,action:"",eventId:z,commandId:String(J?.commandId||""),raw:J},n)}}}let c=new Map;z9(u?.controlEvents).forEach((F,U)=>{let Q=tS(F,U),L=c.get(Q)||{key:Q,events:[]};L.events.push(F),c.set(Q,L)});for(let F of c.values()){let U=Vu(F.events).slice().sort((V,Y)=>AL(Y)-AL(V)),Q=Vu(F.events).find((V)=>Ir(V)==="control-command-queued")||null,L=U[0]||Q;if(!Q&&!L)continue;let w=String(Q?.sourceNodeId||L?.sourceNodeId||""),J=String(Q?.sourceKind||L?.sourceKind||""),N=cy(Q)||cy(L)||Y$(Q?.createdAt,L?.createdAt),q=vu(N),W=String(L?.commandId||Q?.commandId||F.key),z=(Ir(L)||"control-command-queued").replace(/^control-command-/u,""),Z="";if(w&&q!==null)Z=`control-source:${W}:${w}`,$.set(W,Z),A({id:Z,runId:l,nodeId:w,procedureRunId:String(Q?.procedureRunId||L?.procedureRunId||""),attempt:"",kind:"control-source",tone:FS(Q||L),status:z,label:`${H$(Q||L)} 发起`,ms:q,timestampIso:N,action:P1(Q||L),sourceKind:J,sourceNodeId:w,targetNodeId:String(L?.targetNodeId||Q?.targetNodeId||""),commandId:W,raw:Q||L},i);let H=L||Q,E=cy(H)||N,D=vu(E);if(D===null)continue;let h=AS(H);for(let V of h){let Y=JS(r,V,D,H),p=`control-target:${W}:${V}`;if(A({id:p,runId:l,nodeId:V,procedureRunId:Y.procedureRunId,attempt:"",kind:"control-target",tone:jS(H),status:z,label:cS(H,V),ms:Y.ms,eventMs:D,onInterval:Y.onInterval,snapReason:Y.snapReason,snapped:Number(Y.ms)!==D,timestampIso:E,renderedTimestampIso:V$(Number(Y.ms)),action:P1(H),sourceKind:J,sourceNodeId:w,targetNodeId:V,commandId:W,raw:H},i),Z&&w&&w!==V)y.push({id:`control-arrow:${W}:${w}:${V}`,commandId:W,sourceNodeId:w,targetNodeId:V,sourceMarkerId:Z,targetMarkerId:p,sourceKind:J,action:P1(H),status:z})}}let j=[...n,...i].sort((F,U)=>Number(F.ms)-Number(U.ms)||String(F.nodeId).localeCompare(String(U.nodeId))||String(F.id).localeCompare(String(U.id)));return{...iS(j,y),sourceMarkerByCommand:$}}function QS({details:u,selectedNodeId:f,selectedNodeRuntime:l,control:r,onRaw:n}){if(!u)return G("span",{className:"muted"},"点击“抓取过程”读取 node 运行材料;主界面只显示结构化摘要,完整内容需点开原始 JSON。");let i=Vu(u.procedureRuns),y=i.at(-1)||{},_=Vu(y.attempts),$=_.at(-1)||{},A=Vu(y.workerLogTail),c=Vu($.controlEventsTail),j=Vu($.controlPromptsTail),F=Vu($.monitorPromptsTail),U=Q9(c),Q=Q9(j),L=Q9(F),w=$.opencodeMessages||{};return G("div",{className:"pipeline-evidence-list compact"},G(Or,{title:"Node runtime",subtitle:f||"--",facts:[`status ${l?.status||"pending"}`,`attempts ${l?.attempts??_.length}`,`procedure ${l?.currentProcedureRunId||Br(y)||"--"}`,r.fetchedAt?`fetched ${tf(r.fetchedAt)}`:"not fetched"],data:u.node||u,onRaw:n,testId:"raw-pipeline-node-runtime"}),G(Or,{title:"Procedure runs",subtitle:`${i.length} groups`,facts:[`latest ${y.status?.status||y.status||"--"}`,`steps ${Vu(y.recentSteps).length}`,`duration ${Hr(vu(y.finishedAt)&&vu(y.startedAt)?Number(vu(y.finishedAt))-Number(vu(y.startedAt)):y.durationMs)}`],data:i,onRaw:n,testId:"raw-pipeline-node-procedures"}),G(Or,{title:"OpenCode messages",subtitle:String(w.exists?"available":"not indexed"),facts:[`messages ${j8(w.messageCount)}`,`size ${j8(w.size)}`,`updated ${Nu(w.updatedAt)}`],data:w,onRaw:n,testId:"raw-pipeline-node-messages"}),G(Or,{title:"Control prompts",subtitle:"manual / monitor append queues",facts:[`manual tail ${Q.total}`,`monitor tail ${L.total}`,`last ${Nu(B9(Q.lastAt,L.lastAt))}`],data:{controlPromptsTail:j,monitorPromptsTail:F},onRaw:n,testId:"raw-pipeline-node-prompts"}),G(Or,{title:"Control events",subtitle:U.eventKinds.length>0?U.eventKinds.join(", "):"event tail",facts:[`tail ${U.total}`,`parsed ${U.parsed}`,`last ${Nu(U.lastAt)}`],data:c,onRaw:n,testId:"raw-pipeline-node-events"}),G(Or,{title:"Worker log",subtitle:"tail is hidden on main canvas",facts:[`tail ${A.length} lines`,"raw only via button",`procedure ${Br(y)||"--"}`],data:A,onRaw:n,testId:"raw-pipeline-node-worker-log"}))}function qS({activeRun:u,onRaw:f}){if(!u)return G(Ur,{title:"暂无运行材料",text:"没有 Pipeline epoch 时不会展示运行材料索引。"});let l=Vu(u.nodes),r=Vu(u.procedureRuns),n=Vu(u.submissions),i=Vu(u.workerLogTail),y=sW(l),_=sW(r),$=r.filter((c)=>String(c?.status||"").toLowerCase()==="failed"),A=B9(...r.flatMap((c)=>[c.updatedAt,c.finishedAt,c.startedAt]));return G("div",{className:"pipeline-evidence-list"},G(Or,{title:"Epoch overview",subtitle:u.runId||"--",facts:[`pipeline ${u.pipelineId||"--"}`,`status ${u.status||"--"}`,`started ${Nu(u.startedAt)}`,`updated ${Nu(u.updatedAt)}`],data:u,onRaw:f,testId:"raw-pipeline-run"}),G(Or,{title:"Node states",subtitle:`${l.length} nodes`,facts:[`running ${y.running||0}`,`succeeded ${y.succeeded||0}`,`failed ${y.failed||0}`,`pending ${y.pending||0}`],data:l,onRaw:f,testId:"raw-pipeline-run-nodes"}),G(Or,{title:"Procedure run index",subtitle:`${r.length} procedure records`,facts:[`succeeded ${_.succeeded||0}`,`failed ${_.failed||0}`,`latest ${Nu(A)}`,`errors ${$.length}`],data:r,onRaw:f,testId:"raw-pipeline-run-procedures"}),G(Or,{title:"OA submissions",subtitle:`${n.length} submission files`,facts:[`records ${n.length}`,`task ${j8(u.task)}`,"raw grouped by run"],data:n,onRaw:f,testId:"raw-pipeline-run-submissions"}),G(Or,{title:"Worker log tail",subtitle:"hidden from main interface",facts:[`tail ${i.length} lines`,"display raw only after click",`updated ${Nu(u.updatedAt)}`],data:i,onRaw:f,testId:"raw-pipeline-run-worker-log"}))}function NS({diagnostics:u,onRaw:f}){let l=Vu(u?.runs).filter(Du),r=Vu(u?.forbiddenResiduals),n=Du(u?.guarantees)?u.guarantees:{},i=u?.hasNeutralNodeFinishedEvidence===!0&&u?.hasNoAuditPolicyEvidence===!0&&u?.hasAuditPolicyEvidence===!0,y=u?.ok===!0&&i&&r.length===0,_=l[0]||null,$=[{label:"中性完成事实",ok:n.neutralNodeFinished===!0,hint:"node-finished 不携带流程策略"},{label:"Config 策略判定",ok:n.auditPolicyFromConfig===!0,hint:"OA backend 读取当前 epoch 配置"},{label:"控制命令来自 OA",ok:n.runnerConsumesControlCommandsFromOaEvents===!0,hint:"runner 只消费 OA control.command"},{label:"无独立审核事件",ok:n.noIndependentAuditRequestEvent===!0,hint:"审核由 node-finished + policy 派生"},{label:"无批次门禁",ok:n.noBatchFinishedControlGate===!0,hint:"下游启动由每个 node 完成驱动"}];return G("div",{className:"pipeline-oa-panel","data-testid":"pipeline-oa-event-flow-panel"},G("div",{className:"metric-grid compact"},G(Yl,{label:"OA Flow",value:y?"100%":"--",hint:String(u?.mode||"waiting diagnostics"),tone:y?"ok":"warn"}),G(Yl,{label:"禁止残留",value:r.length,hint:r.length===0?"source scan clean":"needs cleanup",tone:r.length===0?"ok":"warn"}),G(Yl,{label:"No-audit",value:u?.hasNoAuditPolicyEvidence?"OK":"--",hint:"OA 下游策略证据",tone:u?.hasNoAuditPolicyEvidence?"ok":"warn"}),G(Yl,{label:"Monitor 审核",value:u?.hasAuditPolicyEvidence?"OK":"--",hint:"OA 控制事件闭环",tone:u?.hasAuditPolicyEvidence?"ok":"warn"})),G("div",{className:"pipeline-oa-guarantees"},$.map((A)=>G("article",{key:A.label,className:`pipeline-oa-guarantee ${A.ok?"ok":"warn"}`},G(Cn,{status:A.ok?"online":"warn"},A.ok?"OK":"MISS"),G("div",null,G("strong",null,A.label),G("span",null,A.hint))))),G("div",{className:"pipeline-evidence-list compact"},l.slice(0,6).map((A)=>G(Or,{key:A.runId,title:String(A.runId||"--"),subtitle:[Number(A.monitorAuditNodeFinishedCount||0)>0?"monitor audit":"",Number(A.noAuditPolicyCount||0)>0?"no-audit policy":""].filter(Boolean).join(" / ")||"event evidence",facts:[`events ${A.eventCount||0}`,`node-finished ${A.nodeFinishedCount||0}`,`policy-in-detail ${A.nodeFinishedWithPolicyCount||0}`,`queued ${A.controlQueuedCount||0}`,`applied ${A.controlAppliedCount||0}`],data:A,onRaw:f,testId:`raw-pipeline-oa-run-${String(A.runId||"run").replace(/[^a-zA-Z0-9_.-]+/g,"-")}`}))),_?G("p",{className:"muted paragraph"},`最新证据 ${_.runId}: ${_.nodeFinishedCount||0} 个 node-finished,${_.controlAppliedCount||0} 个控制结果。`):G(Ur,{title:"暂无 OA 事件流证据",text:"等待 Pipeline backend 暴露 diagnostics。"}),u?G("div",{className:"panel-actions inline-actions"},G(gr,{title:"Pipeline OA Event Flow Diagnostics",data:u,onOpen:f,testId:"raw-pipeline-oa-event-flow"})):null)}function WS({quota:u,onRaw:f}){let l=Du(u?.summary)?u.summary:{},r=Du(u?.target)?u.target:{},n=Du(u?.cache)?u.cache:{},i=u?.ok===!0,y=String(u?.modelId||l.modelName||r.modelName||"MiniMax-M2.7"),_=l.totalCount??r.currentIntervalTotalCount,$=l.usageCount??r.currentIntervalUsageCount,A=l.remainingCount??r.currentIntervalRemainingCount,c=l.remainingRatio??(Number.isFinite(Number(_))&&Number(_)>0&&Number.isFinite(Number(A))?Number(A)/Number(_):void 0),j=l.usageRatio??(Number.isFinite(Number(_))&&Number(_)>0&&Number.isFinite(Number($))?Number($)/Number(_):void 0),F=l.resetAt||r.endAt,U=l.remainsMs??r.remainsMs,Q=Number(A),L=!i||Number.isFinite(Q)&&Q<=0?"warn":"ok",w=[i?`endpoint ${u?.endpoint||"--"}`:"quota unavailable",`fetched ${c8(u?.fetchedAt)}`,n.hit?`cache ${Hr(n.ageMs)}`:"live quota"];return G("div",{className:"pipeline-minimax-quota-panel","data-testid":"pipeline-minimax-quota-panel"},G("div",{className:"metric-grid compact"},G(Yl,{label:"MiniMax",value:i?y:"--",hint:u?.modelComponent||u?.error||"model/minimax-m27",tone:L}),G(Yl,{label:"当前窗口",value:`${U9($)}/${U9(_)}`,hint:`已用 ${gW(j)}`,tone:L}),G(Yl,{label:"剩余额度",value:U9(A),hint:`剩余 ${gW(c)}`,tone:L}),G(Yl,{label:"重置时间",value:c8(F),hint:U!==void 0?`约 ${Hr(U)}`:Nu(F),tone:L})),G(D9,{items:w}),i?G("p",{className:"muted paragraph"},`MiniMax 限额来自 D601 Pipeline 后端实时查询;当前模型匹配 ${l.modelName||r.modelName||y}。`):G(yf,{error:u?.error||"MiniMax 限额查询失败"}),u?G("div",{className:"panel-actions inline-actions"},G(gr,{title:"Pipeline MiniMax Quota",data:u,onOpen:f,testId:"raw-pipeline-minimax-quota"})):null)}function LS({epochs:u,activeRun:f,activePipeline:l,pipelineNodes:r,pipelineEdges:n,runDetails:i,nodeDetails:y,nodeDetailsState:_,ganttScale:$=X$,onGanttScaleChange:A,onRunChange:c,onIntervalSelect:j,onMarkerSelect:F,selection:U,detailOpen:Q,onDetailOpenChange:L,onRaw:w}){let[J,N]=gl(oY),[q,W]=gl({startY:0,endY:0,startMs:0,endMs:0}),[z,Z]=gl(Date.now()),H=Pn(null),E=String(f?.runId||""),D=Boolean(Q),h=(cu)=>{if(typeof L==="function")L(cu)},V=Rn($??X$),Y=String(i?.runId||"")===E?i?.details:null,p=Y?{...Du(f)?f:{},...Du(Y)?Y:{},runId:E,procedureRuns:Vu(Y?.procedureRuns).length>0?Y.procedureRuns:f?.procedureRuns}:f,O=TL(p,r,z),m=Y?US(Y,p):{markers:[],arrows:[]},X=Vu(m.markers),v=aY(p,O,X),T=lS(v,V,O,z),S=String(T.source||"frontend-y"),k=O.map((cu)=>rS(cu,T,z)),I={startMs:Number(T.startMs),endMs:Number(T.endMs),durationMs:Math.max(1,Number(T.durationMs??Number(T.endMs)-Number(T.startMs)))},b=m9(V),o={...b,pxPerMinute:Number(T.pxPerMinute??b.pxPerMinute)},s=Math.round(Number(T.chartHeight||360)),x=O.some(P9);j0(()=>{if(!E||!x)return;let cu=window.setInterval(()=>Z(Date.now()),1000);return()=>window.clearInterval(cu)},[E,x]);let fu=CY(l,r,Array.isArray(n)?n:[]),$u=r.map((cu)=>String(cu?.id||"")).filter(Boolean),tu=k.map((cu)=>String(cu.nodeId||"")).filter(Boolean),ju=X.map((cu)=>String(cu.nodeId||"")).filter(Boolean),Gu=Array.from(new Set([...fu,...$u,...tu,...ju])),qu={startY:0,endY:s,startMs:Number(I.startMs),endMs:Number(I.endMs)},P=Number(q?.endY||0)>0?q:qu,e=(cu)=>{return N8(cu,I,s,T)<=Number(P.endY)&&H9(cu,I,s,T)>=Number(P.startY)},uu=(cu)=>{let ku=Jr(cu,I,s,T);return ku>=Number(P.startY)&&ku<=Number(P.endY)},Wu=new Set(Gu.filter((cu)=>k.some((ku)=>ku.nodeId===cu&&e(ku))||X.some((ku)=>ku.nodeId===cu&&uu(ku)))),g=J?Gu.filter((cu)=>Wu.has(cu)):Gu,Qu=`${F9}px ${g.length>0?g.map(()=>`${A0}px`).join(" "):"minmax(160px, 1fr)"}`,Tu=Vu(T.ticks).filter(Du),Zu=String(U?.mode==="interval"?U?.interval?.procedureRunId||"":""),Xu=String(U?.mode==="event"?U?.marker?.id||"":""),uf=()=>{let cu=H.current;if(!cu){W(qu);return}let ku=Math.max(0,cu.scrollTop-J9),Tl=Math.max(120,cu.clientHeight-J9),pu=Math.min(s,ku+Tl),rl={startY:ku,endY:pu,startMs:Number(I.startMs),endMs:Number(I.endMs)},El=Math.max(0,Math.min(1,ku/s)),Jl=Math.max(El,Math.min(1,pu/s)),nl=Math.max(1,Number(I.endMs)-Number(I.startMs));rl.startMs=Number(I.startMs)+nl*El,rl.endMs=Number(I.startMs)+nl*Jl,W(rl)};j0(()=>{let cu=H.current,ku=window.setTimeout(uf,0);return cu?.addEventListener("scroll",uf),window.addEventListener("resize",uf),()=>{window.clearTimeout(ku),cu?.removeEventListener("scroll",uf),window.removeEventListener("resize",uf)}},[E,I.startMs,I.endMs,s]);let _f=Math.max(0,Gu.length-g.length),Jf=new Set(X.filter((cu)=>g.includes(String(cu.nodeId||""))&&uu(cu)).map((cu)=>String(cu.id))),Pf=new Map(X.map((cu)=>[String(cu.id),cu])),Sl=Vu(m.arrows).filter((cu)=>{if(!Jf.has(String(cu.targetMarkerId||"")))return!1;if(String(cu.action||"")==="observe")return g.includes(String(cu.sourceNodeId||""));return Jf.has(String(cu.sourceMarkerId||""))}),vf=F9+Math.max(1,g.length)*A0,ll=(cu)=>{let ku=Rn(cu.target.value);if(typeof A==="function")A(ku);window.setTimeout(uf,0)},dl=()=>IY({title:`${l?.id||"pipeline"}-${E||"epoch"}-gantt`,meta:[`run ${E||"--"}`,`${Nu(I.startMs)} -> ${Nu(I.endMs)}`,`duration ${Hr(I.durationMs)}`,`${o.label} / ${L9(o.pxPerMinute)} px/min`,`${g.length}/${Gu.length} nodes`,`${X.length} markers`],visibleNodeIds:g,intervals:k,markers:X.filter((cu)=>g.includes(String(cu.nodeId||""))),arrows:Sl,ticks:Tu,bounds:I,chartHeight:s,backendLayout:T}),el=Du(Y?.gantt?.diagnostics)?Y.gantt.diagnostics:null;return G(c0,{title:"Epoch 甘特图",eyebrow:`${l?.id||"pipeline"} / ${u.length} epochs`,className:"pipeline-wide-panel",loading:i?.loading,actions:G("div",{className:"pipeline-gantt-actions"},G("select",{value:E,disabled:u.length===0,onChange:(cu)=>c(cu.target.value),"data-testid":"pipeline-epoch-select"},u.map((cu)=>G("option",{key:cu.runId,value:cu.runId},Z9(u,cu)))),G("label",{className:"pipeline-gantt-toggle"},G("input",{type:"checkbox","data-testid":"pipeline-gantt-auto-hide-idle",checked:J,onChange:(cu)=>{N(Boolean(cu.target.checked)),window.setTimeout(uf,0)}}),G("span",null,"自动隐藏空闲列")),G("label",{className:"pipeline-gantt-scale"},G("span",null,G("b",null,"时间尺度"),G("em",{"data-testid":"pipeline-gantt-scale-label"},`${o.label} · ${L9(o.pxPerMinute)} px/min`)),G("input",{type:"range",min:0,max:100,step:0.01,value:V,onChange:ll,"aria-label":"调整甘特图时间尺度","data-testid":"pipeline-gantt-time-scale"}),G("small",null,G("span",null,"全局"),G("span",null,"细节"))),f?G("button",{type:"button",className:"ghost-btn",onClick:dl,disabled:g.length===0,"data-testid":"pipeline-export-gantt"},"导出甘特图"):null,f?G(gr,{title:`Pipeline Epoch ${f.runId}`,data:f,onOpen:w,testId:"raw-pipeline-epoch-gantt"}):null)},!f?G(Ur,{title:"暂无 Epoch",text:"当前 pipeline 还没有完整运行记录。"}):k.length===0?G(Ur,{title:"暂无时间区间",text:"等待 D601 Pipeline backend 在 procedure summary 中返回 startedAt / finishedAt。"}):G("div",{className:"pipeline-gantt-wrap"},G("div",{className:`pipeline-gantt-detail-layout ${D?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-gantt-detail-layout","data-sidebar-open":D?"true":"false"},G("div",{className:"pipeline-gantt-main"},G("div",{className:"pipeline-gantt-main-head"},G("div",{className:"pipeline-gantt-meta"},G("span",null,`time ${Nu(I.startMs)} -> ${Nu(I.endMs)}`),G("span",null,`duration ${Hr(I.durationMs)}`),G("span",null,`scale ${o.label} / ${L9(o.pxPerMinute)} px/min`),G("span",null,`layout ${S}`),el?G("span",null,`align ${el.timeAxisAlignmentOk===!1?"check":"ok"}`):null,G("span",null,`visible ${g.length}/${Gu.length} nodes`),Y?G("span",null,`markers ${X.length}`):null,J&&_f>0?G("span",null,`hidden idle ${_f}`):null),!D?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!U?.mode,onClick:()=>h(!0),"data-testid":"pipeline-gantt-sidebar-toggle"},U?.mode?"展开详情":"点击甘特图元素展开详情"):null),G("div",{className:"pipeline-gantt-viewport",ref:H,"data-testid":"pipeline-epoch-gantt","data-pipeline-id":l?.id||"","data-run-id":E,"data-layout-source":S,"data-start-ms":String(I.startMs),"data-end-ms":String(I.endMs),"data-chart-height":String(s)},G("div",{className:"pipeline-gantt-board",style:{gridTemplateColumns:Qu,minWidth:`${vf}px`}},G("div",{className:"pipeline-gantt-head time"},"Time"),g.length===0?G("div",{className:"pipeline-gantt-head empty"},"当前时间窗无工作节点"):g.map((cu)=>G("div",{key:`head-${cu}`,className:"pipeline-gantt-head node",title:cu,"data-testid":"pipeline-gantt-head-node","data-node-id":cu},G(wY,{value:cu}))),G("div",{className:"pipeline-gantt-time-axis",style:{height:`${s}px`}},Tu.map((cu)=>{let ku=VL(cu,I,s,T);return G("div",{key:`tick-${cu.ms}-${ku}`,className:"pipeline-gantt-tick",style:{top:`${ku}px`},"data-testid":"pipeline-gantt-tick","data-ms":String(cu.ms),"data-y":String(ku)},G("b",null,Nu(cu.ms)),G("span",null,`+${Hr(Number(cu.offsetMs??Number(cu.ms)-Number(I.startMs)))}`))})),g.length>0?G("svg",{className:"pipeline-gantt-arrow-layer",width:g.length*A0,height:s,viewBox:`0 0 ${g.length*A0} ${s}`,style:{left:`${F9}px`,top:`${J9}px`,width:`${g.length*A0}px`,height:`${s}px`},"aria-hidden":"true"},G("defs",null,G("marker",{id:"pipeline-gantt-arrowhead",viewBox:"0 0 10 10",refX:9,refY:5,markerWidth:6,markerHeight:6,orient:"auto-start-reverse"},G("path",{d:"M 0 0 L 10 5 L 0 10 z",fill:"context-stroke"}))),Sl.map((cu)=>{let ku=Pf.get(String(cu.targetMarkerId||""));if(!ku)return null;let Tl=Pf.get(String(cu.sourceMarkerId||"")),pu=String(Tl?.nodeId||cu.sourceNodeId||""),rl=g.indexOf(pu),El=g.indexOf(String(ku.nodeId||""));if(rl<0||El<0)return null;let Jl=rl*A0+A0/2,nl=El*A0+A0/2,pl=Tl?Jr(Tl,I,s,T):Jr(ku,I,s,T),qr=Jr(ku,I,s,T);return G("path",{key:cu.id,className:`pipeline-gantt-arrow ${String(cu.sourceKind||"").toLowerCase()} ${String(cu.status||"").toLowerCase()} ${String(cu.action||"").toLowerCase()}`,d:DL(Jl,pl,nl,qr),markerEnd:"url(#pipeline-gantt-arrowhead)","data-testid":String(cu.action||"")==="observe"?"pipeline-gantt-observation-arrow":"pipeline-gantt-arrow","data-source-node-id":String(cu.sourceNodeId||""),"data-target-node-id":String(cu.targetNodeId||""),"data-target-marker-id":String(cu.targetMarkerId||""),"data-action":String(cu.action||""),"data-source-y":String(pl),"data-target-y":String(qr)})})):null,g.length===0?G("div",{className:"pipeline-gantt-empty-col",style:{height:`${s}px`}},"滚动到有活动的时间段后,相关 node 列会自动出现。"):g.map((cu)=>{let ku=k.filter((pu)=>pu.nodeId===cu),Tl=X.filter((pu)=>String(pu.nodeId||"")===cu);return G("div",{key:`col-${cu}`,className:"pipeline-gantt-node-col",style:{height:`${s}px`}},ku.map((pu)=>{let rl=N8(pu,I,s,T),El=H9(pu,I,s,T),Jl=BL(pu,I,s,T),nl=String(pu.procedureRunId||`${cu}-${pu.startMs}`);return G("button",{key:nl,type:"button",className:`pipeline-gantt-bar ${pu.status} ${pu.live?"live":""} ${Zu===nl?"selected":""}`,style:{top:`${rl}px`,height:`${Jl}px`},title:`${cu} ${pu.status} ${Nu(pu.startedAt||pu.startMs)} -> ${Nu(pu.finishedAt||pu.endMs)}`,onClick:()=>j(pu),"data-testid":"pipeline-gantt-line","data-node-id":cu,"data-procedure-run-id":String(pu.procedureRunId||""),"data-status":String(pu.status||""),"data-live":pu.live?"true":"false","data-start-ms":String(pu.startMs||""),"data-end-ms":String(pu.endMs||""),"data-y1":String(rl),"data-y2":String(El),"data-natural-height":String(Math.max(0,El-rl))},G("strong",null,pu.status||"working"),G("span",null,Hr(pu.durationMs)))}),Tl.map((pu)=>G("button",{key:pu.id,type:"button",className:`pipeline-gantt-marker ${pu.kind} ${pu.tone||""} ${pu.status||""} ${Xu===String(pu.id)?"selected":""}`,style:{top:`${Jr(pu,I,s,T)}px`},title:`${pu.label||"event"} / ${Nu(pu.timestampIso||pu.timestamp||pu.ms)}`,onClick:()=>F(pu),"data-testid":pu.kind==="prompt"?"pipeline-gantt-prompt-marker":"pipeline-gantt-control-marker","data-marker-id":String(pu.id||""),"data-ms":String(pu.ms??pu.eventMs??""),"data-y":String(Jr(pu,I,s,T))})))})))),D?G(LY,{selection:U,runDetails:i,nodeDetails:y,nodeDetailsState:_,onRaw:w,onCollapse:()=>h(!1)}):null)))}function R0(){return{loading:!1,actionLoading:"",error:"",message:"",details:null,fetchedAt:null,appendPrompt:"",guidePrompt:"",modifyPrompt:"",approveReason:"",redoReason:""}}function mn(){return{mode:"",runId:"",interval:null,marker:null}}function w9(){return{runId:"",loading:!1,error:"",details:null,fetchedAt:null}}function E$(u,f){return`${u}/microservices/pipeline/proxy${f}`}function wS({activeRun:u,pipelineRuns:f,selectedRunId:l,onRunChange:r,selectedNodeId:n,selectedNodeConfig:i,selectedNodeRuntime:y,control:_,onControlChange:$,onFetch:A,onAction:c,onRaw:j,onCollapse:F}){let U=String(u?.runId||""),Q=String(y?.status||"pending"),L=!U||!n||_.loading||Boolean(_.actionLoading),w=(N)=>(q)=>$({[N]:q.target.value,error:"",message:""}),J=f.length>0?f:u?[u]:[];return G("aside",{className:"pipeline-node-control","data-testid":"pipeline-node-control"},G("div",{className:"pipeline-node-control-head"},G("div",null,G("p",{className:"panel-eyebrow"},"Manual Node Control"),G(nf,{title:n||"点击控制图中的 node",level:3,loading:_.loading||Boolean(_.actionLoading)})),G("div",{className:"pipeline-node-control-head-actions"},n?G(Cn,{status:Q},Q):G(Cn,{status:"pending"},"idle"),G("button",{type:"button",className:"ghost-btn mini",onClick:F,"data-testid":"pipeline-node-sidebar-collapse"},"收起"))),G("div",{className:"pipeline-control-runbar"},G("label",null,G("span",null,"目标 run"),G("select",{value:U||l,disabled:J.length===0,onChange:(N)=>r(N.target.value),"data-testid":"pipeline-node-run-select"},J.map((N)=>G("option",{key:N.runId,value:N.runId},`${N.runId||"--"} / ${N.status||"--"}`)))),G("button",{type:"button",className:"ghost-btn",disabled:L,onClick:A,"data-testid":"pipeline-node-fetch"},_.loading?"抓取中":"抓取过程"),_.details?G(gr,{title:`Pipeline Node ${n}`,data:_.details,onOpen:j,testId:"raw-pipeline-node-control"}):null),G("div",{className:"pipeline-control-meta"},G("span",null,G("b",null,"kind"),String(i?.kind||"--")),G("span",null,G("b",null,"procedure"),String(y?.currentProcedureRunId||"--")),G("span",null,G("b",null,"attempts"),String(y?.attempts??"--")),G("span",null,G("b",null,"updated"),Nu(u?.updatedAt))),!n?G(Ur,{title:"未选择 node",text:"点击 React Flow 控制图中的任意 node 后,可抓取执行过程、追加 prompt、下发引导、增量修改、审核通过或重做。"}):null,G(yf,{error:_.error,wide:!0}),G("div",{className:"pipeline-control-actions"},G("label",null,G("span",null,"实时追加 prompt(仅 running node)"),G("textarea",{value:_.appendPrompt,onChange:w("appendPrompt"),placeholder:"让当前执行中的 agent 继续、补充检查或调整当前步骤...",rows:4,disabled:!n,"data-testid":"pipeline-node-append-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:L||!String(_.appendPrompt||"").trim(),onClick:()=>c("append"),"data-testid":"pipeline-node-append-button"},_.actionLoading==="append"?"追加中":"追加到运行中 node")),G("label",null,G("span",null,"下次尝试引导 prompt"),G("textarea",{value:_.guidePrompt,onChange:w("guidePrompt"),placeholder:"给该 node 下一次 attempt 的执行提示;不会立即打断当前 session。",rows:4,disabled:!n,"data-testid":"pipeline-node-guide-input"}),G("button",{type:"button",className:"ghost-btn compact",disabled:L||!String(_.guidePrompt||"").trim(),onClick:()=>c("guide"),"data-testid":"pipeline-node-guide-button"},_.actionLoading==="guide"?"下发中":"下发 guide")),G("label",null,G("span",null,"完成后增量修改 prompt"),G("textarea",{value:_.modifyPrompt,onChange:w("modifyPrompt"),placeholder:"在该 node 已完成结果基础上追加修改要求;runner 会重跑目标 node,并保留同 node 既有 OA 输出作为上下文。",rows:4,disabled:!n,"data-testid":"pipeline-node-modify-input"}),G("button",{type:"button",className:"ghost-btn compact",disabled:L||!String(_.modifyPrompt||"").trim(),onClick:()=>c("modify"),"data-testid":"pipeline-node-modify-button"},_.actionLoading==="modify"?"排队中":"增量修改 node")),G("label",null,G("span",null,"Monitor 审核通过原因"),G("textarea",{value:_.approveReason,onChange:w("approveReason"),placeholder:"当流程配置开启 monitor 审核时,记录审核通过原因并释放后续 node。",rows:3,disabled:!n,"data-testid":"pipeline-node-approve-input"}),G("button",{type:"button",className:"primary-btn compact",disabled:L||!String(_.approveReason||"").trim(),onClick:()=>c("approve"),"data-testid":"pipeline-node-approve-button"},_.actionLoading==="approve"?"提交中":"审核通过")),G("label",null,G("span",null,"重做 / restart 原因"),G("textarea",{value:_.redoReason,onChange:w("redoReason"),placeholder:"说明为什么需要重做;runner 会重置目标 node 以及非 rework 下游 node。",rows:4,disabled:!n,"data-testid":"pipeline-node-redo-input"}),G("button",{type:"button",className:"danger-btn compact",disabled:L||!String(_.redoReason||"").trim(),onClick:()=>c("redo"),"data-testid":"pipeline-node-redo-button"},_.actionLoading==="redo"?"排队中":"重做 node"))),G("div",{className:"pipeline-control-evidence"},G("strong",null,"Node 过程索引"),G(QS,{details:_.details,selectedNodeId:n,selectedNodeRuntime:y,control:_,onRaw:j})))}function XL({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((lu)=>lu.id==="pipeline")||null,[n,i]=gl({loading:!1,error:"",health:null,snapshot:null,oaDiagnostics:null,minimaxQuota:null,refreshedAt:null}),[y,_]=gl(""),[$,A]=gl(""),[c,j]=gl(""),[F,U]=gl(R0()),[Q,L]=gl({}),[w,J]=gl(mn()),[N,q]=gl(w9()),[W,z]=gl(X$),[Z,H]=gl(!1),[E,D]=gl(!1),h=Pn(0),{addNotification:V}=Vl(),Y=Pn(!1),p=Pn(0),O=Pn(""),m=Pn({}),X=Pn(""),v=Pn("");async function T(lu={}){let Ou=lu.silent===!0;if(!r)return;if(Y.current)return;Y.current=!0;let Yu=h.current+1;if(h.current=Yu,!Ou)i((Iu)=>({...Iu,loading:!0,error:""}));try{let Iu=`__unideskArrayLimit=registry.components:80,runs:${rY}`,[Qf,il,ff]=await Promise.all([pn(`${l}/microservices/pipeline/proxy/api/snapshot?${Iu}`,{cache:"no-store"}),pn(`${l}/microservices/pipeline/proxy/api/oa-event-flow/diagnostics`,{cache:"no-store"}).catch(($f)=>({ok:!1,error:Hu($f,"OA event flow diagnostics failed")})),pn(`${l}/microservices/pipeline/proxy/api/model-quota/minimax`,{cache:"no-store"}).catch(($f)=>({ok:!1,error:Hu($f,"MiniMax quota failed")}))]);if(Yu!==h.current)return;let df={ok:Qf?.ok!==!1,service:"pipeline-v2-control snapshot"};i({loading:!1,error:"",health:df,snapshot:Qf,oaDiagnostics:il,minimaxQuota:ff,refreshedAt:new Date})}catch(Iu){if(Yu!==h.current)return;i((Qf)=>({...Qf,loading:!1,error:Hu(Iu,"Pipeline 加载失败")}))}finally{Y.current=!1}}j0(()=>{if(T(),!r)return;let lu=()=>{if(y8())T({silent:!0})},Ou=window.setInterval(()=>{lu()},vW),Yu=()=>{if(y8())lu()};return document.addEventListener("visibilitychange",Yu),()=>{window.clearInterval(Ou),document.removeEventListener("visibilitychange",Yu)}},[r?.id,r?.runtime?.providerStatus,l]);let S=KY(r),k=zY(r),I=GY(r),b=n.snapshot||{},o=n.oaDiagnostics||null,s=n.minimaxQuota||null,{components:x,pipelines:fu,runs:$u}=TY(b),tu=String($u[0]?.pipelineId||""),ju=(tu?fu.find((lu)=>String(lu.id||"")===tu):null)||fu[0]||{},Gu=fu.find((lu)=>String(lu.id||"")===y)||ju,qu=String(Gu.id||""),P=LL(Gu),e=Y9(Gu),uu=_L($u,qu),Wu=sY($u,qu),g=Wu.find((lu)=>String(lu?.runId||"")===$)||uu,Qu=String(N.runId||"")===String(g?.runId||"")?HY(N.details):null,Tu=BY(g,Qu),Zu=String(Tu?.runId||""),Xu=P.find((lu)=>String(lu?.id||"")===c)||null,uf=c?wL(Tu,c):null,_f=ZY($u),Jf=YY(x),Pf=Number(n.health?.components)||uL(b,"registry.components",x.length),Sl=uL(b,"runs",$u.length),vf=rL(Gu,Tu,x),ll={nodes:vf.nodes.map((lu)=>lu.id===c?{...lu,selected:!0,className:`${lu.className||""} selected-control-node`}:lu),edges:vf.edges},dl=fu.map((lu)=>{let Ou=String(lu.id||"pipeline"),Yu=_L($u,Ou);return{title:`${Ou}-${Yu?.runId||"snapshot"}`,flow:rL(lu,Yu,x)}}),el=String(w?.runId||Zu||""),cu=String(w?.interval?.nodeId||w?.marker?.nodeId||""),ku=el&&cu?Q[W9(el,cu)]||null:null,Tl=F8(F.details,el,cu),pu=F8(ku?.details,el,cu)||Tl,rl=el&&cu?{...Du(ku)?ku:{},runId:el,nodeId:cu,details:pu,loading:Boolean(ku?.loading)||!pu&&Boolean(F.loading)&&c===cu,error:String(ku?.error||""),fetchedAt:ku?.fetchedAt||(Tl?F.fetchedAt:null)}:null,El=Wu.map((lu)=>String(lu?.runId||"")).filter(Boolean).join("|"),Jl=P.map((lu)=>String(lu?.id||"")).filter(Boolean).join("|");j0(()=>{X.current=c},[c]),j0(()=>{v.current=Zu},[Zu]),j0(()=>{if(!$||El.split("|").includes($))return;A("")},[$,El]),j0(()=>{if(!c||Jl.split("|").includes(c))return;j(""),U(R0()),J(mn()),H(!1),D(!1)},[c,Jl]),j0(()=>{if(!c)H(!1)},[c]),j0(()=>{if(!w.mode)D(!1)},[w.mode]);async function nl(lu=Zu,Ou={}){if(!lu){q(w9());return}let Yu=Rn(Ou.scale??W??X$),Iu=`${lu}:timeline`;if(O.current===Iu)return;O.current=Iu;let Qf=Ou.silent===!0,il=p.current+1;p.current=il,q((ff)=>({runId:lu,scale:Yu,loading:!Qf||String(ff.runId||"")!==lu||!ff.details,error:"",details:Qf&&ff.runId===lu?ff.details:ff.runId===lu?ff.details:null,fetchedAt:ff.runId===lu?ff.fetchedAt:null}));try{let[ff,df]=await Promise.all([pn(E$(l,`/api/node-control/runs/${encodeURIComponent(lu)}?tail=160&view=timeline`),{cache:"no-store",strictJson:!0}),pn(E$(l,`/api/runs/${encodeURIComponent(lu)}`),{cache:"no-store"}).catch(($f)=>({ok:!1,runSummaryError:Hu($f,"抓取评分失败")}))]);if(il!==p.current)return;q({runId:lu,scale:Yu,loading:!1,error:"",details:{...ff,run:Du(df?.run)?df.run:void 0,runSummaryError:df?.runSummaryError},fetchedAt:new Date})}catch(ff){if(il!==p.current)return;q((df)=>({runId:lu,scale:Yu,loading:!1,error:Hu(ff,"抓取 epoch 执行过程失败"),details:df.runId===lu?df.details:null,fetchedAt:df.runId===lu?df.fetchedAt:null}))}finally{if(O.current===Iu)O.current=""}}function pl(lu,Ou,Yu){let Iu=W9(lu,Ou);L((Qf)=>{let il={...Qf,[Iu]:{...Du(Qf?.[Iu])?Qf[Iu]:{},runId:lu,nodeId:Ou,...Yu}},ff=Object.keys(il);if(ff.length>32)for(let df of ff.slice(0,ff.length-32))delete il[df];return il})}async function qr(lu,Ou){if(!lu||!Ou)return;let Yu=W9(lu,Ou),Iu=Number(m.current?.[Yu]||0)+1;m.current={...m.current,[Yu]:Iu},pl(lu,Ou,{loading:!0,error:""});try{let Qf=await pn(E$(l,`/api/node-control/runs/${encodeURIComponent(lu)}/nodes/${encodeURIComponent(Ou)}?tail=160`),{cache:"no-store",strictJson:!0});if(Number(m.current?.[Yu]||0)!==Iu)return;let il=new Date;if(pl(lu,Ou,{loading:!1,details:Qf,fetchedAt:il,error:""}),X.current===Ou&&v.current===lu)U((ff)=>({...ff,loading:!1,details:Qf,fetchedAt:il,error:""}))}catch(Qf){if(Number(m.current?.[Yu]||0)!==Iu)return;pl(lu,Ou,{loading:!1,error:Hu(Qf,"抓取 Gantt node 详情失败")})}}j0(()=>{if(!Zu){q(w9());return}nl(Zu);let lu=()=>{if(y8())nl(Zu,{silent:!0})},Ou=window.setInterval(()=>{lu()},vW),Yu=()=>{if(y8())lu()};return document.addEventListener("visibilitychange",Yu),()=>{window.clearInterval(Ou),document.removeEventListener("visibilitychange",Yu)}},[Zu,l]);async function rf(lu=Zu,Ou=c){if(!lu||!Ou){U((Yu)=>({...Yu,error:"请先选择 run 和 node",message:""}));return}U((Yu)=>({...Yu,loading:!0,error:"",message:""}));try{let Yu=await pn(E$(l,`/api/node-control/runs/${encodeURIComponent(lu)}/nodes/${encodeURIComponent(Ou)}?tail=160`),{cache:"no-store",strictJson:!0}),Iu=new Date;U((Qf)=>({...Qf,loading:!1,details:Yu,fetchedAt:Iu,error:""})),pl(lu,Ou,{loading:!1,details:Yu,fetchedAt:Iu,error:""})}catch(Yu){U((Iu)=>({...Iu,loading:!1,error:Hu(Yu,"抓取 node 执行过程失败")}))}}async function C1(lu){let Ou=String(lu?.runId||Zu||""),Yu=String(lu?.nodeId||"");if(J({mode:"interval",runId:Ou,interval:lu,marker:null}),D(!0),!Ou||!Yu)return;if(Ou!==Zu)A(Ou);j(Yu),U(R0()),nl(Ou,{silent:!0}),qr(Ou,Yu)}async function kn(lu){let Ou=String(lu?.runId||Zu||""),Yu=String(lu?.nodeId||"");if(J({mode:"event",runId:Ou,interval:null,marker:lu}),D(!0),!Ou)return;if(Ou!==Zu)A(Ou);if(nl(Ou,{silent:!0}),!Yu)return;j(Yu),U(R0()),qr(Ou,Yu)}async function R1(lu){if(!Zu||!c){U((Iu)=>({...Iu,error:"请先选择 run 和 node",message:""}));return}let Ou=lu==="append"?"prompts":lu,Yu=lu==="append"?F.appendPrompt:lu==="guide"?F.guidePrompt:lu==="modify"?F.modifyPrompt:lu==="approve"?F.approveReason:F.redoReason;if(!String(Yu||"").trim()){U((Iu)=>({...Iu,error:"操作内容不能为空",message:""}));return}U((Iu)=>({...Iu,actionLoading:lu,error:"",message:""}));try{let Iu=lu==="redo"||lu==="approve"?{reason:Yu,source:"unidesk-frontend",sourceKind:"webui"}:{prompt:Yu,source:"unidesk-frontend",sourceKind:"webui"},Qf=await pn(E$(l,`/api/node-control/runs/${encodeURIComponent(Zu)}/nodes/${encodeURIComponent(c)}/${Ou}`),{method:"POST",body:JSON.stringify(Iu)});if(U((ff)=>({...ff,actionLoading:"",details:Qf,fetchedAt:new Date,appendPrompt:lu==="append"?"":ff.appendPrompt,guidePrompt:lu==="guide"?"":ff.guidePrompt,modifyPrompt:lu==="modify"?"":ff.modifyPrompt,approveReason:lu==="approve"?"":ff.approveReason,redoReason:lu==="redo"?"":ff.redoReason,message:lu==="append"?"已追加到运行中 node":lu==="guide"?"已下发 guide,等待 runner 处理":lu==="modify"?"已排队增量修改命令":lu==="approve"?"已提交审核通过决策":"已排队重做命令"})),V("success",lu==="append"?"已追加到运行中 node":lu==="guide"?"已下发 guide,等待 runner 处理":lu==="modify"?"已排队增量修改命令":lu==="approve"?"已提交审核通过决策":"已排队重做命令"),await rf(Zu,c),await nl(Zu,{silent:!0}),lu!=="append")await T()}catch(Iu){U((Qf)=>({...Qf,actionLoading:"",error:Hu(Iu,"node 控制操作失败")}))}}if(!r)return G(Ur,{title:"Pipeline 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=pipeline"});return G("div",{className:"pipeline-page","data-testid":"pipeline-page"},G(c0,{title:"Pipeline v2 工作台",eyebrow:"D601 Snapshot 用户服务",loading:n.loading,actions:G("div",{className:"panel-actions"},G("button",{type:"button",className:"ghost-btn",onClick:T,disabled:n.loading,"data-testid":"pipeline-refresh-button"},n.loading?"刷新中":"刷新"),G(gr,{title:"Pipeline 用户服务",data:r,onOpen:f,testId:"raw-pipeline-service"}))},G("div",{className:"pipeline-hero"},G("div",null,G("div",{className:"node-version-line"},G(Cn,{status:S.providerStatus==="online"?"online":"warn"},S.providerStatus||"unknown"),G("span",null,r.providerId),G("span",null,I.public?"公网暴露":"仅 UniDesk frontend 代理访问")),G("p",{className:"muted paragraph"},r.description)),G("div",{className:"microservice-ref-card"},G("span",null,"Repo"),G("strong",null,k.url||"--"),G("code",null,k.commitId||"--")),G("div",{className:"microservice-ref-card"},G("span",null,"D601 Docker"),G("strong",null,`${I.nodeBindHost||"--"}:${I.nodePort||"--"}`),G("code",null,`${k.composeFile||"--"} / ${k.composeService||"--"}`))),G(yf,{error:n.error,wide:!0})),G("div",{className:"pipeline-grid"},G(c0,{title:"控制图",eyebrow:`${Gu.id||"pipeline"} / run ${Tu?.status||"--"}`,className:"pipeline-wide-panel",loading:n.loading,actions:G("div",{className:"pipeline-toolbar"},G("select",{value:qu,disabled:fu.length===0,onChange:(lu)=>{_(lu.target.value),A(""),j(""),U(R0()),J(mn()),H(!1),D(!1)},"data-testid":"pipeline-select"},fu.map((lu)=>G("option",{key:lu.id,value:lu.id},lu.id||lu.key))),G("select",{value:Zu,disabled:Wu.length===0,onChange:(lu)=>{if(A(lu.target.value),U(R0()),J(mn()),H(!1),D(!1),c)rf(lu.target.value,c)},"data-testid":"pipeline-run-select"},Wu.map((lu)=>G("option",{key:lu.runId,value:lu.runId},Z9(Wu,lu)))),G("button",{type:"button",className:"ghost-btn",disabled:ll.nodes.length===0,onClick:()=>zL(ll,`${Gu.id||"pipeline"}-${Tu?.runId||"snapshot"}`),"data-testid":"pipeline-export-graph"},"导出渲染图"),G("button",{type:"button",className:"ghost-btn",disabled:dl.every((lu)=>lu.flow.nodes.length===0),onClick:()=>gY(dl),"data-testid":"pipeline-export-all-graphs"},"批量导出"))},P.length===0?G(Ur,{title:"暂无控制图",text:"等待 D601 pipeline backend 返回 config.nodes / config.edges"}):G("div",{className:`pipeline-control-shell ${Z?"detail-open":"detail-collapsed"}`,"data-testid":"pipeline-control-shell","data-sidebar-open":Z?"true":"false"},G("div",{className:"pipeline-flow-frame","data-testid":"pipeline-react-flow"},G(PW,{nodes:ll.nodes,edges:ll.edges,nodeTypes:$Y,edgeTypes:_Y,fitView:!0,fitViewOptions:{padding:0.18},nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,minZoom:0.25,maxZoom:1.4,proOptions:{hideAttribution:!0},onNodeClick:(lu,Ou)=>{let Yu=String(Ou.id);if(j(Yu),U(R0()),H(!0),Zu)rf(Zu,Yu)}},G(CW,{gap:22,size:1,color:"rgba(215, 161, 58, 0.24)"}),G(xW,{showInteractive:!1})),!Z?G("button",{type:"button",className:"pipeline-sidecar-tab right",disabled:!c,onClick:()=>H(!0),"data-testid":"pipeline-node-sidebar-toggle"},c?"展开 node 控制":"点击 node 展开控制"):null),Z?G(wS,{activeRun:Tu,pipelineRuns:Wu,selectedRunId:$,onRunChange:(lu)=>{if(A(lu),U(R0()),J(mn()),c)rf(lu,c)},selectedNodeId:c,selectedNodeConfig:Xu,selectedNodeRuntime:uf,control:F,onControlChange:(lu)=>U((Ou)=>({...Ou,...lu})),onFetch:()=>rf(),onAction:R1,onRaw:f,onCollapse:()=>H(!1)}):null),G("div",{className:"pipeline-flow-summary"},G("span",null,`${ll.nodes.length} nodes`),G("span",null,`${ll.edges.length} edges`),G("span",null,`${fu.length} pipelines`),G("span",null,`source config+components(${x.length})`),G("span",null,`run ${Tu?.runId||"--"}`),G("span",null,`score ${E9(Tu)}`),G("span",null,c?`selected ${c}`:"click node to control"))),G(LS,{epochs:Wu,activeRun:Tu,activePipeline:Gu,pipelineNodes:P,pipelineEdges:e,selection:w,detailOpen:E,onDetailOpenChange:D,runDetails:N,nodeDetails:pu,nodeDetailsState:rl,ganttScale:W,onGanttScaleChange:z,onIntervalSelect:C1,onMarkerSelect:kn,onRunChange:(lu)=>{if(A(lu),U(R0()),J(mn()),D(!1),c)rf(lu,c)},onRaw:f}),G(c0,{title:"观测指标",eyebrow:n.refreshedAt?`Updated ${tf(n.refreshedAt)}`:"Snapshot",loading:n.loading},G("div",{className:"metric-grid"},G(Yl,{label:"Health",value:n.health?.ok?"OK":"--",hint:n.health?.service||"D601 /health",tone:n.health?.ok?"ok":"warn"}),G(Yl,{label:"组件",value:Pf,hint:"components registry",tone:b?.registry?.ok===!1?"warn":"ok"}),G(Yl,{label:"Pipeline",value:fu.length,hint:`${P.length} nodes / ${e.length} edges`}),G(Yl,{label:"运行记录",value:Sl,hint:`${_f.succeeded||0} succeeded / ${_f.running||0} running`}),G(Yl,{label:"OA 记录",value:Array.isArray(uu?.submissions)?uu.submissions.length:0,hint:uu?.runId||"latest run"}),G(Yl,{label:"Procedure",value:Array.isArray(uu?.procedureRuns)?uu.procedureRuns.length:0,hint:uu?.status||"no run"}),G(Yl,{label:"Score",value:E9(Tu),hint:Tu?.runId||"selected epoch",tone:p9(Tu)})),G("div",{className:"panel-actions inline-actions"},G(gr,{title:"Pipeline Snapshot",data:b,onOpen:f,testId:"raw-pipeline-snapshot"}))),G(c0,{title:"评分器",eyebrow:Tu?.runId||"selected epoch",loading:n.loading},G(XY,{run:Tu,onRaw:f})),G(c0,{title:"MiniMax 限额",eyebrow:"model/minimax-m27 quota",loading:n.loading},G(WS,{quota:s,onRaw:f})),G(c0,{title:"OA 事件流",eyebrow:"100% event-driven diagnostics",className:"pipeline-wide-panel",loading:n.loading},G(NS,{diagnostics:o,onRaw:f})),G(c0,{title:"组件矩阵",eyebrow:`${Jf.length} classes`,loading:n.loading},Jf.length===0?G(Ur,{title:"暂无组件",text:"等待 D601 pipeline backend 返回 registry.components"}):G("div",{className:"component-strata"},Jf.map((lu)=>G("article",{key:lu.name,className:"component-stratum"},G("span",null,lu.name),G("strong",null,lu.count)))),G("div",{className:"pipeline-component-list"},x.slice(0,12).map((lu)=>G("span",{key:lu.key,className:"data-chip"},G("b",null,lu.componentClass||"--"),G("span",null,lu.id||lu.key||"--"))))),G(c0,{title:"Epoch 列表",eyebrow:`${Wu.length}/${Sl} preview`,loading:n.loading},Wu.length===0?G(Ur,{title:"暂无运行记录",text:"当前 pipeline 在 .state/pipeline-runs 中还没有 epoch。"}):G("div",{className:"pipeline-run-list"},Wu.map((lu)=>{let Ou=String(lu?.runId||"")===Zu?Tu:lu;return G("article",{key:lu.runId,className:`pipeline-run-card ${String(lu.runId||"")===Zu?"active":""}`,role:"button",tabIndex:0,onClick:()=>{A(String(lu.runId||"")),J(mn())},onKeyDown:(Yu)=>{if(Yu.key==="Enter"||Yu.key===" ")A(String(lu.runId||"")),J(mn())}},G("div",{className:"node-card-head"},G("strong",null,Z9(Wu,lu)),G(Cn,{status:lu.status},lu.status||"--")),G("div",{className:"docker-meta compact"},G("span",null,Ou?.pipelineId||"--"),G("span",null,`nodes ${Array.isArray(Ou?.nodes)?Ou.nodes.length:0}`),G("span",null,`oa ${Array.isArray(Ou?.submissions)?Ou.submissions.length:0}`),G("span",null,`procedures ${Array.isArray(Ou?.procedureRuns)?Ou.procedureRuns.length:0}`),G(DY,{run:Ou})),G("p",{className:"muted paragraph"},j8(Ou?.task)),G("span",{className:"pipeline-run-time"},Nu(Ou?.updatedAt)))}))),G(c0,{title:"运行材料索引",eyebrow:Tu?.runId||"selected epoch",className:"pipeline-wide-panel",loading:n.loading},G(qS,{activeRun:Tu,onRaw:f}))))}var z8=Pu(qf(),1);var _u=z8.default.createElement,{useEffect:KS}=z8.default,K8=z8.default.useState,C9={id:"",sequenceNo:"",contractNo:"",name:"",currentStatus:"",pending:"",paymentStatus:"",notes:""};function GS({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return _u("span",{className:`status-badge ${l}`},f||u||"unknown")}function G8({label:u,value:f,hint:l,tone:r}){return _u("article",{className:`metric-card ${r||""}`},_u("div",{className:"metric-label"},u),_u("div",{className:"metric-value"},f),_u("div",{className:"metric-hint"},l))}function R9({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return _u("section",{className:`panel ${n||""}`},_u("div",{className:"panel-head"},_u("div",null,f?_u("p",{className:"panel-eyebrow"},f):null,_u(nf,{title:u,loading:i})),l?_u("div",{className:"panel-actions"},l):null),_u("div",{className:"panel-body"},r))}function YL({title:u,data:f,onOpen:l,testId:r}){return _u("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function SL({title:u,text:f}){return _u("div",{className:"empty-state"},_u("strong",null,u),_u("span",null,f))}function zS(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function TS(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function ES(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function Uy(u,f){return`${u}/microservices/project-manager/proxy${f}`}function ZS(u){return{id:String(u.id||""),sequenceNo:u.sequenceNo===null||u.sequenceNo===void 0?"":String(u.sequenceNo),contractNo:String(u.contractNo||""),name:String(u.name||""),currentStatus:String(u.currentStatus||""),pending:String(u.pending||""),paymentStatus:String(u.paymentStatus||""),notes:String(u.notes||"")}}function OS(u){return{sequenceNo:u.sequenceNo===""?null:Number(u.sequenceNo),contractNo:String(u.contractNo||"").trim(),name:String(u.name||"").trim(),currentStatus:String(u.currentStatus||"").trim(),pending:String(u.pending||"").trim(),paymentStatus:String(u.paymentStatus||"").trim(),paymentRatio:String(u.paymentStatus||"").trim(),notes:String(u.notes||"").trim()}}function x9(u){return String(u||"item").replace(/[^A-Za-z0-9_-]+/g,"-")}function HS(u){let f=new Uint8Array(u),l="",r=32768;for(let n=0;n_u("tr",{key:n.id,className:f===n.id?"active-row":"","data-testid":`project-manager-row-${x9(n.id)}`},_u("td",null,n.sequenceNo??"--"),_u("td",null,_u("strong",null,n.contractNo||"--"),_u("code",null,n.id||"--")),_u("td",null,_u("strong",null,n.name||"--"),_u("span",{className:"muted block"},n.sourceFile||"--")),_u("td",null,n.currentStatus||"--"),_u("td",null,_u("span",{className:"preline"},n.pending||"--")),_u("td",null,_u(GS,{status:Number(n.paymentRatio||0)>=1?"online":"warn"},n.paymentStatus||"--")),_u("td",null,n.notes||"--"),_u("td",null,_u("div",{className:"inline-actions"},_u("button",{type:"button",className:"ghost-btn",onClick:()=>l(n),"data-testid":`project-manager-edit-${x9(n.id)}`},"编辑"),_u(YL,{title:`Project ${n.contractNo||n.id}`,data:n,onOpen:r,testId:`raw-project-${x9(n.id)}`}))))))))}function pL({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((E)=>E.id==="project-manager")||null,[n,i]=K8({loading:!1,saving:!1,importing:!1,exporting:!1,error:"",notice:"",health:null,list:null,refreshedAt:null}),[y,_]=K8({...C9}),[$,A]=K8(""),[c,j]=K8("all"),{addNotification:F}=Vl();async function U(E=$,D=c){if(!r)return;i((h)=>({...h,loading:!0,error:""}));try{let h=new URLSearchParams({pageSize:"200",status:D});if(E.trim())h.set("q",E.trim());let[V,Y]=await Promise.all([Eu(`${l}/microservices/project-manager/health`),Eu(Uy(l,`/api/projects?${h.toString()}`))]);i((p)=>({...p,loading:!1,health:V,list:Y,refreshedAt:new Date,error:""}))}catch(h){i((V)=>({...V,loading:!1,error:Hu(h,"Project Manager 加载失败")}))}}KS(()=>{U()},[r?.id,r?.runtime?.providerStatus]);async function Q(E){E.preventDefault(),i((D)=>({...D,saving:!0,error:"",notice:""}));try{let D=OS(y);if(y.id)await Eu(Uy(l,`/api/projects/${encodeURIComponent(y.id)}`),{method:"PUT",body:JSON.stringify(D)});else await Eu(Uy(l,"/api/projects"),{method:"POST",body:JSON.stringify(D)});let h=y.id?"项目已更新":"项目已创建";i((V)=>({...V,saving:!1,notice:h})),F("success",h),await U()}catch(D){i((h)=>({...h,saving:!1,error:Hu(D,"保存项目失败")}))}}async function L(){if(!y.id)return;if(!window.confirm(`删除项目 ${y.contractNo||y.name||y.id} ?`))return;i((E)=>({...E,saving:!0,error:"",notice:""}));try{await Eu(Uy(l,`/api/projects/${encodeURIComponent(y.id)}`),{method:"DELETE"}),_({...C9});let E="项目已删除";i((D)=>({...D,saving:!1,notice:E})),F("success",E),await U()}catch(E){i((D)=>({...D,saving:!1,error:Hu(E,"删除项目失败")}))}}async function w(E){let D=E.target.files?.[0];if(!D)return;i((h)=>({...h,importing:!0,error:"",notice:""}));try{let h=HS(await D.arrayBuffer()),Y=`Excel 已导入 ${(await Eu(Uy(l,"/api/import/excel"),{method:"POST",body:JSON.stringify({fileName:D.name,contentBase64:h,replace:!1})})).imported||0} 条项目`;i((p)=>({...p,importing:!1,notice:Y})),F("success",Y),E.target.value="",await U()}catch(h){i((V)=>({...V,importing:!1,error:Hu(h,"Excel 导入失败")}))}}async function J(){i((E)=>({...E,exporting:!0,error:""}));try{let E=await fU(Uy(l,"/api/projects/export.xlsx")),D=URL.createObjectURL(E),h=document.createElement("a");h.href=D,h.download=`project-manager-${X7()}.xlsx`,document.body.appendChild(h),h.click(),h.remove(),URL.revokeObjectURL(D),i((V)=>({...V,exporting:!1,notice:"Excel 已导出"}))}catch(E){i((D)=>({...D,exporting:!1,error:Hu(E,"Excel 导出失败")}))}}if(!r)return _u(SL,{title:"Project Manager 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=project-manager"});let N=zS(r),q=ES(r),W=TS(r),z=Array.isArray(n.list?.projects)?n.list.projects:[],Z=n.list?.summary||{},H=n.health||{};return _u("div",{className:"project-manager-page","data-testid":"project-manager-page"},_u(R9,{title:"项目管理工作台",eyebrow:"Main Server PostgreSQL 用户服务",loading:n.loading||n.exporting,actions:_u("div",{className:"panel-actions"},_u("button",{type:"button",className:"ghost-btn",disabled:n.loading,onClick:()=>U(),"data-testid":"project-manager-refresh-button"},n.loading?"刷新中":"刷新"),_u("button",{type:"button",className:"ghost-btn",disabled:n.exporting,onClick:J,"data-testid":"project-manager-export-button"},n.exporting?"导出中":"导出 Excel"),_u(YL,{title:"Project Manager 用户服务",data:r,onOpen:f,testId:"raw-project-manager-service"}))},_u("div",{className:"project-manager-hero"},_u(G8,{label:"项目总数",value:Z.total??z.length,hint:`PG 表 ${H.storage?.table||"project_manager_projects"}`,tone:"ok"}),_u(G8,{label:"进行中",value:Z.active??"--",hint:"当前状态未完全完成"}),_u(G8,{label:"已完成",value:Z.completed??"--",hint:"按 完成 关键字统计",tone:"ok"}),_u(G8,{label:"未全款",value:Z.unpaid??"--",hint:"付款比例 < 1",tone:Number(Z.unpaid||0)>0?"warn":"ok"})),_u(yf,{error:n.error}),n.notice?_u("div",{className:"form-success"},n.notice):null),_u("div",{className:"project-manager-hero"},_u("div",{className:"microservice-ref-card"},_u("span",null,"Repo"),_u("strong",null,q.url||"--"),_u("code",null,q.commitId||"--")),_u("div",{className:"microservice-ref-card"},_u("span",null,"Main Server Docker"),_u("strong",null,`${W.nodeBindHost||"--"}:${W.nodePort||"--"}`),_u("code",null,`${q.composeService||"--"} / ${q.containerName||"--"}`)),_u("div",{className:"microservice-ref-card"},_u("span",null,"Runtime"),_u("strong",null,N.providerName||r.providerId),_u("code",null,`Health ${H.ok?"OK":"--"} / ${n.refreshedAt?tf(n.refreshedAt):"--"}`)),_u("div",{className:"microservice-ref-card"},_u("span",null,"Import Source"),_u("strong",null,"D601 WeChat Excel"),_u("code",null,"合作项目列表_I_20260309.xlsx"))),_u("div",{className:"project-manager-layout"},_u(R9,{title:"项目清单",eyebrow:"CRUD + Excel Export",loading:n.loading||n.importing||n.exporting,actions:_u("div",{className:"inline-actions project-manager-filters"},_u("input",{value:$,onChange:(E)=>A(E.target.value),placeholder:"搜索合同号 / 项目名称 / 状态","data-testid":"project-manager-search"}),_u("select",{value:c,onChange:(E)=>{j(E.target.value),U($,E.target.value)},"data-testid":"project-manager-status-filter"},_u("option",{value:"all"},"全部"),_u("option",{value:"active"},"进行中"),_u("option",{value:"completed"},"已完成"),_u("option",{value:"unpaid"},"未全款")),_u("button",{type:"button",className:"ghost-btn",onClick:()=>U($,c)},"筛选"))},_u(BS,{projects:z,activeId:y.id,onSelect:(E)=>_(ZS(E)),onRaw:f})),_u(R9,{title:y.id?"编辑项目":"新建项目",eyebrow:"PostgreSQL Write Path",loading:n.saving||n.importing},_u("form",{className:"stack-form project-manager-form",onSubmit:Q,"data-testid":"project-manager-form"},y.id?_u("label",null,"项目 ID",_u("input",{value:y.id,disabled:!0})):null,_u("label",null,"序号",_u("input",{type:"number",value:y.sequenceNo,onChange:(E)=>_((D)=>({...D,sequenceNo:E.target.value}))})),_u("label",null,"合同号",_u("input",{value:y.contractNo,onChange:(E)=>_((D)=>({...D,contractNo:E.target.value})),required:!0})),_u("label",null,"项目名称",_u("input",{value:y.name,onChange:(E)=>_((D)=>({...D,name:E.target.value})),required:!0})),_u("label",null,"当前状况",_u("textarea",{value:y.currentStatus,onChange:(E)=>_((D)=>({...D,currentStatus:E.target.value}))})),_u("label",null,"待完成",_u("textarea",{value:y.pending,onChange:(E)=>_((D)=>({...D,pending:E.target.value}))})),_u("label",null,"付款情况",_u("input",{value:y.paymentStatus,onChange:(E)=>_((D)=>({...D,paymentStatus:E.target.value})),placeholder:"例如 1 / 0.5 / 50%"})),_u("label",null,"其它",_u("input",{value:y.notes,onChange:(E)=>_((D)=>({...D,notes:E.target.value}))})),_u("div",{className:"inline-actions"},_u("button",{type:"submit",className:"primary-btn",disabled:n.saving,"data-testid":"project-manager-save-button"},n.saving?"保存中":y.id?"保存修改":"创建项目"),_u("button",{type:"button",className:"ghost-btn",onClick:()=>_({...C9})},"清空"),y.id?_u("button",{type:"button",className:"danger-btn",disabled:n.saving,onClick:L,"data-testid":"project-manager-delete-button"},"删除"):null)),_u("div",{className:"project-manager-import"},_u("p",{className:"muted paragraph"},"浏览器只访问 UniDesk frontend;后端通过同源用户服务代理写入主 PostgreSQL,不暴露 4233 公网端口。"),_u("label",{className:"file-import"},n.importing?"导入中...":"导入 Excel",_u("input",{type:"file",accept:".xlsx",onChange:w,disabled:n.importing,"data-testid":"project-manager-import-input"}))))))}var Z8=Pu(qf(),1);var Au=Z8.default.createElement,{useEffect:VS}=Z8.default,al=Z8.default.useState;function DS({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return Au("span",{className:`status-badge ${l}`},f||u||"unknown")}function T8({label:u,value:f,hint:l,tone:r}){return Au("article",{className:`metric-card ${r||""}`},Au("div",{className:"metric-label"},u),Au("div",{className:"metric-value"},f),Au("div",{className:"metric-hint"},l))}function h9({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){return Au("section",{className:`panel ${n||""}`},Au("div",{className:"panel-head"},Au("div",null,f?Au("p",{className:"panel-eyebrow"},f):null,Au(nf,{title:u,loading:i})),l?Au("div",{className:"panel-actions"},l):null),Au("div",{className:"panel-body"},r))}function mL({title:u,data:f,onOpen:l,testId:r}){return Au("button",{type:"button",className:"ghost-btn","data-testid":r,onClick:()=>l(u,f)},"查看原始JSON")}function E8({title:u,text:f}){return Au("div",{className:"empty-state"},Au("strong",null,u),Au("span",null,f))}function XS(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function YS(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function SS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function ML(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function pS(u){if(!Number.isFinite(u))return"--";return`${u.toFixed(1)}%`}function Qy(u,f){return`${u}/microservices/todo-note/proxy${f}`}function CL(u){return u.reduce((f,l)=>{let r=CL(Array.isArray(l.children)?l.children:[]),n=Boolean(l.completed);return{total:f.total+1+r.total,completed:f.completed+(n?1:0)+r.completed,active:f.active+(n?0:1)+r.active}},{total:0,completed:0,active:0})}function v9(u,f){let l=f==="all"||(f==="completed"?Boolean(u.completed):!u.completed),r=Array.isArray(u.children)?u.children:[];return l||r.some((n)=>v9(n,f))}function PL(u){return Array.isArray(u?.instances)?u.instances:[]}function b9(u,f){for(let l of u){if(l?.id===f)return Array.isArray(l.children)?l.children:[];let r=b9(Array.isArray(l?.children)?l.children:[],f);if(r.length>0)return r}return[]}function RL({microservices:u,onRaw:f,apiBaseUrl:l="/api"}){let r=u.find((g)=>g.id==="todo-note")||null,[n,i]=al(null),[y,_]=al(null),[$,A]=al(""),[c,j]=al(null),[F,U]=al("all"),[Q,L]=al(13),[w,J]=al(""),[N,q]=al(""),[W,z]=al(""),[Z,H]=al(""),[E,D]=al(""),[h,V]=al(!1),[Y,p]=al(""),[O,m]=al(null),X=PL(y),v=CL(Array.isArray(c?.todos)?c.todos:[]),T=r?XS(r):{},S=r?SS(r):{},k=r?YS(r):{};async function I(g=$){let[Qu,Tu]=await Promise.all([Eu(`${l}/microservices/todo-note/health`),Eu(Qy(l,"/api/instances"))]);i(Qu),_(Tu);let Zu=PL(Tu),Xu=Zu.some((uf)=>uf.id===g)?g:Zu[0]?.id||"";return A(Xu),Xu}async function b(g=$){if(!g){j(null);return}let Qu=await Eu(Qy(l,`/api/instances/${encodeURIComponent(g)}`));j(Qu)}async function o(g=$){if(!r)return;V(!0),p("");try{let Qu=await I(g);await b(Qu),m(new Date)}catch(Qu){p(Hu(Qu,"Todo Note 加载失败"))}finally{V(!1)}}async function s(g){if(!$)return null;p("");try{let Qu=await Eu(Qy(l,`/api/instances/${encodeURIComponent($)}/actions`),{method:"POST",body:JSON.stringify({action:g})});return j(Qu),await I($),Qu}catch(Qu){return p(Hu(Qu,"Todo 操作失败")),null}}async function x(g){g.preventDefault();let Qu=w.trim();if(!Qu)return;V(!0),p("");try{let Tu=await Eu(Qy(l,"/api/instances"),{method:"POST",body:JSON.stringify({name:Qu})});J(""),await o(Tu.id)}catch(Tu){p(Hu(Tu,"创建清单失败"))}finally{V(!1)}}async function fu(g){if(!window.confirm("确认删除这个 Todo Note 清单?"))return;V(!0),p("");try{await Eu(Qy(l,`/api/instances/${encodeURIComponent(g)}`),{method:"DELETE"}),await o($===g?"":$)}catch(Qu){p(Hu(Qu,"删除清单失败"))}finally{V(!1)}}async function $u(g){g.preventDefault();let Qu=N.trim();if(!Qu)return;q(""),await s({type:"addTodo",title:Qu})}async function tu(g){if(!$)return;p("");try{let Qu=await Eu(Qy(l,`/api/instances/${encodeURIComponent($)}/${g}`),{method:"POST",body:JSON.stringify({})});j(Qu),await I($)}catch(Qu){p(Hu(Qu,`${g} 失败`))}}function ju(g){z(g.id),H(String(g.title||""))}async function Gu(g){let Qu=Z.trim();if(z(""),H(""),Qu)await s({type:"updateTodoTitle",todoId:g,title:Qu})}async function qu(g){let Tu=window.prompt("新增子任务标题")?.trim();if(!Tu)return;let Zu=b9(Array.isArray(c?.todos)?c.todos:[],g),Xu=new Set(Zu.map((Pf)=>Pf.id)),uf=await s({type:"addTodo",title:Tu,parentId:g,targetIndex:0});if(!uf)return;let _f=b9(Array.isArray(uf?.todos)?uf.todos:[],g),Jf=_f.find((Pf)=>!Xu.has(Pf.id));if(Jf&&_f[0]?.id!==Jf.id)await s({type:"moveTodo",todoId:Jf.id,targetParentId:g,targetIndex:0})}async function P(g,Qu){if(!E)return;let Tu={type:"moveTodo",todoId:E,targetIndex:Qu};if(g)Tu.targetParentId=g;D(""),await s(Tu)}if(VS(()=>{o()},[r?.id,r?.runtime?.providerStatus]),!r)return Au(E8,{title:"Todo Note 未登记",text:"请在 config.json 的 microservices 中登记用户服务 id=todo-note"});let e=X.find((g)=>g.id===$)||null,uu=Array.isArray(c?.todos)?c.todos:[],Wu=uu.map((g,Qu)=>({todo:g,index:Qu})).filter((g)=>v9(g.todo,F));return Au("div",{className:"todo-note-page","data-testid":"todo-note-page"},Au(h9,{title:"Todo Note 工作台",eyebrow:"Main Server 用户服务",loading:h,actions:Au("div",{className:"panel-actions"},Au("button",{type:"button",className:"ghost-btn",disabled:h,onClick:()=>o($),"data-testid":"todo-note-refresh-button"},h?"刷新中":"刷新"),Au(mL,{title:"Todo Note 用户服务",data:r,onOpen:f,testId:"raw-todo-note-service"}))},Au("div",{className:"todo-note-hero"},Au("div",null,Au("div",{className:"node-version-line"},Au(DS,{status:T.providerStatus==="online"?"online":"warn"},T.providerStatus||"unknown"),Au("span",null,r.providerId),Au("span",null,k.public?"公网暴露":"仅 UniDesk frontend 代理访问"),Au("span",null,n?.ok?"Health OK":"Health --")),Au("p",{className:"muted paragraph"},r.description)),Au("div",{className:"microservice-ref-card"},Au("span",null,"Repo"),Au("strong",null,S.url||"--"),Au("code",null,S.commitId||"--")),Au("div",{className:"microservice-ref-card"},Au("span",null,"Main Server Docker"),Au("strong",null,`${k.nodeBindHost||"--"}:${k.nodePort||"--"}`),Au("code",null,`${S.composeService||"--"} / ${S.containerName||"--"}`))),Au(yf,{error:Y,wide:!0})),Au("div",{className:"todo-note-layout"},Au(h9,{title:"清单",eyebrow:`${X.length} Instances`,className:"todo-list-panel",loading:h},Au("form",{className:"todo-create-list",onSubmit:x},Au("input",{placeholder:"新清单名称",value:w,onChange:(g)=>J(g.target.value),"aria-label":"新清单名称"}),Au("button",{type:"submit",className:"ghost-btn",disabled:h||!w.trim()},"创建")),X.length===0?Au(E8,{title:"暂无清单",text:"迁移或创建清单后会出现在这里"}):Au("div",{className:"todo-instance-list"},X.map((g)=>Au("button",{key:g.id,type:"button",className:`todo-instance-row ${$===g.id?"active":""}`,onClick:()=>{A(g.id),b(g.id)},"data-testid":`todo-instance-${ML(g.id)}`},Au("strong",null,g.name),Au("span",null,`${g.completedCount??0}/${g.todoCount??0} 完成`),Au("code",null,g.id))))),Au("div",{className:"todo-main-stack"},Au(h9,{title:e?.name||"待选择清单",eyebrow:O?`Updated ${tf(O)}`:"Todo Tree",loading:h,actions:c?Au("div",{className:"panel-actions"},Au("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"renameInstance",name:window.prompt("清单新名称",c.name)||c.name})},"重命名"),Au("button",{type:"button",className:"ghost-btn danger",onClick:()=>fu($)},"删除清单"),Au(mL,{title:`Todo Instance ${$}`,data:c,onOpen:f,testId:"raw-todo-instance"})):null},!c?Au(E8,{title:"未选择清单",text:"左侧选择一个 Todo Note 清单"}):Au("div",{className:"todo-workbench",style:{"--todo-font-size":`${Q}px`}},Au("div",{className:"todo-toolbar"},Au("form",{className:"todo-add-form",onSubmit:$u},Au("input",{placeholder:"新增根任务",value:N,onChange:(g)=>q(g.target.value),"aria-label":"新增根任务"}),Au("button",{type:"submit",className:"ghost-btn",disabled:!N.trim()},"新增")),Au("div",{className:"todo-filter-strip"},["all","active","completed"].map((g)=>Au("button",{key:g,type:"button",className:`todo-filter ${F===g?"active":""}`,onClick:()=>U(g)},g==="all"?"全部":g==="active"?"未完成":"已完成"))),Au("div",{className:"todo-toolbar-actions"},Au("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"setAllTodosExpanded",expanded:!0})},"全部展开"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>s({type:"setAllTodosExpanded",expanded:!1})},"全部收起"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>tu("undo")},"撤销"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>tu("redo")},"重做"),Au("label",{className:"todo-font-control"},"字号",Au("input",{type:"range",min:11,max:18,value:Q,onChange:(g)=>L(Number(g.target.value))})))),Au("div",{className:"todo-stats-grid"},Au(T8,{label:"总任务",value:v.total,hint:`${X.length} lists`}),Au(T8,{label:"已完成",value:v.completed,hint:`${pS(v.total?v.completed/v.total*100:0)}`,tone:"ok"}),Au(T8,{label:"未完成",value:v.active,hint:F==="active"?"当前筛选":"active tasks",tone:v.active>0?"warn":"ok"}),Au(T8,{label:"历史指针",value:c.historyPointer??0,hint:"undo / redo"})),Au("div",{className:"todo-root-drop",onDragOver:(g)=>g.preventDefault(),onDrop:(g)=>{g.preventDefault(),P(null,uu.length)}},"拖到这里可移为根任务末尾"),Au("div",{className:"todo-tree","data-testid":"todo-note-tree"},Wu.length===0?Au(E8,{title:"没有匹配任务",text:"调整筛选或新增任务"}):Wu.map(({todo:g,index:Qu})=>Au(xL,{key:g.id,todo:g,depth:0,parentId:null,index:Qu,siblingCount:uu.length,filter:F,editingId:W,editingTitle:Z,setEditingTitle:H,beginEdit:ju,saveEdit:Gu,applyTodoAction:s,addChild:qu,dragTodoId:E,setDragTodoId:D,dropTodo:P}))))))))}function xL(u){let{todo:f,depth:l,parentId:r,index:n,siblingCount:i,filter:y,editingId:_,editingTitle:$,setEditingTitle:A,beginEdit:c,saveEdit:j,applyTodoAction:F,addChild:U,dragTodoId:Q,setDragTodoId:L,dropTodo:w}=u,J=Array.isArray(f.children)?f.children:[],N=J.map((z,Z)=>({child:z,childIndex:Z})).filter((z)=>v9(z.child,y)),q=_===f.id,W=r||null;return Au("div",{className:"todo-row-wrap"},Au("article",{className:`todo-row ${f.completed?"completed":""} ${Q===f.id?"dragging":""}`,style:{"--todo-depth":l},draggable:!0,onDragStart:(z)=>{L(f.id),z.dataTransfer.effectAllowed="move"},onDragOver:(z)=>z.preventDefault(),onDrop:(z)=>{z.preventDefault(),w(f.id,J.length)},"data-testid":`todo-row-${ML(f.id)}`},Au("button",{type:"button",className:"todo-expand",disabled:J.length===0,onClick:()=>F({type:"toggleTodoExpanded",todoId:f.id})},J.length===0?"·":f.expanded?"▾":"▸"),Au("input",{type:"checkbox",checked:Boolean(f.completed),onChange:()=>F({type:"toggleTodoCompleted",todoId:f.id}),"aria-label":`完成 ${f.title}`}),Au("div",{className:"todo-title-cell",onDoubleClick:()=>c(f)},q?Au("div",{className:"todo-edit-inline"},Au("input",{value:$,autoFocus:!0,onChange:(z)=>A(z.target.value),onKeyDown:(z)=>{if(z.key==="Enter")j(f.id);if(z.key==="Escape")c({id:"",title:""})}}),Au("button",{type:"button",className:"ghost-btn",onClick:()=>j(f.id)},"保存")):Au("strong",null,f.title||"Untitled"),Au("div",{className:"todo-meta-line"},Au("span",null,`子项 ${J.length}`),Au("span",null,`更新 ${Nu(f.updatedAt)}`),f.reminderAt?Au("span",{className:"todo-reminder"},`提醒 ${Nu(f.reminderAt)}`):Au("span",null,"无提醒"))),Au("input",{className:"todo-reminder-input",type:"datetime-local",value:a8(f.reminderAt),onChange:(z)=>F({type:"setTodoReminder",todoId:f.id,reminderAt:Y7(z.target.value)})}),Au("div",{className:"todo-row-actions"},Au("button",{type:"button",className:"ghost-btn",onClick:()=>c(f)},"编辑"),Au("button",{type:"button",className:"ghost-btn",onClick:()=>U(f.id)},"子项"),Au("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:n-1})},"上移"),Au("button",{type:"button",className:"ghost-btn",disabled:n<=0,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:0})},"置顶"),Au("button",{type:"button",className:"ghost-btn",disabled:n>=i-1,onClick:()=>F({type:"moveTodo",todoId:f.id,...W?{targetParentId:W}:{},targetIndex:n+1})},"下移"),Au("button",{type:"button",className:"ghost-btn",disabled:!r,onClick:()=>F({type:"moveTodo",todoId:f.id,targetIndex:9999})},"提升"),Au("button",{type:"button",className:"ghost-btn danger",onClick:()=>F({type:"deleteTodo",todoId:f.id})},"删除"))),f.expanded&&N.length>0?Au("div",{className:"todo-children"},N.map(({child:z,childIndex:Z})=>Au(xL,{key:z.id,todo:z,depth:l+1,parentId:f.id,index:Z,siblingCount:J.length,filter:y,editingId:_,editingTitle:$,setEditingTitle:A,beginEdit:c,saveEdit:j,applyTodoAction:F,addChild:U,dragTodoId:Q,setDragTodoId:L,dropTodo:w}))):null)}var hL=Pu(qf(),1),xn=hL.default.createElement;function bL({title:u,items:f,actions:l,className:r,testId:n}){let i=Array.isArray(f)?f:[];return xn("section",{className:`top-status-bar ${r||""}`,"data-testid":n},xn("div",{className:"top-status-main"},u?xn("strong",{className:"top-status-title"},u):null,xn("div",{className:"top-status-chips"},i.map((y,_)=>xn("span",{key:y?.key||`${y?.label||"status"}-${_}`,className:`top-status-chip ${y?.tone||""}`,"data-testid":y?.testId},y?.label?xn("b",null,y.label):null,xn("span",null,y?.value??"--"))))),l?xn("div",{className:"top-status-actions"},l):null)}var S$=Pu(qf(),1);var hf=S$.default.createElement;function vL({onClose:u}){let{notifications:f,removeNotification:l,clearNotifications:r}=Vl(),n=S$.default.useRef(null);if(S$.default.useEffect(()=>{let i=(y)=>{if(n.current&&!n.current.contains(y.target))u()};return document.addEventListener("mousedown",i),()=>document.removeEventListener("mousedown",i)},[u]),f.length===0)return hf("div",{className:"notification-popup",ref:n},hf("div",{className:"notification-popup-header"},hf("span",null,"通知"),hf("button",{className:"notification-popup-close",onClick:u},"×")),hf("div",{className:"notification-popup-empty"},"暂无通知"));return hf("div",{className:"notification-popup",ref:n},hf("div",{className:"notification-popup-header"},hf("span",null,`通知 (${f.length})`),hf("div",{className:"notification-popup-actions"},hf("button",{className:"notification-popup-clear",onClick:r},"清空"),hf("button",{className:"notification-popup-close",onClick:u},"×"))),hf("div",{className:"notification-popup-list"},f.slice().reverse().map((i)=>hf("div",{key:i.id,className:`notification-item ${i.type}`},hf("span",{className:"notification-item-icon"},i.type==="success"?"✓":"×"),hf("span",{className:"notification-item-message"},i.message),hf("button",{className:"notification-item-dismiss",onClick:()=>l(i.id)},"×")))))}function kL({notification:u}){let{removeNotification:f}=Vl();return S$.default.useEffect(()=>{let l=setTimeout(()=>{f(u.id)},3000);return()=>clearTimeout(l)},[u.id,f]),hf("div",{className:`notification-banner ${u.type}`,role:"alert"},hf("span",{className:"notification-banner-icon"},u.type==="success"?"✓":"×"),hf("span",{className:"notification-banner-message"},u.message),hf("button",{className:"notification-banner-dismiss",onClick:()=>f(u.id)},"×"))}function nw(u,f){let l=document.getElementById("root")?.getAttribute(u);if(!l)return f;try{let r=JSON.parse(l);return typeof r==="object"&&r!==null&&!Array.isArray(r)?r:f}catch{return f}}var gu=nw("data-config",{apiBaseUrl:"/api",authUsername:"admin"}),mS=nw("data-codex-overview",null),t=bn.default.createElement,{useEffect:F0,useMemo:P$}=bn.default,hu=bn.default.useState,s9=bn.default.createContext(!1),Vr=xQ(u6),PS={id:"code-queue",name:"Code Queue",providerId:"main-server",description:"Code Queue",repository:{containerName:"code-queue-backend"},backend:{nodeBaseUrl:"http://code-queue:4222",nodeBindHost:"code-queue",nodePort:4222,public:!1},runtime:{providerStatus:"loading",providerName:"main-server"}};function IL(){return typeof document>"u"||document.visibilityState!=="hidden"}function MS(u,f){if(u==="ops"&&f==="status")return 5000;if(u==="nodes"&&f==="monitor")return 5000;if(u==="tasks"&&(f==="dispatch"||f==="scheduled"||f==="pending"))return 5000;if(u==="nodes"||u==="ops")return 1e4;if(u==="apps")return 15000;if(u==="tasks")return 15000;return 30000}async function CS(u){if(!u?._summaryOnly||!u?.id)return u;return(await Eu(`${gu.apiBaseUrl}/tasks/${encodeURIComponent(String(u.id))}`))?.task||u}function M$(u){return u?._summaryOnly?{...u,_loadRaw:()=>CS(u)}:u}function x0(u){if(!Number.isFinite(u))return"--";let f=Math.max(0,u);if(f===0)return"0s";if(f<0.01)return"<0.01s";if(f<0.1)return`${f.toFixed(2)}s`;if(f<1)return`${f.toFixed(1)}s`;if(f<10&&!Number.isInteger(f))return`${f.toFixed(1)}s`;if(f<60)return`${Math.round(f)}s`;let l=Math.floor(f);if(l<3600)return`${Math.floor(l/60)}m ${l%60}s`;return`${Math.floor(l/3600)}h ${Math.floor(l%3600/60)}m`}function Qr(u){let f=Number(u);if(!Number.isFinite(f))return"--";if(f<1)return`${Math.max(0,f).toFixed(1)}ms`;if(f<10)return`${f.toFixed(1)}ms`;if(f<1000)return`${Math.round(f)}ms`;return x0(f/1000)}function zl(u){let f=Number(u);if(!Number.isFinite(f)||f<=0)return"--";let l=["B","KB","MB","GB","TB"],r=f,n=0;while(r>=1024&&n0)return l[r]}return"任务失败但 provider 未返回明确原因"}function M1(u){if(u===null||u===void 0)return"--";if(typeof u==="boolean")return u?"是":"否";if(typeof u==="number")return String(u);if(typeof u==="string")return u.length>80?`${u.slice(0,77)}...`:u;if(Array.isArray(u))return`${u.length} 项`;if(typeof u==="object")return`${Object.keys(u).length} 字段`;return String(u)}function xS(u,f){let l=u.replace(/[-_\s]/g,"").toLowerCase(),r=l==="ts"||l.endsWith("at")||l.endsWith("timestamp")||l.endsWith("heartbeat");if((typeof f==="string"||typeof f==="number")&&r){let n=Nu(f);if(n!=="--")return n}if(u==="bodyText"&&typeof f==="string")return`${/^\s*[{[]/.test(f)?"JSON":"HTTP"} body ${f.length} chars`;return M1(f)}function _w(u){if(!u||typeof u!=="object"||Array.isArray(u))return[];return Object.entries(u)}function ol(u){return String(u).replace(/[^a-zA-Z0-9_-]/g,"_")}function o9(u,f){return u&&typeof u==="object"&&!Array.isArray(u)?u[f]:void 0}function H8(u,f,l="未知"){let r=o9(u?.labels,f);return typeof r==="string"&&r.length>0?r:l}function $w(u){return H8(u,"providerGatewayVersion")}function m$(u){return H8(u,"providerGatewayUpgradePolicy")}function gL(u){return H8(u,"providerGatewayStartedAt","")}function tw(u){let f=o9(u?.labels,"unideskCapabilities");if(typeof f==="string")return f.split(",").map((l)=>l.trim()).filter(Boolean);return Array.isArray(f)?f.filter((l)=>typeof l==="string"):[]}function Aw(u,f){return tw(u).includes(f)}function sL(u,f){let l=o9(u?.labels,f);return l===!0||l==="true"||l==="1"}function hS(u){if(!Aw(u,"host.ssh"))return{tone:"fail",label:"不可用",detail:"未声明 host.ssh"};if(!sL(u,"hostSshConfigured"))return{tone:"warn",label:"未配置",detail:"缺少 SSH 环境变量"};if(!sL(u,"hostSshKeyPresent"))return{tone:"warn",label:"缺 key",detail:"私钥未挂载"};return{tone:"ok",label:"可用",detail:H8(u,"hostSshTarget","host.ssh ready")}}function bS(u){if(!Aw(u,"provider.upgrade"))return{tone:"fail",label:"不可用",detail:"未声明 provider.upgrade"};let f=m$(u);if(f!=="always-enabled")return{tone:"warn",label:"待确认",detail:`策略 ${f}`};return{tone:"ok",label:"可用",detail:"always-enabled"}}function d9(u){let f=typeof u==="string"&&u.length>0?u:"未知";if(f==="未知")return"版本未知";return f.startsWith("v")?f:`v${f}`}function cw(u){return u?.payload&&typeof u.payload==="object"&&!Array.isArray(u.payload)?u.payload:{}}function B8(u){return u?.result&&typeof u.result==="object"&&!Array.isArray(u.result)?u.result:{}}function O8(u){let f=cw(u),l=B8(u);return(f.mode??l.mode)==="schedule"?"schedule":"plan"}function vS(u){let f=cw(u).source;return typeof f==="string"&&f.length>0?f:"unknown"}function kS(u){let f=B8(u),l=f.plan&&typeof f.plan==="object"&&!Array.isArray(f.plan)?f.plan:{},r=f.policy??l.policy;return typeof r==="string"&&r.length>0?r:"--"}function jw(u){let f=B8(u),l=f.plan&&typeof f.plan==="object"&&!Array.isArray(f.plan)?f.plan:{},r=f.targetProviderGatewayVersion??f.providerGatewayVersion??l.targetProviderGatewayVersion??l.providerGatewayVersion;return typeof r==="string"&&r.length>0?d9(r):"版本未知"}function Fw(u){if(String(u?.status||"").toLowerCase()==="failed")return yw(u);if(Ny(u))return"等待 provider 回传升级终态";let l=B8(u);if(typeof l.updaterContainerId==="string"&&l.updaterContainerId.length>0)return`updater ${l.updaterContainerId.slice(0,18)}`;if(typeof l.message==="string"&&l.message.length>0)return l.message;if(l.plan)return"升级计划已生成";return"无升级结果摘要"}function Jw(u,f){return u.filter((l)=>l?.providerId===f&&l?.command==="provider.upgrade").sort((l,r)=>(J0(r.updatedAt)??0)-(J0(l.updatedAt)??0))}function IS(u){return u.find((f)=>O8(f)==="schedule")||u[0]||null}function Uw(u){return u?.runtime&&typeof u.runtime==="object"&&!Array.isArray(u.runtime)?u.runtime:{}}function aL(u){return u?.backend&&typeof u.backend==="object"&&!Array.isArray(u.backend)?u.backend:{}}function gS(u){return u?.repository&&typeof u.repository==="object"&&!Array.isArray(u.repository)?u.repository:{}}function wf({status:u,children:f}){let l=String(u||"unknown").toLowerCase();return t("span",{className:`status-badge ${l}`},f||u||"unknown")}function cf({label:u,value:f,hint:l,tone:r,onClick:n,testId:i}){let y=typeof n==="function";return t("article",{className:`metric-card ${r||""} ${y?"clickable":""}`,role:y?"button":void 0,tabIndex:y?0:void 0,"data-testid":i,onClick:n,onKeyDown:y?(_)=>{if(_.key==="Enter"||_.key===" ")_.preventDefault(),n()}:void 0},t("div",{className:"metric-label"},u),t("div",{className:"metric-value"},f),t("div",{className:"metric-hint"},l))}function au({title:u,eyebrow:f,actions:l,children:r,className:n,loading:i}){let y=bn.default.useContext(s9),_=Boolean(i)||y;return t("section",{className:`panel ${n||""}`},t("div",{className:"panel-head"},t("div",null,f?t("p",{className:"panel-eyebrow"},f):null,t(nf,{title:u,loading:_})),l?t("div",{className:"panel-actions"},l):null),t("div",{className:"panel-body"},r))}function bf({title:u,data:f,onOpen:l,testId:r}){let[n,i]=hu(!1),y=f&&typeof f==="object"&&typeof f._loadRaw==="function"?f._loadRaw:null;async function _(){if(!y){l(u,f);return}i(!0);try{l(u,await y())}catch($){l(u,{ok:!1,error:Hu($,"读取原始 JSON 失败"),fallback:f})}finally{i(!1)}}return t("button",{type:"button",className:"ghost-btn","data-testid":r,disabled:n,onClick:()=>void _()},n?"读取中":"查看原始JSON")}function sS({raw:u,onClose:f}){if(!u)return null;return t("div",{className:"modal-backdrop",role:"presentation"},t("section",{className:"raw-dialog",role:"dialog","aria-modal":"true","aria-label":u.title},t("div",{className:"raw-dialog-head"},t("h2",null,u.title),t("button",{type:"button",className:"ghost-btn",onClick:f},"关闭")),t("pre",{className:"raw-json","data-testid":"raw-json"},JSON.stringify(u.data,null,2))))}function Qw({labels:u,limit:f=8}){let l=_w(u).slice(0,f);if(l.length===0)return t("span",{className:"muted"},"无标签");return t("div",{className:"chip-row"},l.map(([r,n])=>t("span",{key:r,className:"data-chip"},t("b",null,r),t("span",null,M1(n)))))}function qy({node:u}){let f=$w(u);return t("span",{className:`version-chip ${f==="未知"?"unknown":""}`,"data-testid":`gateway-version-${ol(u?.providerId||"unknown")}`},d9(f))}function oL({title:u,state:f,testId:l}){return t("span",{className:`capability-badge ${f.tone}`,title:f.detail,"data-testid":l},t("b",null,u),t("strong",null,f.label),t("small",null,f.detail))}function e9({node:u}){let f=ol(u?.providerId||"unknown");return t("div",{className:"node-availability-strip"},t(oL,{title:"SSH 透传",state:hS(u),testId:`ssh-availability-${f}`}),t(oL,{title:"远程更新",state:bS(u),testId:`upgrade-availability-${f}`}))}function vn({data:u,empty:f="无数据"}){if(u===null||u===void 0)return t("span",{className:"muted"},f);if(typeof u!=="object")return t("span",{className:"summary-value"},M1(u));if(Array.isArray(u))return t("span",{className:"summary-value"},`${u.length} 项列表`);let l=Object.entries(u).slice(0,5);if(l.length===0)return t("span",{className:"muted"},f);return t("div",{className:"summary-grid"},l.map(([r,n])=>t("span",{key:r,className:"summary-item"},t("b",null,r),t("span",null,xS(r,n)))))}function Ff({title:u,text:f}){return t("div",{className:"empty-state"},t("strong",null,u),t("span",null,f))}function aS({onLogin:u}){let[f,l]=hu(gu.authUsername||"admin"),[r,n]=hu(""),[i,y]=hu(""),[_,$]=hu(!1);async function A(c){c.preventDefault(),$(!0),y("");try{let j=await Eu("/login",{method:"POST",body:JSON.stringify({username:f,password:r})});u(j)}catch(j){y(Hu(j,"登录失败"))}finally{$(!1)}}return t("main",{className:"login-screen","data-testid":"login-screen"},t("section",{className:"login-card"},t("div",{className:"login-brand"},t("span",{className:"brand-mark"},"UD"),t("div",null,t("h1",null,"UniDesk"),t("p",null,"Control Plane Login"))),t("form",{className:"login-form",onSubmit:A},t("label",null,"账号",t("input",{name:"username",autoComplete:"username",value:f,onChange:(c)=>l(c.target.value)})),t("label",null,"密码",t("input",{name:"password",type:"password",autoComplete:"current-password",value:r,onChange:(c)=>n(c.target.value)})),t(yf,{error:i}),t("button",{type:"submit",disabled:_},_?"登录中":"登录")),t("div",{className:"login-note"},"默认账号由 config.json 注入;公网入口只暴露前端登录面。")))}function oS({connection:u,lastRefresh:f,onRefresh:l,onLogout:r,session:n,clock:i,activeStatusItems:y=[],onNotificationToggle:_,unreadCount:$=0}){let A=[{key:"core",label:"核心",value:u.text,tone:u.ok?"ok":"fail",testId:"conn-text"},...Array.isArray(y)?y:[],{key:"refresh",label:"刷新",value:f?tf(f):"未刷新"},{key:"clock",label:y3,value:tf(i)},{key:"user",label:"用户",value:n?.user?.username||"--",tone:"user"}];return t("header",{className:"topbar"},t("div",null,t("p",{className:"eyebrow"},"Distributed Work Platform"),t("h1",null,"UniDesk 控制平面")),t(bL,{className:"global-top-status",title:"状态",items:A,actions:[t("button",{key:"notification",type:"button",className:`notification-icon-btn ${$>0?"has-unread":""}`,onClick:_,"aria-label":"通知"},"\uD83D\uDD14",$>0?t("span",{key:"badge",className:"notification-badge"},$>99?"99+":$):null),t("button",{key:"refresh",type:"button",className:"ghost-btn",onClick:l},"刷新"),t("button",{key:"logout",type:"button",className:"ghost-btn danger",onClick:r},"退出")]}))}function dS(u){return!u.defaultPrevented&&u.button===0&&!u.metaKey&&!u.altKey&&!u.ctrlKey&&!u.shiftKey&&u.currentTarget.target!=="_blank"}function qw({moduleId:u,tabId:f,className:l,active:r=!1,title:n,testId:i,onNavigate:y,children:_}){let $=f6(Vr,u,f);return t("a",{href:$,role:"button",className:l,title:n,"aria-current":r?"page":void 0,"data-testid":i,"data-route":$,onClick:(A)=>{if(!dS(A))return;A.preventDefault(),y(u,f)}},_)}function eS({activeModule:u,activeTabs:f,onNavigate:l,collapsed:r,onToggle:n}){return t("aside",{className:`rail ${r?"collapsed":""}`,"aria-label":"主模块"},t("div",{className:"brand"},t("span",{className:"brand-mark"},"UD"),t("span",{className:"brand-text"},"UniDesk"),t("button",{type:"button",className:"rail-toggle",onClick:n,"aria-label":r?"展开左侧边栏":"收起左侧边栏","data-testid":"rail-toggle"},r?"»":"«")),u6.map((i)=>{let y=f[i.id]||b_[i.id]||i.tabs[0]?.id||"";return t(qw,{key:i.id,moduleId:i.id,tabId:y,className:`module ${u===i.id?"active":""}`,active:u===i.id,title:i.label,onNavigate:l},t("span",{className:"module-code"},i.code),t("span",null,i.label))}))}function up({module:u,activeTab:f,onNavigate:l}){return t("nav",{className:"tabs","aria-label":`${u.label} 子功能`},u.tabs.map((r)=>t(qw,{key:r.id,moduleId:u.id,tabId:r.id,className:`tab ${f===r.id?"active":""}`,active:f===r.id,onNavigate:l},r.label)))}function fp({data:u,onRaw:f,onNavigate:l}){let r=u.overview||{},n=u.nodes.filter((U)=>U.status==="online"),i=u.pendingTasks||u.tasks.filter(Ny),y=r.pendingTaskCount??i.length,_=u.tasks.slice(0,5),$=r.pgdata||{},A=r.microserviceAvailability||{},c=Mu(A.totalCount),j=Mu(A.healthyCount),F=Mu(A.unhealthyCount);return t("div",{className:"page-grid overview-grid","data-testid":"overview-page"},t(au,{title:"核心指标",eyebrow:"Control"},t("div",{className:"metric-grid"},t(cf,{label:"数据库",value:r.dbReady?"READY":"WAIT",hint:"PostgreSQL internal network",tone:r.dbReady?"ok":"warn"}),t(cf,{label:"PGDATA",value:zl($.databaseBytes),hint:`${$.volumeName||"unidesk_pgdata_10gb"} / ${$.databasePretty||"--"}`,tone:"ok",testId:"pgdata-usage-card"}),t(cf,{label:"在线节点",value:r.onlineNodeCount??0,hint:`${r.nodeCount??0} registered`,tone:"ok"}),t(cf,{label:"WebSocket",value:r.activeSocketCount??0,hint:"Provider ingress sockets"}),t(cf,{label:"用户服务可用",value:c>0?`${j}/${c}`:"--",hint:c>0?`healthyCount ${j} · unhealthyCount ${F}`:"strict /health probes",tone:c>0&&F===0?"ok":"warn",testId:"microservice-availability-card"}),t(cf,{label:"待处理任务",value:y,hint:y>0?"点击查看具体任务":`timeout ${x0(Math.floor((r.taskPendingTimeoutMs??0)/1000))}`,tone:y>0?"warn":"ok",onClick:()=>l("tasks","pending"),testId:"pending-task-card"}))),t(au,{title:"本机 Provider",eyebrow:"Self Connected"},n.length===0?t(Ff,{title:"暂无在线节点",text:"provider-gateway 未完成自接入"}):t("div",{className:"node-card-list"},n.slice(0,4).map((U)=>t(lp,{key:U.providerId,node:U,onRaw:f})))),t(au,{title:"待处理任务明细",eyebrow:`${y} Pending`,actions:t("button",{type:"button",className:"ghost-btn",onClick:()=>l("tasks","pending"),"data-testid":"pending-task-detail-link"},"进入任务调度")},i.length===0?t(Ff,{title:"当前无待处理",text:"queued / dispatched / running 超时后会自动转为 failed,避免总览长期卡住"}):t("div",{className:"compact-list"},i.slice(0,5).map((U)=>t(fw,{key:U.id,task:U,onRaw:f})))),t(au,{title:"最近任务",eyebrow:"Dispatch"},_.length===0?t(Ff,{title:"暂无任务",text:"可以在任务调度模块发起 docker.ps 或 echo"}):t("div",{className:"compact-list"},_.map((U)=>t(fw,{key:U.id,task:U,onRaw:f})))))}function lp({node:u,onRaw:f}){return t("article",{className:"node-card"},t("div",{className:"node-card-head"},t("div",null,t("strong",null,u.name),t("code",null,u.providerId)),t(wf,{status:u.status})),t("div",{className:"node-version-line"},t(qy,{node:u}),t("span",null,`升级策略 ${m$(u)}`)),t(e9,{node:u}),t(Qw,{labels:u.labels,limit:6}),t("div",{className:"node-card-foot"},t("span",null,`心跳 ${Nu(u.lastHeartbeat)}`),t(bf,{title:`Provider ${u.providerId}`,data:u,onOpen:f,testId:`raw-node-${ol(u.providerId)}`})))}function rp({events:u,onRaw:f}){return t(au,{title:"事件摘要",eyebrow:"Latest 100"},u.length===0?t(Ff,{title:"暂无事件",text:"Provider 注册、心跳超时和任务状态会写入事件流"}):t("div",{className:"table-wrap"},t("table",null,t("thead",null,t("tr",null,t("th",null,"ID"),t("th",null,"类型"),t("th",null,"来源"),t("th",null,"摘要"),t("th",null,"时间"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.id},t("td",null,t("code",null,l.id)),t("td",null,t(wf,{status:l.type},l.type)),t("td",null,t("code",null,l.source)),t("td",null,t(vn,{data:l.payload})),t("td",null,Nu(l.createdAt)),t("td",null,t(bf,{title:`Event ${l.id}`,data:l,onOpen:f}))))))))}function np({logs:u,onRaw:f}){return t(au,{title:"服务日志",eyebrow:"Core Recent"},u.length===0?t(Ff,{title:"暂无日志",text:"backend-core 内存日志会在请求和 provider 事件后出现"}):t("div",{className:"log-list"},u.slice(-80).reverse().map((l,r)=>t("article",{key:r,className:`log-row ${l.level||"info"}`},t("span",null,Nu(l.ts)),t("b",null,l.level||"info"),t("strong",null,l.message||"log"),t(vn,{data:l.data,empty:"无附加字段"}),t(bf,{title:`Log ${l.message||r}`,data:l,onOpen:f})))))}function ip({nodes:u,onRaw:f}){return t(au,{title:"节点清单",eyebrow:`${u.length} Providers`},u.length===0?t(Ff,{title:"暂无 Provider 节点",text:"确认 provider-gateway 已连接 provider ingress"}):t("div",{className:"table-wrap"},t("table",{className:"node-list-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"Provider"),t("th",null,"网关版本"),t("th",null,"运维可用性"),t("th",null,"资源标签"),t("th",null,"连接时间"),t("th",null,"最后心跳"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.providerId},t("td",null,t(wf,{status:l.status})),t("td",null,t("strong",null,l.name),t("code",null,l.providerId)),t("td",null,t("div",{className:"gateway-cell"},t(qy,{node:l}),t("span",null,m$(l)))),t("td",null,t(e9,{node:l})),t("td",null,t(Qw,{labels:l.labels,limit:5})),t("td",null,Nu(l.connectedAt)),t("td",null,Nu(l.lastHeartbeat)),t("td",null,t(bf,{title:`Provider ${l.providerId}`,data:l,onOpen:f,testId:`raw-node-table-${ol(l.providerId)}`}))))))))}function yp({nodes:u}){let f=P$(()=>{let l=[];for(let r of u)for(let[n,i]of _w(r.labels))l.push({providerId:r.providerId,name:r.name,key:n,value:i});return l},[u]);return t(au,{title:"资源标签",eyebrow:"Structured Labels"},f.length===0?t(Ff,{title:"暂无标签",text:"provider-gateway 注册消息会同步资源标签"}):t("div",{className:"label-matrix"},f.map((l)=>t("article",{key:`${l.providerId}-${l.key}`,className:"label-card"},t("span",null,l.key),t("strong",null,M1(l.value)),t("code",null,l.providerId)))))}function _p({nodes:u}){return t(au,{title:"心跳状态",eyebrow:"Provider Liveness"},u.length===0?t(Ff,{title:"无心跳",text:"等待 provider 注册和 heartbeat"}):t("div",{className:"heartbeat-list"},u.map((f)=>t("article",{key:f.providerId,className:"heartbeat-row"},t("span",{className:`pulse ${f.status}`}),t("div",null,t("strong",null,f.name),t("code",null,f.providerId)),t("div",null,t("span",null,"connected"),t("b",null,Nu(f.connectedAt))),t("div",null,t("span",null,"last heartbeat"),t("b",null,Nu(f.lastHeartbeat)))))))}function $p({nodes:u,systemStatuses:f,tasks:l,onRaw:r,refresh:n}){let[i,y]=hu(""),_=P$(()=>u.map((L)=>{let w=f.find((J)=>J.providerId===L.providerId);return{...L,systemCurrent:w?.current||null,systemHistory:w?.history||[],systemUpdatedAt:w?.updatedAt||null}}),[u,f]),$=_.find((L)=>L.providerId===i)||_[0]||null;if(F0(()=>{if(!i&&_[0])y(_[0].providerId)},[_.length,i]),!$)return t(Ff,{title:"暂无资源监控",text:"等待 provider 上报 CPU、内存和硬盘指标"});let A=$.systemCurrent,c=$.systemHistory||[],j=A?.cpu||{},F=A?.memory||{},U=A?.disk||{},Q=c.length>0?c:A?[{at:A.collectedAt,cpuPercent:Mu(j.percent),memoryPercent:Mu(F.percent),diskPercent:Mu(U.percent)}]:[];return t("div",{className:"monitor-page","data-testid":"node-monitor-page"},t("div",{className:"docker-node-strip"},_.map((L)=>t("button",{key:L.providerId,type:"button",className:`docker-node-tile ${$.providerId===L.providerId?"active":""}`,onClick:()=>y(L.providerId)},t("span",{className:`pulse ${L.status}`}),t("strong",null,L.name),t("code",null,L.providerId),t("span",null,L.systemCurrent?`CPU ${hn(L.systemCurrent.cpu?.percent)} / MEM ${hn(L.systemCurrent.memory?.percent)}`:"等待指标")))),t("div",{className:"monitor-layout"},t(au,{title:"任务管理器视图",eyebrow:$.name,className:"monitor-main-panel",actions:A?t(bf,{title:`System ${$.providerId}`,data:{current:A,history:c},onOpen:r}):null},!A?t(Ff,{title:"系统指标未上报",text:"provider-gateway 会周期性采集 /proc 与 df,并保存历史曲线"}):t("div",null,t("div",{className:"monitor-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Node Performance"),t("h3",null,$.name),t("div",{className:"docker-meta"},t("span",null,`${j.cores||0} CPU cores`),t("span",null,`load ${Mu(j.load1).toFixed(2)} / ${Mu(j.load5).toFixed(2)} / ${Mu(j.load15).toFixed(2)}`),t("span",null,`memory actual ${zl(F.usedBytes)} / ${zl(F.totalBytes)}`),t("span",null,`disk ${zl(U.usedBytes)} / ${zl(U.totalBytes)}`))),t(wf,{status:A.ok?"online":"warn"},A.ok?"METRICS READY":"METRICS DEGRADED")),t("div",{className:"monitor-chart-grid"},t(I9,{title:"CPU",metricKey:"cpuPercent",current:j.percent,points:Q,detail:`${j.cores||0} cores / load ${Mu(j.load1).toFixed(2)}`,tone:"cpu",testId:"metric-chart-cpu"}),t(I9,{title:"Memory",metricKey:"memoryPercent",current:F.percent,points:Q,detail:`${zl(F.usedBytes)} actual / ${zl(F.cacheBytes)} cache excluded`,tone:"memory",testId:"metric-chart-memory"}),t(I9,{title:"Disk",metricKey:"diskPercent",current:U.percent,points:Q,detail:`${U.path||"/"} mounted ${U.mount||"--"}`,tone:"disk",testId:"metric-chart-disk"})),t("div",{className:"monitor-summary-grid"},t(cf,{label:"CPU 当前",value:hn(j.percent),hint:`history ${Q.length} samples`,tone:"ok"}),t(cf,{label:"实际内存",value:zl(F.usedBytes),hint:`${hn(F.percent)} 不含缓存`}),t(cf,{label:"硬盘已用",value:zl(U.usedBytes),hint:hn(U.percent)}),t(cf,{label:"更新时间",value:Nu($.systemUpdatedAt||A.collectedAt),hint:$.providerId})),t(tp,{current:A,onRaw:r}))),t("div",{className:"monitor-side-stack"},t(qp,{provider:$,refresh:n,onRaw:r}),t(Np,{provider:$,tasks:l,onRaw:r,limit:5}),t(au,{title:"采样说明",eyebrow:"Retention"},t("div",{className:"monitor-note-list"},t("article",null,t("b",null,"CPU"),t("span",null,"从 /proc/stat 计算相邻采样差值,首个采样用 load/cores 近似")),t("article",null,t("b",null,"Memory"),t("span",null,"实际内存 = MemTotal - MemFree - Buffers - Cached - SReclaimable + Shmem,不把 page cache / buffer 计入占用")),t("article",null,t("b",null,"Disk"),t("span",null,"使用 df -PB1 对配置路径采样,默认监控根文件系统")),t("article",null,t("b",null,"Process"),t("span",null,"从 /proc/[pid] 采集进程 CPU、实际内存 RSS、线程数和磁盘 I/O 速率;表格默认按内存占用降序")))))))}function dL(u,f){if(f==="memory")return Mu(u.rssBytes);if(f==="cpu")return Mu(u.cpuPercent);if(f==="disk")return Mu(u.readBytesPerSecond)+Mu(u.writeBytesPerSecond);if(f==="pid")return Mu(u.pid);if(f==="threads")return Mu(u.threads);if(f==="runtime")return Mu(u.elapsedSeconds);if(f==="user")return String(u.user||"");return String(u.name||u.command||"")}function eL({value:u,label:f,tone:l}){let r=Math.max(1,Math.min(100,Mu(u)));return t("div",{className:`process-meter ${l||""}`},t("span",{style:{width:`${r}%`}}),t("b",null,f))}function tp({current:u,onRaw:f}){let[l,r]=hu({key:"memory",direction:"desc"}),n=bn.default.useContext(s9),i=u?.processSummary&&typeof u.processSummary==="object"?u.processSummary:{},y=Array.isArray(u?.processes)?u.processes:[],_=P$(()=>{let A=l.direction==="asc"?1:-1;return[...y].sort((c,j)=>{let F=dL(c,l.key),U=dL(j,l.key);if(typeof F==="string"||typeof U==="string")return String(F).localeCompare(String(U),"zh-CN")*A;return(F-U)*A||Mu(c.pid)-Mu(j.pid)})},[y,l.key,l.direction]),$=(A,c)=>{let j=l.key===c,F=j?l.direction==="asc"?"ascending":"descending":"none";return t("th",{"aria-sort":F},t("button",{type:"button",className:`process-sort-button ${j?"active":""}`,"data-testid":`process-sort-${c}`,onClick:()=>r((U)=>({key:c,direction:U.key===c&&U.direction==="desc"?"asc":"desc"}))},A,t("span",null,j?l.direction==="desc"?"↓":"↑":"↕")))};return t("section",{className:"process-resource-panel","data-testid":"process-resource-panel"},t("div",{className:"process-resource-head"},t("div",null,t("p",{className:"panel-eyebrow"},"Windows Resource Monitor Style"),t(nf,{title:"进程资源占用",level:3,loading:n})),t("div",{className:"process-resource-actions"},t("span",{className:"data-chip"},"默认按内存排序"),t("span",{className:"data-chip"},`${Mu(i.visible,_.length)} / ${Mu(i.total,_.length)} 进程`),t(bf,{title:"Process Resource Snapshot",data:{processSummary:i,processes:y},onOpen:f,testId:"raw-process-resources"}))),_.length===0?t(Ff,{title:"暂无进程资源数据",text:"等待 provider-gateway 上报 /proc/[pid] 采样;旧版 provider 需要先升级到支持进程资源表的版本"}):t("div",{className:"process-table-wrap"},t("table",{className:"process-resource-table","data-testid":"process-resource-table"},t("thead",null,t("tr",null,$("进程","name"),$("PID","pid"),$("用户","user"),t("th",null,"状态"),$("CPU","cpu"),$("内存","memory"),t("th",null,"RSS"),$("磁盘 I/O","disk"),$("线程","threads"),$("运行时长","runtime"))),t("tbody",null,_.map((A)=>{let c=Mu(A.readBytesPerSecond)+Mu(A.writeBytesPerSecond);return t("tr",{key:`${A.pid}-${A.startedAt}`,"data-testid":`process-row-${ol(A.pid)}`,"data-memory-bytes":String(Mu(A.rssBytes)),"data-cpu-percent":String(Mu(A.cpuPercent)),"data-disk-bps":String(c),"data-pid":String(Mu(A.pid))},t("td",null,t("div",{className:"process-name-cell"},t("strong",null,A.name||"--"),t("span",{className:"process-command"},A.command||"--"))),t("td",null,t("code",null,A.pid||"--")),t("td",null,A.user||`uid:${A.uid??"--"}`),t("td",null,t("span",{className:`process-state state-${ol(A.state||"unknown")}`},A.state||"?")),t("td",null,t(eL,{value:A.cpuPercent,label:RS(A.cpuPercent),tone:"cpu"})),t("td",null,t(eL,{value:A.memoryPercent,label:hn(A.memoryPercent),tone:"memory"})),t("td",null,zl(A.rssBytes)),t("td",null,t("div",{className:"process-io-cell"},t("strong",null,k9(c)),t("span",null,`R ${k9(A.readBytesPerSecond)} / W ${k9(A.writeBytesPerSecond)}`))),t("td",null,A.threads||0),t("td",null,x0(Mu(A.elapsedSeconds))))})))))}function I9({title:u,metricKey:f,current:l,points:r,detail:n,tone:i,testId:y}){let _=r.map((F)=>Math.max(0,Math.min(100,Mu(F[f])))),$=_.length>1?_:[_[0]||0,_[0]||0],A=$.length<=1?100:100/($.length-1),c=$.map((F,U)=>`${(U*A).toFixed(2)},${(46-F*0.42).toFixed(2)}`).join(" "),j=`0,48 ${c} 100,48`;return t("article",{className:`metric-chart ${i}`,"data-testid":y},t("div",{className:"metric-chart-head"},t("div",null,t("span",null,u),t("strong",null,hn(l))),t("code",null,`${r.length} pts`)),t("svg",{viewBox:"0 0 100 48",preserveAspectRatio:"none",role:"img","aria-label":`${u} usage curve`},t("polygon",{points:j}),t("polyline",{points:c}),t("line",{x1:"0",x2:"100",y1:"24",y2:"24"})),t("div",{className:"metric-chart-foot"},t("span",null,"0%"),t("span",null,n),t("span",null,"100%")))}function h0(u){return Array.isArray(u)?u:[]}function Ap(u){let f=h0(u?.core?.requests?.componentSummary);return[...h0(u?.frontend?.requests?.componentSummary),...f].sort((r,n)=>Mu(n.requestCount)-Mu(r.requestCount))}function cp(u){let f=h0(u?.core?.operations?.summary);return[...h0(u?.frontend?.operations?.summary),...f].sort((r,n)=>Mu(n.count)-Mu(r.count))}function jp(u){let f=h0(u?.core?.requests?.recentFailures).map((r)=>({source:"backend",...r}));return[...h0(u?.frontend?.requests?.recentFailures).map((r)=>({source:"frontend",...r})),...f].sort((r,n)=>(J0(n.at)??0)-(J0(r.at)??0)).slice(0,20)}function Fp(u){let f=h0(u?.core?.operations?.recentSlowOperations);return[...h0(u?.frontend?.operations?.recentSlowOperations),...f].sort((r,n)=>Mu(n.durationMs)-Mu(r.durationMs)).slice(0,20)}function Jp(u){let f=performance.memory,l=Number(f?.usedJSHeapSize);if(Number.isFinite(l)&&l>0)return l;let r=Number(u?.appBundleBytes);if(Number.isFinite(r)&&r>0)return r;return Mu(u?.process?.heapUsedBytes)}function Up({points:u}){let f=h0(u),l=f.map((F)=>Mu(F.mb)),r=Math.max(1,...l),n=Math.max(0,Math.min(...l,0)),i=Math.max(1,r-n),y=f.length>1?f:[...f,...f],_=y.length<=1?100:100/(y.length-1),$=y.map((F,U)=>{let Q=Mu(F.mb);return`${(U*_).toFixed(2)},${(48-(Q-n)/i*42).toFixed(2)}`}).join(" "),A=`0,50 ${$} 100,50`,c=f.at(-1),j=f[0];return t("article",{className:"performance-memory-card","data-testid":"performance-memory-chart"},t("div",{className:"performance-memory-head"},t("strong",null,`Bwebui: ${c?`${Mu(c.mb).toFixed(1)}MB`:"--"}`),t("span",null,f.length>0?`${f.length} samples`:"等待采样")),t("svg",{viewBox:"0 0 100 50",preserveAspectRatio:"none",role:"img","aria-label":"Bwebui memory trend"},t("polygon",{points:A}),t("polyline",{points:$}),t("line",{x1:"0",x2:"100",y1:"25",y2:"25"})),t("div",{className:"performance-axis-row"},t("span",null,j?tf(new Date(j.at)):"--"),t("span",null,"时间"),t("span",null,c?tf(new Date(c.at)):"--")),t("div",{className:"performance-axis-row"},t("span",null,`${n.toFixed(1)}`),t("span",null,"(MB)"),t("span",null,`${r.toFixed(1)}`)))}function Qp({onRaw:u}){let[f,l]=hu({core:null,frontend:null}),[r,n]=hu([]),[i,y]=hu(""),[_,$]=hu(!1),[A,c]=hu(null),[j,F]=hu(!1);async function U(){$(!0),y("");try{let[Y,p]=await Promise.all([Eu(`${gu.apiBaseUrl}/performance`,{cache:"no-store"}),Eu(`${gu.apiBaseUrl}/frontend-performance`,{cache:"no-store"})]);l({core:Y,frontend:p});let O=Jp(p);n((m)=>[...m,{at:new Date().toISOString(),mb:O/1048576}].slice(-80))}catch(Y){y(Hu(Y,"性能指标加载失败"))}finally{$(!1)}}F0(()=>{U();let Y=setInterval(()=>void U(),5000);return()=>clearInterval(Y)},[]);async function Q(){F(!0),y(""),c(null);try{let Y=await Eu(`${gu.apiBaseUrl}/code-queue-load-test`,{method:"POST",body:JSON.stringify({targetMs:1000,timeoutMs:90000,url:gu.frontendPublicUrl||window.location.origin})});c(Y),U()}catch(Y){y(Hu(Y,"Code Queue Playwright 测量失败"))}finally{F(!1)}}let L=Ap(f),w=jp(f),J=cp(f),N=Fp(f),q=f.core?.process||{},W=f.frontend?.process||{},z=f.core?.database?.codeQueueStorage||{},Z=Mu(z.total),H=A?.result||{},E=Mu(H.wallMs,NaN),D=Mu(H.networkIdleMs,NaN),h=H.withinTarget===!0,V=j?"running":A===null?"idle":A.measurementOk===!0?h?"passed":"slow":"failed";return t("div",{className:"performance-page","data-testid":"performance-page"},t("div",{className:"performance-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Unified Performance"),t(nf,{title:"性能面板",loading:_||j}),t("p",null,"按组件统计 HTTP 请求、失败率、P95 延迟,并汇总 backend/frontend 内部操作耗时。")),t("div",{className:"inline-actions"},t("button",{type:"button",className:"ghost-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-button"},j?"测试中...":"测试 Code Queue 加载"),t("button",{type:"button",className:"ghost-btn",onClick:()=>void U(),disabled:_,"data-testid":"performance-refresh-button"},_?"刷新中":"刷新"),t(bf,{title:"Performance Snapshot",data:f,onOpen:u,testId:"raw-performance"}))),t(yf,{error:i}),t("div",{className:"performance-top-grid"},t(Up,{points:r}),t("div",{className:"performance-metric-stack"},t(cf,{label:"backend RSS",value:zl(q.rssBytes),hint:`heap ${zl(q.heapUsedBytes)}`}),t(cf,{label:"frontend RSS",value:zl(W.rssBytes),hint:`bundle ${zl(f.frontend?.appBundleBytes)}`}),t(cf,{label:"Codex PG 任务",value:Z||"--",hint:z.ok?"unidesk_code_queue_tasks":"等待表初始化",tone:z.ok?"ok":"warn"}),t(cf,{label:"请求样本",value:Mu(f.core?.requests?.sampleCount)+Mu(f.frontend?.requests?.sampleCount),hint:"rolling window 3000"}))),t(au,{title:"Code Queue 加载基准",eyebrow:"Playwright / target <1s",className:"codex-load-test-panel",loading:j,actions:t("div",{className:"panel-actions"},t("button",{type:"button",className:"primary-btn",onClick:()=>void Q(),disabled:j,"data-testid":"code-queue-load-test-panel-button"},j?"正在运行 Playwright...":"手动触发测试"),A?t(bf,{title:"Code Queue Load Test",data:A,onOpen:u,testId:"raw-code-queue-load-test"}):null)},t("div",{className:"codex-load-test-grid","data-testid":"code-queue-load-test-result"},t(cf,{label:"总耗时",value:j?"运行中":Number.isFinite(E)?Qr(E):"--",hint:A===null?"点击按钮启动远端 Playwright":`目标 ${Qr(H.targetMs||1000)} / ${H.url||"Code Queue"}`,tone:V==="passed"?"ok":V==="failed"||V==="slow"?"warn":""}),t(cf,{label:"判定",value:j?"RUNNING":V==="passed"?"PASS <1s":V==="slow"?"SLOW":V==="failed"?"FAILED":"--",hint:A?.measurementOk===!1?String(A.error||H.error||"measurement failed").slice(0,120):"导航开始 -> DOMContentLoaded -> data-load-state=complete",tone:V==="passed"?"ok":V==="idle"||V==="running"?"":"fail"}),t(cf,{label:"Network idle",value:Number.isFinite(D)?Qr(D):"--",hint:`DOMContentLoaded ${Qr(H.domContentLoadedMs)} / ${H.networkIdleReached===!1?"未在 5s 内空闲":"已空闲"}`,tone:Number.isFinite(D)&&D<=1000?"ok":"warn"}),t(cf,{label:"组件耗时",value:Number.isFinite(Mu(H.componentLoadMs,NaN))?Qr(H.componentLoadMs):"--",hint:`queue ${Qr(H.queueMs)} / detail ${Qr(H.detailMs)}`,tone:Mu(H.componentLoadMs)>1000?"warn":"ok"}),t(cf,{label:"Trace 规模",value:Number.isFinite(Mu(H.transcriptRows,NaN))?String(H.transcriptRows):"--",hint:`${H.visibleTaskCount??0} visible tasks / ${H.partial?"preview":"complete"}`})),j?t("div",{className:"performance-empty-line"},"正在通过 main-server Host SSH 启动 Playwright,完成后会显示 wall time、组件耗时和最慢 API。"):null,A&&Array.isArray(H.slowestApi)&&H.slowestApi.length>0?t("div",{className:"table-wrap performance-table-wrap compact codex-load-api-table"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["API","状态","耗时"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,H.slowestApi.slice(0,5).map((Y,p)=>t("tr",{key:`${Y.url}-${p}`},t("td",null,t("code",null,Y.url)),t("td",null,Y.status),t("td",null,Qr(Y.durationMs))))))):null),t("div",{className:"performance-grid"},t(au,{title:"组件汇总",eyebrow:"Requests",loading:_},L.length===0?t(Ff,{title:"暂无请求样本",text:"刷新几次或打开页面后会自动形成组件统计"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["组件","请求数","失败数","失败率","平均延迟","P95"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,L.map((Y)=>t("tr",{key:Y.component},t("td",null,t("code",null,Y.component)),t("td",null,Y.requestCount),t("td",null,Y.failureCount),t("td",null,hn(Mu(Y.failureRate)*100)),t("td",null,Qr(Y.averageLatencyMs)),t("td",null,Qr(Y.p95LatencyMs)))))))),t(au,{title:"最近失败请求",eyebrow:"Failures",loading:_},w.length===0?t("div",{className:"performance-empty-line"},"最近没有失败请求"):t("div",{className:"table-wrap performance-table-wrap compact"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["时间","来源","组件","状态","路径"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,w.map((Y,p)=>t("tr",{key:`${Y.at}-${p}`},t("td",null,Nu(Y.at)),t("td",null,Y.source),t("td",null,t("code",null,Y.component)),t("td",null,t(wf,{status:"failed"},Y.status)),t("td",null,t("code",null,Y.path)))))))),t(au,{title:"内部操作汇总",eyebrow:"Operations",loading:_},J.length===0?t(Ff,{title:"暂无内部操作样本",text:"API 查询和代理请求会自动记录内部操作耗时"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["服务","操作","次数","平均延迟","P95"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,J.map((Y)=>t("tr",{key:`${Y.service}-${Y.operation}`},t("td",null,Y.service),t("td",null,t("code",null,Y.operation)),t("td",null,Y.count),t("td",null,Qr(Y.averageLatencyMs)),t("td",null,Qr(Y.p95LatencyMs)))))))),t(au,{title:"最近慢操作",eyebrow:"Slowest",loading:_},N.length===0?t(Ff,{title:"暂无慢操作",text:"后端会记录最近窗口内耗时最高的内部操作"}):t("div",{className:"table-wrap performance-table-wrap"},t("table",{className:"performance-table"},t("thead",null,t("tr",null,["时间","操作","耗时","结果","细节"].map((Y)=>t("th",{key:Y},Y)))),t("tbody",null,N.map((Y,p)=>t("tr",{key:`${Y.at}-${Y.operation}-${p}`},t("td",null,Nu(Y.at)),t("td",null,t("code",null,Y.operation)),t("td",null,Qr(Y.durationMs)),t("td",null,Y.ok?"成功":"失败"),t("td",null,Y.detail||"-")))))))))}function qp({provider:u,refresh:f,onRaw:l}){let[r,n]=hu(""),[i,y]=hu(null),[_,$]=hu("");async function A(c){n(c),$("");try{let j=await Eu(`${gu.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:u.providerId,command:"provider.upgrade",payload:{mode:c,source:"frontend-resource-monitor",requestedAt:new Date().toISOString()}})});y({mode:c,...j}),await f()}catch(j){$(Hu(j,"升级命令下发失败"))}finally{n("")}}return t(au,{title:"Provider Gateway 升级",eyebrow:"Remote Control",loading:Boolean(r)},t("div",{className:"upgrade-control","data-testid":"provider-upgrade-control"},t("p",null,"通过 UniDesk WebSocket 向当前计算节点下发 provider.upgrade;预检只生成升级计划,执行升级会调度节点本地 updater 容器。"),t("div",{className:"upgrade-target-line"},t("span",null,"指定 Provider"),t("code",null,u.providerId),t(qy,{node:u})),t("div",{className:"upgrade-actions"},t("button",{type:"button",className:"ghost-btn",disabled:Boolean(r),onClick:()=>A("plan"),"data-testid":"upgrade-plan-button"},r==="plan"?"预检中":"预检升级"),t("button",{type:"button",className:"ghost-btn danger",disabled:Boolean(r),onClick:()=>A("schedule"),"data-testid":"upgrade-schedule-button"},r==="schedule"?"调度中":"执行升级")),t(yf,{error:_}),i?t("div",{className:"upgrade-result"},t(wf,{status:i.status||"queued"},i.status||"queued"),t("span",null,`${i.mode==="schedule"?"执行升级":"预检升级"} 已下发`),t("span",null,`指定版本 ${d9($w(u))}`),t("code",null,i.taskId||"--"),t(bf,{title:"Provider Upgrade Dispatch",data:i,onOpen:l})):t("span",{className:"muted"},"升级任务结果会进入任务历史;执行升级可能导致 provider 短暂重连。")))}function Nw({records:u,onRaw:f,compact:l=!1}){if(u.length===0)return t(Ff,{title:"暂无远程更新记录",text:"该节点还没有 provider.upgrade 任务;执行预检或升级后会在这里形成结构化记录"});return t("div",{className:`upgrade-record-table-wrap table-wrap ${l?"compact":""}`},t("table",{className:"upgrade-record-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"模式"),t("th",null,"任务"),t("th",null,"来源"),t("th",null,"耗时"),t("th",null,"策略"),t("th",null,"Gateway 版本"),t("th",null,"结果记录"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,u.map((r)=>t("tr",{key:r.id,"data-testid":`gateway-upgrade-record-${ol(r.id)}`},t("td",null,t(wf,{status:r.status})),t("td",null,t("span",{className:`mode-chip ${O8(r)}`},O8(r)==="schedule"?"执行升级":"预检")),t("td",null,t("strong",null,"provider.upgrade"),t("code",null,r.id)),t("td",null,vS(r)),t("td",null,t(Lw,{task:r})),t("td",null,kS(r)),t("td",null,t("span",{className:"version-chip"},jw(r))),t("td",null,t("span",{className:`upgrade-outcome ${String(r.status||"").toLowerCase()}`},Fw(r))),t("td",null,Nu(r.updatedAt)),t("td",null,t(bf,{title:`Provider Upgrade Task ${r.id}`,data:M$(r),onOpen:f})))))))}function Np({provider:u,tasks:f,onRaw:l,limit:r=5}){let n=Jw(f,u.providerId).slice(0,r);return t(au,{title:"远程更新记录",eyebrow:u.providerId,actions:t(qy,{node:u}),className:"provider-upgrade-records-panel"},t("div",{"data-testid":`provider-upgrade-records-${ol(u.providerId)}`},t(Nw,{records:n,onRaw:l,compact:!0})))}function Wp({nodes:u,tasks:f,onRaw:l}){let r=P$(()=>u.map((i)=>{let y=Jw(f,i.providerId);return{node:i,records:y,latest:IS(y),capabilities:tw(i)}}),[u,f]),n=r.reduce((i,y)=>i+y.records.length,0);return t("div",{className:"gateway-page","data-testid":"gateway-version-page"},t(au,{title:"Provider Gateway 版本",eyebrow:`${u.length} Providers / ${n} 更新记录`},u.length===0?t(Ff,{title:"暂无 Provider 节点",text:"等待 provider-gateway 注册后显示版本号和升级记录"}):t("div",{className:"table-wrap gateway-version-table-wrap"},t("table",{className:"gateway-version-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"Provider"),t("th",null,"Gateway 版本"),t("th",null,"升级策略"),t("th",null,"运维可用性"),t("th",null,"运行时间"),t("th",null,"能力"),t("th",null,"最近远程更新"),t("th",null,"操作"))),t("tbody",null,r.map((i)=>t("tr",{key:i.node.providerId},t("td",null,t(wf,{status:i.node.status})),t("td",null,t("strong",null,i.node.name),t("code",null,i.node.providerId)),t("td",null,t(qy,{node:i.node})),t("td",null,m$(i.node)),t("td",null,t(e9,{node:i.node})),t("td",null,gL(i.node)?Nu(gL(i.node)):"待新版上报"),t("td",null,t("div",{className:"capability-row"},i.capabilities.length===0?t("span",{className:"muted"},"未声明"):i.capabilities.slice(0,5).map((y)=>t("span",{key:y,className:"data-chip"},y)))),t("td",null,i.latest?t("div",{className:"latest-upgrade-cell"},t(wf,{status:i.latest.status}),t("span",null,`${O8(i.latest)==="schedule"?"执行升级":"预检"} / ${Nu(i.latest.updatedAt)}`),t("small",null,`Gateway ${jw(i.latest)}`),t("small",null,Fw(i.latest))):t("span",{className:"muted"},"暂无记录")),t("td",null,t(bf,{title:`Provider ${i.node.providerId}`,data:i.node,onOpen:l})))))))),t(au,{title:"远程更新记录",eyebrow:"Structured provider.upgrade records"},u.length===0?t(Ff,{title:"暂无记录",text:"没有 provider 节点时不会生成远程更新记录"}):t("div",{className:"gateway-record-grid"},r.map((i)=>t("article",{key:i.node.providerId,className:"gateway-record-card","data-testid":`gateway-records-${ol(i.node.providerId)}`},t("div",{className:"gateway-record-head"},t("div",null,t("strong",null,i.node.name),t("code",null,i.node.providerId)),t(qy,{node:i.node})),t("div",{className:"gateway-record-meta"},t("span",null,`心跳 ${Nu(i.node.lastHeartbeat)}`),t("span",null,`策略 ${m$(i.node)}`),t("span",null,`${i.records.length} 条记录`)),t(Nw,{records:i.records.slice(0,8),onRaw:l,compact:!0}))))))}function Lp(u){if(u==="running")return"online";if(u==="paused"||u==="restarting")return"warn";if(u==="exited"||u==="dead")return"offline";return"internal"}function Ww(u){return/^[a-f0-9]{48,64}$/i.test(u)}function p$(u){let f=String(u?.name||""),l=String(u?.labels||"");return f==="unidesk_pgdata_10gb"||l.includes("com.docker.compose.volume=unidesk_pgdata_10gb")||f.toLowerCase().includes("pgdata")}function uw(u){let f=String(u?.name||""),l=String(u?.labels||"");if(p$(u))return 0;if(l.includes("com.docker.compose.project=unidesk"))return 1;if(!Ww(f))return 2;return 3}function wp(u){return[...u].sort((f,l)=>{let r=uw(f)-uw(l);if(r!==0)return r;return String(f.name||"").localeCompare(String(l.name||""))})}function Kp({nodes:u,dockerStatuses:f,onRaw:l}){let[r,n]=hu(""),i=P$(()=>u.map((N)=>{let q=f.find((W)=>W.providerId===N.providerId);return{...N,dockerStatus:q?.dockerStatus||null,dockerUpdatedAt:q?.updatedAt||null}}),[u,f]),y=i.find((N)=>N.providerId===r)||i[0]||null;if(F0(()=>{if(!r&&i[0])n(i[0].providerId)},[i.length,r]),!y)return t(Ff,{title:"暂无 Docker 节点",text:"等待 provider 上报 Docker daemon 状态"});let _=y.dockerStatus,$=y.providerId==="main-server",A=_?.counts||{},c=_?.daemon||{},j=_?.containers||[],F=_?.images||[],U=wp(_?.volumes||[]),Q=$?U.find(p$):null,L=_?.networks||[],w=j.filter((N)=>N.state==="running"),J=j.filter((N)=>N.state!=="running");return t("div",{className:"docker-page","data-testid":"docker-status-page"},t("div",{className:"docker-node-strip"},i.map((N)=>t("button",{key:N.providerId,type:"button",className:`docker-node-tile ${y.providerId===N.providerId?"active":""}`,onClick:()=>n(N.providerId)},t("span",{className:`pulse ${N.status}`}),t("strong",null,N.name),t("code",null,N.providerId),t("span",null,N.dockerStatus?`Docker ${N.dockerStatus.ok?"ready":"degraded"}`:"等待上报")))),t("div",{className:"docker-layout"},t(au,{title:"Docker Desktop 视图",eyebrow:y.name,className:"docker-main-panel",actions:_?t(bf,{title:`Docker ${y.providerId}`,data:_,onOpen:l}):null},!_?t(Ff,{title:"Docker 状态未上报",text:"provider-gateway 会在连接后周期性采集 docker info / ps / images / volume / network"}):t("div",null,t("div",{className:"docker-hero"},t("div",null,t("p",{className:"panel-eyebrow"},"Daemon"),t("h3",null,c.name||y.providerId),t("div",{className:"docker-meta"},t("span",null,c.serverVersion?`Engine ${c.serverVersion}`:"Engine --"),t("span",null,c.operatingSystem||"OS --"),t("span",null,c.architecture||"arch --"),t("span",null,`${c.cpus||0} CPU / ${zl(c.memoryBytes)}`))),t(wf,{status:_.ok?"online":"warn"},_.ok?"Docker Ready":"Docker Degraded")),t("div",{className:"docker-metrics"},t(cf,{label:"Containers",value:A.containers??j.length,hint:`${A.running??w.length} running / ${A.stopped??J.length} stopped`,tone:"ok"}),t(cf,{label:"Images",value:A.images??F.length,hint:`${A.daemonImages??A.images??F.length} daemon images`}),t(cf,{label:"Volumes",value:A.volumes??U.length,hint:$?Q?"database volume visible":"database volume missing":"node local volumes",tone:Q?"ok":""}),t(cf,{label:"Networks",value:A.networks??L.length,hint:c.driver?`driver ${c.driver}`:"docker networks"})),$?t(Gp,{volume:Q,volumeCount:U.length}):null,t("div",{className:"docker-section-head"},t("h3",null,"Containers"),t("span",null,`updated ${Nu(y.dockerUpdatedAt||_.collectedAt)}`)),t("div",{className:"docker-container-table table-wrap","data-testid":"docker-container-table"},t("table",null,t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"容器"),t("th",null,"镜像"),t("th",null,"端口"),t("th",null,"运行时间"),t("th",null,"重启策略"),t("th",null,"PID"),t("th",null,"大小"))),t("tbody",null,j.length===0?t("tr",null,t("td",{colSpan:8},"暂无容器")):j.map((N)=>t("tr",{key:`${N.id}-${N.name}`},t("td",null,t(wf,{status:Lp(N.state)},N.state||"unknown")),t("td",null,t("strong",null,N.name||"--"),t("code",null,N.id||"--")),t("td",null,N.image||"--"),t("td",null,N.ports||t("span",{className:"muted"},"未发布")),t("td",null,N.runningFor||N.status||"--"),t("td",null,N.restartPolicy?t(wf,{status:N.restartPolicy==="always"?"online":"warn"},N.restartPolicy):"--"),t("td",null,N.pidMode?t("code",null,N.pidMode):"--"),t("td",null,N.size||"--")))))))),t("div",{className:"docker-side-stack"},t(g9,{title:"Images",items:F,render:(N)=>t("article",{key:`${N.id}-${N.repository}`,className:"docker-side-row"},t("strong",null,`${N.repository}:${N.tag}`),t("span",null,N.size||"--"),t("code",null,N.id||"--"))}),t(g9,{title:"Volumes",items:U,limit:U.length,render:(N)=>t("article",{key:N.name,className:`docker-side-row volume-row ${$&&p$(N)?"database-volume":""}`,"data-testid":$&&p$(N)?"database-volume-row":void 0},t("strong",null,N.name),t("span",null,$&&p$(N)?"PostgreSQL":Ww(String(N.name||""))?"anonymous":"named"),t("code",null,N.mountpoint||N.driver||N.scope||"--"))}),t(g9,{title:"Networks",items:L,render:(N)=>t("article",{key:N.id||N.name,className:"docker-side-row"},t("strong",null,N.name),t("span",null,N.driver||"--"),t("code",null,N.id||"--"))}))))}function Gp({volume:u,volumeCount:f}){return t("section",{className:`docker-volume-focus ${u?"ready":"missing"}`,"data-testid":"database-volume-card"},t("div",{className:"volume-focus-head"},t("span",{className:"panel-eyebrow"},"Database Named Volume"),t(wf,{status:u?"online":"warn"},u?"FOUND":"MISSING")),u?t("div",{className:"volume-focus-body"},t("strong",null,u.name),t("span",null,"PostgreSQL data volume for unidesk-database"),t("div",{className:"volume-route"},t("code",null,u.mountpoint||"/var/lib/docker/volumes/unidesk_pgdata_10gb/_data"),t("span",null,"->"),t("code",null,"unidesk-database:/var/lib/postgresql/data")),t("div",{className:"docker-meta compact"},t("span",null,`driver ${u.driver||"--"}`),t("span",null,`scope ${u.scope||"--"}`),t("span",null,`${f} volumes reported`))):t("div",{className:"volume-focus-body"},t("strong",null,"unidesk_pgdata_10gb"),t("span",null,"当前 Docker 快照没有发现数据库命名卷;请检查 provider-gateway 的 Docker volume 上报。")))}function g9({title:u,items:f,render:l,limit:r}){let n=f.slice(0,r??12),i=Math.max(0,f.length-n.length);return t(au,{title:u,eyebrow:`${f.length} items`,className:"docker-side-panel"},f.length===0?t(Ff,{title:`暂无 ${u}`,text:"等待 Docker 状态采集"}):t("div",{className:"docker-side-list"},n.map(l),i>0?t("div",{className:"docker-side-more"},`+ ${i} more`):null))}function zp({microservices:u,onRaw:f,onNavigate:l}){let r=u.filter((n)=>aL(n).public===!1);return t("div",{className:"microservice-page","data-testid":"microservice-catalog-page"},t(au,{title:"用户服务目录",eyebrow:"Provider Mounted User Services"},t("div",{className:"metric-grid"},t(cf,{label:"服务总数",value:u.length,hint:"config.json 用户服务登记"}),t(cf,{label:"私有后端",value:r.length,hint:"不直接暴露公网",tone:"ok"}),t(cf,{label:"D601 服务",value:u.filter((n)=>n.providerId==="D601").length,hint:"compute-node docker"}),t(cf,{label:"集成前端",value:u.filter((n)=>n.frontend?.integrated).length,hint:"UniDesk React 页面"}))),t(au,{title:"服务映射",eyebrow:"Repo Reference + Runtime"},u.length===0?t(Ff,{title:"暂无用户服务",text:"在 config.json 的 microservices 中登记用户服务的 provider、仓库引用和后端映射"}):t("div",{className:"table-wrap"},t("table",{className:"microservice-table"},t("thead",null,t("tr",null,t("th",null,"服务"),t("th",null,"Provider"),t("th",null,"代码引用"),t("th",null,"Docker 引用"),t("th",null,"后端映射"),t("th",null,"开发入口"),t("th",null,"运行态"),t("th",null,"操作"))),t("tbody",null,u.map((n)=>{let i=Uw(n),y=gS(n),_=aL(n),$=i.availability||{},A=$.status||(i.providerStatus==="online"?"unknown":"unhealthy");return t("tr",{key:n.id,"data-testid":`microservice-row-${ol(n.id)}`},t("td",null,t("strong",null,n.name),t("code",null,n.id)),t("td",null,t("strong",null,i.providerName||n.providerId),t("code",null,n.providerId)),t("td",null,t("span",null,y.url||"--"),t("code",null,y.commitId||"--")),t("td",null,t("span",null,y.composeFile||"--"),t("code",null,`${y.composeService||"--"} / ${y.containerName||"--"}`)),t("td",null,t(wf,{status:_.public?"warn":"online"},_.public?"public":"private"),t("code",null,`${_.nodeBindHost||"--"}:${_.nodePort||"--"} -> ${_.proxyMode||"--"}`)),t("td",null,t("span",null,n.development?.sshPassthrough?"SSH 透传":"未配置"),t("code",null,n.development?.worktreePath||"--")),t("td",null,t(wf,{status:A==="healthy"?"online":A==="unknown"?"warn":"failed"},A),t("span",null,$.reason||i.providerStatus||"unknown"),t(vn,{data:i.container,empty:"容器快照未上报"})),t("td",null,t("div",{className:"microservice-actions"},n.id==="findjob"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","findjob"),"data-testid":"open-findjob-button"},"打开"):null,n.id==="pipeline"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","pipeline"),"data-testid":"open-pipeline-button"},"打开"):null,n.id==="todo-note"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","todo-note"),"data-testid":"open-todo-note-button"},"打开"):null,n.id==="met-nonlinear"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","met-nonlinear"),"data-testid":"open-met-nonlinear-button"},"打开"):null,n.id==="claudeqq"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","claudeqq"),"data-testid":"open-claudeqq-button"},"打开"):null,n.id==="baidu-netdisk"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","baidu-netdisk"),"data-testid":"open-baidu-netdisk-button"},"打开"):null,n.id==="oa-event-flow"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","oa-event-flow"),"data-testid":"open-oa-event-flow-button"},"打开"):null,n.id==="code-queue"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","code-queue"),"data-testid":"open-code-queue-button"},"打开"):null,n.id==="project-manager"?t("button",{type:"button",className:"ghost-btn",onClick:()=>l("apps","project-manager"),"data-testid":"open-project-manager-button"},"打开"):null,t(bf,{title:`用户服务 ${n.id}`,data:n,onOpen:f}))))}))))))}function Tp({nodes:u,onDispatched:f,onRaw:l}){let r=u.filter((V)=>V.status==="online"),[n,i]=hu(r[0]?.providerId||u[0]?.providerId||""),[y,_]=hu("docker.ps"),[$,A]=hu("frontend"),[c,j]=hu("operator-check"),[F,U]=hu("normal"),[Q,L]=hu(!1),[w,J]=hu(""),[N,q]=hu(!1),[W,z]=hu(null),[Z,H]=hu("");F0(()=>{if(!n&&(r[0]?.providerId||u[0]?.providerId))i(r[0]?.providerId||u[0].providerId)},[u.length,r.length,n]);function E(){return{source:$,note:c,priority:F}}function D(){J(JSON.stringify(E(),null,2)),L(!0)}async function h(V){V.preventDefault(),q(!0),H("");try{let Y=Q?JSON.parse(w||"{}"):E(),p=await Eu(`${gu.apiBaseUrl}/dispatch`,{method:"POST",body:JSON.stringify({providerId:n,command:y,payload:Y})});z(p),await f()}catch(Y){H(Hu(Y,"下发失败"))}finally{q(!1)}}return t("div",{className:"page-grid dispatch-grid"},t(au,{title:"下发任务",eyebrow:"Real WebSocket Dispatch"},t("form",{className:"dispatch-form",onSubmit:h},t("label",null,"Provider",t("select",{value:n,onChange:(V)=>i(V.target.value)},u.map((V)=>t("option",{key:V.providerId,value:V.providerId},`${V.name} / ${V.providerId}`)))),t("label",null,"Command",t("select",{value:y,onChange:(V)=>_(V.target.value)},t("option",{value:"docker.ps"},"docker.ps"),t("option",{value:"host.ssh"},"host.ssh"),t("option",{value:"microservice.http"},"microservice.http"),t("option",{value:"echo"},"echo"))),t("label",null,"来源",t("input",{value:$,onChange:(V)=>A(V.target.value)})),t("label",null,"备注",t("input",{value:c,onChange:(V)=>j(V.target.value)})),t("label",null,"优先级",t("select",{value:F,onChange:(V)=>U(V.target.value)},t("option",{value:"normal"},"normal"),t("option",{value:"low"},"low"),t("option",{value:"urgent"},"urgent"))),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",onClick:D},"查看原始JSON"),t("button",{type:"submit",disabled:N||!n},N?"下发中":"下发任务")),Q?t("label",{className:"raw-editor-label"},"高级 Payload",t("textarea",{className:"raw-editor",value:w,onChange:(V)=>J(V.target.value)})):null,t(yf,{error:Z,wide:!0}))),t(au,{title:"下发结果",eyebrow:"Response"},W?t("div",{className:"result-card"},t(wf,{status:W.status||"queued"},W.status||"queued"),t("dl",null,t("dt",null,"Task ID"),t("dd",null,t("code",null,W.taskId||"--")),t("dt",null,"Provider 在线"),t("dd",null,M1(W.providerOnline))),t(bf,{title:"Dispatch Response",data:W,onOpen:l})):t(Ff,{title:"等待操作",text:"任务响应会以结构化结果卡展示"})))}function fw({task:u,onRaw:f}){return t("article",{className:"compact-row"},t(wf,{status:u.status}),t("div",null,t("strong",null,u.command),t("code",null,u.id)),t("span",null,Ny(u)?`已等待 ${a9(u.updatedAt)}`:`耗时 ${x0(iw(u)??0)}`),t(bf,{title:`Task ${u.id}`,data:M$(u),onOpen:f}))}function Lw({task:u}){let f=iw(u),l=Ny(u);return t("div",{className:"task-duration"},t("strong",null,f===null?"--":x0(f)),t("span",null,l?`已运行 / 创建 ${Nu(u.createdAt)}`:`创建 ${Nu(u.createdAt)}`))}function Ep({task:u}){let f=String(u?.status||"").toLowerCase(),l=u?.result,r=l&&typeof l==="object"&&!Array.isArray(l)?l:{},i=["exitCode","code","signal","timeoutMs","previousStatus","mode"].filter((y)=>r[y]!==void 0&&r[y]!==null);if(f==="failed"){let y=yw(u);return t("div",{className:"task-diagnostic failed"},t("b",null,"失败原因"),t("span",{className:"diagnostic-reason"},M1(y)),i.length>0?t("div",{className:"diagnostic-meta"},i.map((_)=>t("span",{key:_,className:"data-chip"},t("b",null,_),t("span",null,M1(r[_]))))):null)}if(Ny(u))return t("div",{className:"task-diagnostic warn"},t("b",null,"等待终态"),t("span",null,`最后更新 ${a9(u.updatedAt)} 前`));return t("div",{className:"task-diagnostic ok"},t("b",null,"完成摘要"),t(vn,{data:l,empty:"无执行输出"}))}function Zp({tasks:u,onRaw:f}){let l=u.filter(Ny);return t("div",{"data-testid":"pending-task-page"},t(au,{title:"待处理任务",eyebrow:`${l.length} Pending`},l.length===0?t(Ff,{title:"当前无待处理任务",text:"queued / dispatched / running 会在超时后自动转为 failed;历史记录仍可在任务历史中查看"}):t("div",{className:"table-wrap","data-testid":"pending-task-table"},t("table",null,t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"Provider"),t("th",null,"已等待"),t("th",null,"载荷摘要"),t("th",null,"操作"))),t("tbody",null,l.map((r)=>t("tr",{key:r.id},t("td",null,t(wf,{status:r.status})),t("td",null,t("strong",null,r.command),t("code",null,r.id)),t("td",null,t("code",null,r.providerId)),t("td",null,a9(r.updatedAt)),t("td",null,t(vn,{data:r.payload})),t("td",null,t(bf,{title:`Pending Task ${r.id}`,data:M$(r),onOpen:f})))))))))}function Op({tasks:u,onRaw:f}){return t("div",{"data-testid":"task-history-page"},t(au,{title:"任务历史",eyebrow:`${u.length} Tasks`},u.length===0?t(Ff,{title:"暂无任务",text:"下发任务后会在这里看到生命周期"}):t("div",{className:"table-wrap"},t("table",{className:"task-history-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"Provider"),t("th",null,"任务耗时"),t("th",null,"载荷摘要"),t("th",null,"诊断信息"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,u.map((l)=>t("tr",{key:l.id,"data-testid":`task-row-${ol(l.id)}`},t("td",null,t(wf,{status:l.status})),t("td",null,t("strong",null,l.command),t("code",null,l.id)),t("td",null,t("code",null,l.providerId)),t("td",null,t(Lw,{task:l})),t("td",null,t(vn,{data:l.payload})),t("td",null,t(Ep,{task:l})),t("td",null,Nu(l.updatedAt)),t("td",null,t(bf,{title:`Task ${l.id}`,data:M$(l),onOpen:f})))))))))}function Hp({tasks:u,onRaw:f}){let l=u.filter((r)=>["succeeded","failed"].includes(r.status));return t(au,{title:"执行结果",eyebrow:"Finished Tasks"},l.length===0?t(Ff,{title:"暂无结果",text:"任务完成后展示 provider 返回的结构化摘要"}):t("div",{className:"result-grid"},l.map((r)=>t("article",{key:r.id,className:"result-card"},t("div",{className:"node-card-head"},t("strong",null,r.command),t(wf,{status:r.status})),t("code",null,r.id),t(vn,{data:r.result,empty:"无执行输出"}),t(bf,{title:`Task Result ${r.id}`,data:M$(r),onOpen:f})))))}function Bp(u){if(!u||typeof u!=="object")return"--";if(u.type==="interval")return`每 ${x0(Number(u.everySeconds||0))}`;return`每天 ${u.timeOfDay||"03:00"} UTC`}function Vp(u){if(!u||typeof u!=="object")return"--";if(u.type==="pgdata_backup")return`PGDATA -> ${u.remoteBaseDir||"/SERVER_DATA/UNIDESK_PG_DATA"}`;if(u.type==="dispatch")return`${u.providerId||"--"} / ${u.command||"--"}`;return String(u.type||"--")}function Dp(u){let f=String(u||"").toLowerCase();if(f==="succeeded")return"online";if(f==="failed")return"failed";if(f==="running"||f==="queued")return"warn";return f}function Xp(u){let f=Number(u?.durationMs);if(Number.isFinite(f)&&f>=0)return x0(f/1000);let l=J0(u?.startedAt||u?.createdAt);if(l===null)return"--";let n=J0(u?.finishedAt)??Date.now();return x0(Math.max(0,(n-l)/1000))}function lw(u){return{id:"unidesk-pgdata-baidu-daily",name:"PGDATA daily Baidu Netdisk backup",description:"Daily PostgreSQL physical base backup uploaded to Baidu Netdisk /SERVER_DATA with monthly rotation.",enabled:!0,timeOfDay:"03:30",actionType:"pgdata_backup",providerId:u[0]?.providerId||"main-server",command:"echo",payloadJson:JSON.stringify({source:"scheduled-task",message:"hello from scheduler"},null,2),remoteBaseDir:"/SERVER_DATA/UNIDESK_PG_DATA",stagingSubdir:"server-data/unidesk-pg-data",timeoutMs:"3600000"}}function Yp({schedules:u,scheduleRuns:f,nodes:l,refresh:r,onRaw:n}){let[i,y]=hu(lw(l||[])),[_,$]=hu(!1),[A,c]=hu(""),[j,F]=hu(""),U=[...f||[]].sort((W,z)=>(J0(z.updatedAt)??0)-(J0(W.updatedAt)??0));function Q(W,z){y((Z)=>({...Z,[W]:z}))}function L(W){let z=W?.action||{};y({id:W?.id||"",name:W?.name||"",description:W?.description||"",enabled:W?.enabled!==!1,timeOfDay:W?.schedule?.timeOfDay||"03:30",actionType:z.type||"dispatch",providerId:z.providerId||l[0]?.providerId||"main-server",command:z.command||"echo",payloadJson:JSON.stringify(z.payload||{source:"scheduled-task"},null,2),remoteBaseDir:z.remoteBaseDir||"/SERVER_DATA/UNIDESK_PG_DATA",stagingSubdir:z.stagingSubdir||"server-data/unidesk-pg-data",timeoutMs:String(z.timeoutMs||3600000)}),F(`正在编辑 ${W?.id||""}`)}function w(){let W={id:i.id,name:i.name,description:i.description,enabled:i.enabled,concurrencyPolicy:"skip",schedule:{type:"daily",timeOfDay:i.timeOfDay,timezone:"Etc/UTC"}};if(i.actionType==="pgdata_backup")return{...W,action:{type:"pgdata_backup",volumeName:"unidesk_pgdata_10gb",remoteBaseDir:i.remoteBaseDir,stagingSubdir:i.stagingSubdir,timeoutMs:Number(i.timeoutMs)||3600000,cleanupLocal:!0}};return{...W,action:{type:"dispatch",providerId:i.providerId,command:i.command,payload:JSON.parse(i.payloadJson||"{}"),timeoutMs:Number(i.timeoutMs)||600000}}}async function J(W){W.preventDefault(),$(!0),c(""),F("");try{let z=w(),Z=encodeURIComponent(String(z.id));await Eu(`${gu.apiBaseUrl}/schedules/${Z}`,{method:"PUT",body:JSON.stringify(z)}),F("定时任务已保存"),await r()}catch(z){c(Hu(z,"保存定时任务失败"))}finally{$(!1)}}async function N(W){if(!W?.id)return;$(!0),c(""),F("");try{await Eu(`${gu.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}`,{method:"DELETE"}),F(`已删除 ${W.id}`),await r()}catch(z){c(Hu(z,"删除定时任务失败"))}finally{$(!1)}}async function q(W){if(!W?.id)return;$(!0),c(""),F("");try{let z=await Eu(`${gu.apiBaseUrl}/schedules/${encodeURIComponent(W.id)}/run`,{method:"POST",body:"{}"});F(`已触发 ${W.id} / ${z?.run?.id||"run"}`),await r()}catch(z){c(Hu(z,"触发定时任务失败"))}finally{$(!1)}}return t("div",{className:"page-grid scheduled-task-page","data-testid":"scheduled-task-page"},t(au,{title:"定时任务",eyebrow:`${(u||[]).length} Schedules`},(u||[]).length===0?t(Ff,{title:"暂无定时任务",text:"创建 daily / dispatch / PGDATA backup 任务后会在这里展示下一次执行时间和最近结果"}):t("div",{className:"schedule-card-grid"},(u||[]).map((W)=>t("article",{key:W.id,className:"schedule-card","data-testid":`schedule-row-${ol(W.id)}`},t("div",{className:"node-card-head"},t("strong",null,W.name||W.id),t(wf,{status:W.enabled?"online":"warn"},W.enabled?"enabled":"disabled")),t("code",null,W.id),t("dl",null,t("dt",null,"计划"),t("dd",null,Bp(W.schedule)),t("dt",null,"动作"),t("dd",null,Vp(W.action)),t("dt",null,"下次执行"),t("dd",null,Nu(W.nextRunAt)),t("dt",null,"最近执行"),t("dd",null,W.lastRunAt?`${Nu(W.lastRunAt)} / ${W.lastRunId||"--"}`:"--")),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>L(W)},"编辑"),t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>q(W),"data-testid":`schedule-run-${ol(W.id)}`},"手动触发"),t("button",{type:"button",className:"ghost-btn danger",disabled:_,onClick:()=>N(W)},"删除"),t(bf,{title:`Schedule ${W.id}`,data:W,onOpen:n})))))),t(au,{title:i.id?"配置定时任务":"新建定时任务",eyebrow:"CRUD"},t("form",{className:"dispatch-form schedule-form",onSubmit:J},t("label",null,"ID",t("input",{value:i.id,onChange:(W)=>Q("id",W.target.value)})),t("label",null,"名称",t("input",{value:i.name,onChange:(W)=>Q("name",W.target.value)})),t("label",null,"每日执行时间 UTC",t("input",{value:i.timeOfDay,placeholder:"03:30",onChange:(W)=>Q("timeOfDay",W.target.value)})),t("label",null,"启用",t("select",{value:i.enabled?"true":"false",onChange:(W)=>Q("enabled",W.target.value==="true")},t("option",{value:"true"},"enabled"),t("option",{value:"false"},"disabled"))),t("label",null,"动作类型",t("select",{value:i.actionType,onChange:(W)=>Q("actionType",W.target.value)},t("option",{value:"pgdata_backup"},"PGDATA 备份到百度网盘"),t("option",{value:"dispatch"},"Provider Dispatch"))),i.actionType==="pgdata_backup"?[t("label",{key:"remote"},"网盘根目录",t("input",{value:i.remoteBaseDir,onChange:(W)=>Q("remoteBaseDir",W.target.value)})),t("label",{key:"staging"},"本地 staging 子目录",t("input",{value:i.stagingSubdir,onChange:(W)=>Q("stagingSubdir",W.target.value)}))]:[t("label",{key:"provider"},"Provider",t("select",{value:i.providerId,onChange:(W)=>Q("providerId",W.target.value)},(l||[]).map((W)=>t("option",{key:W.providerId,value:W.providerId},`${W.name} / ${W.providerId}`)))),t("label",{key:"command"},"Command",t("select",{value:i.command,onChange:(W)=>Q("command",W.target.value)},t("option",{value:"echo"},"echo"),t("option",{value:"docker.ps"},"docker.ps"),t("option",{value:"host.ssh"},"host.ssh"),t("option",{value:"microservice.http"},"microservice.http"))),t("label",{key:"payload",className:"raw-editor-label"},"Payload JSON",t("textarea",{className:"raw-editor",value:i.payloadJson,onChange:(W)=>Q("payloadJson",W.target.value)}))],t("label",null,"超时 ms",t("input",{value:i.timeoutMs,onChange:(W)=>Q("timeoutMs",W.target.value)})),t("label",{className:"raw-editor-label"},"描述",t("textarea",{className:"raw-editor compact",value:i.description,onChange:(W)=>Q("description",W.target.value)})),t("div",{className:"dispatch-actions"},t("button",{type:"button",className:"ghost-btn",disabled:_,onClick:()=>y(lw(l||[]))},"重置"),t("button",{type:"submit",disabled:_||!i.id},_?"保存中":"保存任务")),j?t("p",{className:"muted paragraph"},j):null,t(yf,{error:A,wide:!0}))),t(au,{title:"历史执行记录",eyebrow:`${U.length} Runs`},U.length===0?t(Ff,{title:"暂无执行记录",text:"定时触发或手动触发后会生成 run history"}):t("div",{className:"table-wrap"},t("table",{className:"task-history-table schedule-run-table"},t("thead",null,t("tr",null,t("th",null,"状态"),t("th",null,"任务"),t("th",null,"触发"),t("th",null,"耗时"),t("th",null,"结果摘要"),t("th",null,"更新时间"),t("th",null,"操作"))),t("tbody",null,U.map((W)=>t("tr",{key:W.id,"data-testid":`schedule-run-row-${ol(W.id)}`},t("td",null,t(wf,{status:Dp(W.status)},W.status)),t("td",null,t("strong",null,W.scheduleId),t("code",null,W.id),W.taskId?t("code",null,W.taskId):null),t("td",null,W.trigger||"--"),t("td",null,Xp(W)),t("td",null,t(vn,{data:W.result||W.error,empty:"无结果"})),t("td",null,Nu(W.updatedAt)),t("td",null,t(bf,{title:`Schedule Run ${W.id}`,data:W,onOpen:n})))))))))}function Sp({data:u}){let f=u.overview||{};return t("div",{className:"page-grid topology-grid"},t(au,{title:"公开入口",eyebrow:"Public"},t("div",{className:"endpoint-list"},t("article",null,t("b",null,"Frontend"),t("span",null,gu.frontendPublicUrl||window.location.origin),t(wf,{status:"online"},"public")),t("article",null,t("b",null,"Provider Ingress"),t("span",null,gu.providerIngressPublicUrl||"ws://public/ws/provider"),t(wf,{status:"online"},"public")))),t(au,{title:"内部服务",eyebrow:"Docker Network Only"},t("div",{className:"endpoint-list"},t("article",null,t("b",null,"backend-core API"),t("span",null,"http://backend-core:8080"),t(wf,{status:"internal"},"internal")),t("article",null,t("b",null,"database"),t("span",null,"postgres://database:5432/unidesk"),t(wf,{status:"internal"},"internal")))),t(au,{title:"运行态",eyebrow:"Runtime"},t("div",{className:"metric-grid"},t(cf,{label:"DB Ready",value:f.dbReady?"YES":"NO",hint:"internal health"}),t(cf,{label:"Online Nodes",value:f.onlineNodeCount??0,hint:"provider-gateway self-link"}))))}function pp({session:u}){return t(au,{title:"认证策略",eyebrow:"Frontend Login"},t("div",{className:"policy-grid"},t("article",null,t("span",null,"默认账号"),t("strong",null,gu.authUsername||"admin")),t("article",null,t("span",null,"当前会话"),t("strong",null,u?.user?.username||"--")),t("article",null,t("span",null,"Session TTL"),t("strong",null,`${gu.sessionTtlSeconds||0}s`)),t("article",null,t("span",null,"API 访问"),t("strong",null,"同源 Cookie 保护"))),t("p",{className:"muted paragraph"},"浏览器只访问 frontend 同源接口;frontend 容器使用 Docker 内网代理 backend-core API。"))}function mp(){return t(au,{title:"安全边界",eyebrow:"Exposure Rule"},t("div",{className:"security-board"},t("article",{className:"allow"},t("b",null,"允许公网"),t("span",null,"frontend 登录入口"),t("span",null,"provider ingress WebSocket/health")),t("article",{className:"deny"},t("b",null,"禁止公网"),t("span",null,"backend-core REST API"),t("span",null,"PostgreSQL database")),t("article",null,t("b",null,"数据库卷"),t("span",null,"named volume unidesk_pgdata_10gb"),t("span",null,"CLI stop/start 不删除数据卷"))))}function Pp({activeModule:u,activeTab:f,data:l,session:r,refresh:n,onRaw:i,onNavigate:y}){if(u==="ops"&&f==="status")return t(fp,{data:l,onRaw:i,onNavigate:y});if(u==="ops"&&f==="performance")return t(Qp,{onRaw:i});if(u==="ops"&&f==="events")return t(rp,{events:l.events,onRaw:i});if(u==="ops"&&f==="logs")return t(np,{logs:l.logs,onRaw:i});if(u==="nodes"&&f==="list")return t(ip,{nodes:l.nodes,onRaw:i});if(u==="nodes"&&f==="monitor")return t($p,{nodes:l.nodes,systemStatuses:l.systemStatuses,tasks:l.tasks,onRaw:i,refresh:n});if(u==="nodes"&&f==="docker")return t(Kp,{nodes:l.nodes,dockerStatuses:l.dockerStatuses,onRaw:i});if(u==="nodes"&&f==="gateway")return t(Wp,{nodes:l.nodes,tasks:l.tasks,onRaw:i});if(u==="nodes"&&f==="labels")return t(yp,{nodes:l.nodes});if(u==="nodes"&&f==="heartbeats")return t(_p,{nodes:l.nodes});if(u==="tasks"&&f==="dispatch")return t(Tp,{nodes:l.nodes,onDispatched:n,onRaw:i});if(u==="tasks"&&f==="scheduled")return t(Yp,{schedules:l.schedules,scheduleRuns:l.scheduleRuns,nodes:l.nodes,refresh:n,onRaw:i});if(u==="tasks"&&f==="pending")return t(Zp,{tasks:l.pendingTasks,onRaw:i});if(u==="tasks"&&f==="history")return t(Op,{tasks:l.tasks,onRaw:i});if(u==="tasks"&&f==="results")return t(Hp,{tasks:l.tasks,onRaw:i});if(u==="apps"&&f==="catalog")return t(zp,{microservices:l.microservices,onRaw:i,onNavigate:y});if(u==="apps"&&f==="todo-note")return t(RL,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="findjob")return t(YQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="pipeline")return t(XL,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="met-nonlinear")return t(MQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="claudeqq")return t(tU,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="baidu-netdisk")return t(yU,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="filebrowser")return t(XQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="oa-event-flow")return t(kQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="apps"&&f==="code-queue")return t(ZQ,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl,initialTasksData:mS});if(u==="apps"&&f==="project-manager")return t(pL,{microservices:l.microservices,onRaw:i,apiBaseUrl:gu.apiBaseUrl});if(u==="config"&&f==="topology")return t(Sp,{data:l});if(u==="config"&&f==="auth")return t(pp,{session:r});if(u==="config"&&f==="security")return t(mp);return t(Ff,{title:"未找到页面",text:"请选择左侧主模块和顶部子功能标签"})}function Mp({session:u,onLogout:f}){let l=yA(Vr,window.location.pathname),[r,n]=hu(l.moduleId),[i,y]=hu({...b_,[l.moduleId]:l.tabId}),[_,$]=hu({overview:null,nodes:[],systemStatuses:[],dockerStatuses:[],microservices:[],events:[],tasks:[],pendingTasks:[],schedules:[],scheduleRuns:[],logs:[]}),[A,c]=hu({ok:!1,text:"连接中"}),[j,F]=hu(null),[U,Q]=hu(new Date),[L,w]=hu(null),[J,N]=hu(!1),[q,W]=hu(!1),z=bn.default.useRef(!1),Z=Vr.moduleById[r]||Vr.modules[0],H=i[r]||b_[r]||Z.tabs[0].id,E=Array.isArray(_.microservices)?_.microservices:[],D=E.length===0&&r==="apps"&&H==="code-queue"?[PS]:E,h=D===E?_:{..._,microservices:D},V=r==="apps"?D.find((o)=>String(o?.id||"")===H):null,Y=V?Uw(V):{},p=Z.tabs.find((o)=>o.id===H)?.label||H,O=V?[{key:"microservice",label:"用户服务",value:`${p} ${Y.providerStatus==="online"?"在线":Y.providerStatus||"未知"}`,tone:Y.providerStatus==="online"?"ok":"warn",testId:"active-microservice-status"}]:[];async function m(){if(z.current)return;z.current=!0,W(!0);try{let o=[],s=(ju,Gu)=>{o.push([ju,Eu(Gu)])},x=r==="ops"&&H==="status",fu=x||r==="config"&&H==="topology",$u=x||r==="nodes"||r==="tasks"&&(H==="dispatch"||H==="scheduled"),tu=r==="apps"&&H!=="code-queue";if(fu)s("overview",`${gu.apiBaseUrl}/overview`);if($u)s("nodes",`${gu.apiBaseUrl}/nodes`);if(r==="nodes"&&H==="monitor")s("systemStatuses",`${gu.apiBaseUrl}/nodes/system-status?limit=60`),s("tasks",`${gu.apiBaseUrl}/tasks?limit=120&summary=1`);else if(r==="nodes"&&H==="docker")s("dockerStatuses",`${gu.apiBaseUrl}/nodes/docker-status`);else if(r==="nodes"&&H==="gateway")s("tasks",`${gu.apiBaseUrl}/tasks?limit=300&summary=1`);else if(r==="tasks"&&H==="scheduled")s("schedules",`${gu.apiBaseUrl}/schedules?limit=100`),s("scheduleRuns",`${gu.apiBaseUrl}/schedules/runs?limit=100`);else if(r==="tasks"&&H==="pending")s("pendingTasks",`${gu.apiBaseUrl}/tasks?status=pending&limit=100&summary=1`);else if(r==="tasks"&&(H==="history"||H==="results"))s("tasks",`${gu.apiBaseUrl}/tasks?limit=300&summary=1`);else if(x)s("tasks",`${gu.apiBaseUrl}/tasks?limit=8&lite=1`),s("pendingTasks",`${gu.apiBaseUrl}/tasks?status=pending&limit=20&lite=1`);if(tu)s("microservices",`${gu.apiBaseUrl}/microservices`);if(r==="ops"&&H==="events")s("events",`${gu.apiBaseUrl}/events?limit=100`);if(r==="ops"&&H==="logs")s("logs","/logs?limit=100");await Promise.all(o.map(async([ju,Gu])=>{let qu=await Gu,P={};if(ju==="overview")P.overview=qu;if(ju==="nodes")P.nodes=qu.nodes||[];if(ju==="systemStatuses")P.systemStatuses=qu.systemStatuses||[];if(ju==="dockerStatuses")P.dockerStatuses=qu.dockerStatuses||[];if(ju==="microservices")P.microservices=qu.microservices||[];if(ju==="events")P.events=qu.events||[];if(ju==="tasks")P.tasks=qu.tasks||[];if(ju==="pendingTasks")P.pendingTasks=qu.tasks||[];if(ju==="schedules")P.schedules=qu.schedules||[];if(ju==="scheduleRuns")P.scheduleRuns=qu.runs||[];if(ju==="logs")P.logs=qu.logs||[];$((e)=>({...e,...P}))})),c({ok:!0,text:"核心在线"}),F(new Date)}catch(o){if(c({ok:!1,text:Hu(o,"连接失败")}),o.status===401)f(!1)}finally{z.current=!1,W(!1)}}F0(()=>{let o=()=>{if(!IL())return;m()};o();let s=setInterval(o,MS(r,H)),x=()=>{if(IL())o()};return document.addEventListener("visibilitychange",x),()=>{clearInterval(s),document.removeEventListener("visibilitychange",x)}},[r,H]),F0(()=>{let o=setInterval(()=>Q(new Date),1000);return()=>clearInterval(o)},[]),F0(()=>{let o=hQ(Vr,window.location.pathname);if(o&&window.location.pathname!==o)window.history.replaceState(null,"",o)},[]),F0(()=>{let o=()=>{let s=yA(Vr,window.location.pathname);n(s.moduleId),y((x)=>({...x,[s.moduleId]:s.tabId})),w(null)};return window.addEventListener("popstate",o),()=>window.removeEventListener("popstate",o)},[]),F0(()=>{window.scrollTo({top:0,left:0,behavior:"auto"})},[r,H]);function X(o,s,x="push"){let fu=Vr.moduleById[o]?o:Vr.fallbackTarget.moduleId,$u=Vr.moduleById[fu]?.tabs.some((ju)=>ju.id===s)?s:b_[fu]||Vr.moduleById[fu]?.tabs[0]?.id||Vr.fallbackTarget.tabId;n(fu),y((ju)=>({...ju,[fu]:$u}));let tu=f6(Vr,fu,$u);if(window.location.pathname!==tu){let ju=x==="replace"?"replaceState":"pushState";window.history[ju](null,"",tu)}}function v(o,s){w({title:o,data:s})}let[T,S]=hu(!1),{unreadCount:k,notifications:I}=Vl(),b=I.length>0?I[I.length-1]:null;return t("div",{className:`shell ${J?"rail-collapsed":""}`,"data-testid":"app-shell"},t(eS,{activeModule:r,activeTabs:i,onNavigate:X,collapsed:J,onToggle:()=>N((o)=>!o)}),t("main",{className:"workspace"},t(oS,{connection:A,lastRefresh:j,onRefresh:m,onLogout:()=>f(!0),session:u,clock:U,activeStatusItems:O,onNotificationToggle:()=>S((o)=>!o),unreadCount:k}),t(up,{module:Z,activeTab:H,onNavigate:X}),t(s9.Provider,{value:q},t(Pp,{activeModule:r,activeTab:H,data:h,session:u,refresh:m,onRaw:v,onNavigate:X}))),t(sS,{raw:L,onClose:()=>w(null)}),b&&t(kL,{key:b.id,notification:b}),T&&t(vL,{onClose:()=>S(!1)}))}function Cp(){let[u,f]=hu(!0),[l,r]=hu(null);async function n(){f(!0);try{let y=await Eu("/api/session");r(y.authenticated?y:null)}catch{r(null)}finally{f(!1)}}async function i(y){if(y)try{await Eu("/logout",{method:"POST"})}catch{}r(null)}if(F0(()=>{n()},[]),u)return t("main",{className:"loading-screen"},t("div",{className:"brand-mark"},"UD"),t("span",null,"加载会话"));if(!l)return t(aS,{onLogin:r});return t(iU,null,t(Mp,{session:l,onLogout:i}))}var ww=document.getElementById("root");if(ww===null)throw Error("root element not found");rw.createRoot(ww).render(t(Cp));})(); diff --git a/src/components/frontend/public/style.css b/src/components/frontend/public/style.css index b1d7e9c0..643e1c67 100644 --- a/src/components/frontend/public/style.css +++ b/src/components/frontend/public/style.css @@ -3181,6 +3181,15 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent-2); } color: var(--accent-2); white-space: nowrap; } +.codex-trace-step-inline-summary { + min-width: 80px; + flex: 1 1 180px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: #a7c7c3; + font-size: 11px; +} .codex-trace-step.error > summary .codex-output-channel { color: var(--danger); border-color: rgba(207, 106, 84, 0.52); diff --git a/src/components/frontend/src/code-queue.tsx b/src/components/frontend/src/code-queue.tsx index 7f4f0972..187dfbf7 100644 --- a/src/components/frontend/src/code-queue.tsx +++ b/src/components/frontend/src/code-queue.tsx @@ -655,6 +655,40 @@ function objectRecord(value: any): AnyRecord | null { return value && typeof value === "object" && !Array.isArray(value) ? value : null; } +function judgeFailureDetailsText(judge: any): string { + const raw = objectRecord(judge?.raw); + const details = objectRecord(judge?.failureDetails) || objectRecord(raw?.minimaxFailure); + if (details === null) return ""; + const repairAttempt = details.repairAttempt === undefined ? "" : `${details.repairAttempt}/${details.maxRepairAttempts ?? "?"}`; + const rows = [ + ["provider", details.provider || "minimax"], + ["stage", details.stage], + ["model", details.model], + ["timedOut", details.timedOut], + ["durationMs", details.durationMs], + ["timeoutMs", details.timeoutMs], + ["promptChars", details.promptChars], + ["promptLines", details.promptLines], + ["payloadBytes", details.payloadBytes], + ["responseStatus", details.responseStatus], + ["repairAttempt", repairAttempt], + ["errorName", details.errorName], + ["error", details.errorMessage], + ["responseContentPreview", details.responseContentPreview], + ["responseTextPreview", details.responseTextPreview], + ].filter(([, value]) => value !== undefined && value !== null && String(value).length > 0); + return rows.map(([key, value]) => `${key}: ${String(value)}`).join("\n"); +} + +function JudgeFailureDetails({ judge, testId = "codex-judge-failure-details" }: AnyRecord) { + const text = judgeFailureDetailsText(judge); + if (text.length === 0) return null; + return h("details", { className: "codex-judge-failure-details", "data-testid": testId }, + h("summary", null, "MiniMax failure details"), + h("pre", null, text), + ); +} + function taskProgressiveAttempts(task: any): any[] { const summaryAttempts = taskTraceSummary(task)?.attempts; if (Array.isArray(summaryAttempts) && summaryAttempts.length > 0) return summaryAttempts; @@ -1214,6 +1248,8 @@ function codexProviderOptions(queue: any, currentProviderId: string): any[] { id: String(item?.id || "").trim(), label: String(item?.label || item?.id || "").trim(), defaultWorkdir: String(item?.defaultWorkdir || "").trim(), + supportsWindowsNativeCodex: item?.supportsWindowsNativeCodex === true, + windowsNativeDefaultWorkdir: String(item?.windowsNativeDefaultWorkdir || "").trim(), kind: String(item?.kind || "").trim(), })) .filter((item: any) => item.id.length > 0); @@ -1221,14 +1257,44 @@ function codexProviderOptions(queue: any, currentProviderId: string): any[] { const byId = new Map(); for (const item of [ ...rows, - { id: fallbackMain, label: `${fallbackMain} (master)`, defaultWorkdir: String(queue?.defaultWorkdir || "/root/unidesk"), kind: "local" }, - currentProviderId ? { id: currentProviderId, label: currentProviderId, defaultWorkdir: providerDefaultWorkdir(queue, currentProviderId), kind: "" } : null, + { id: fallbackMain, label: `${fallbackMain} (master)`, defaultWorkdir: String(queue?.defaultWorkdir || "/root/unidesk"), supportsWindowsNativeCodex: false, windowsNativeDefaultWorkdir: "", kind: "local" }, + currentProviderId ? { id: currentProviderId, label: currentProviderId, defaultWorkdir: providerDefaultWorkdir(queue, currentProviderId), supportsWindowsNativeCodex: currentProviderId !== fallbackMain, windowsNativeDefaultWorkdir: String(queue?.windowsNativeCodexDefaultWorkdir || "/mnt/f/Work/ConStart"), kind: "" } : null, ].filter(Boolean) as any[]) { if (!byId.has(item.id)) byId.set(item.id, item); } return Array.from(byId.values()); } +function codexExecutionModeOptions(queue: any, currentMode: string): any[] { + const configured = Array.isArray(queue?.executionModes) ? queue.executionModes : []; + const rows = configured + .map((item: any) => ({ + id: String(item?.id || item?.kind || "").trim(), + label: String(item?.label || item?.id || item?.kind || "").trim(), + description: String(item?.description || "").trim(), + defaultWorkdir: String(item?.defaultWorkdir || "").trim(), + requiresProvider: item?.requiresProvider === true, + requiresWindowsCwd: item?.requiresWindowsCwd === true, + })) + .filter((item: any) => item.id.length > 0); + const fallback = [ + { id: "default", label: "默认容器/本机", description: "主 server 用本机 Codex;远程 Provider 用执行容器 Codex。", defaultWorkdir: "", requiresProvider: false, requiresWindowsCwd: false }, + { id: "windows-native", label: "Windows 原生 Codex", description: "启动执行容器,但容器只做 stdio relay,Codex 运行在 Provider 的 Windows 宿主。", defaultWorkdir: String(queue?.windowsNativeCodexDefaultWorkdir || "/mnt/f/Work/ConStart"), requiresProvider: true, requiresWindowsCwd: true }, + ]; + const byId = new Map(); + for (const item of [...rows, ...fallback, currentMode ? { id: currentMode, label: currentMode, description: "", defaultWorkdir: "", requiresProvider: currentMode === "windows-native", requiresWindowsCwd: currentMode === "windows-native" } : null].filter(Boolean) as any[]) { + if (!byId.has(item.id)) byId.set(item.id, item); + } + return Array.from(byId.values()); +} + +function executionModeDefaultWorkdir(queue: any, mode: string, providerId: string): string { + if (mode !== "windows-native") return providerDefaultWorkdir(queue, providerId); + const option = Array.isArray(queue?.executionModes) ? queue.executionModes.find((item: any) => String(item?.id || item?.kind || "") === "windows-native") : null; + const provider = Array.isArray(queue?.executionProviders) ? queue.executionProviders.find((item: any) => String(item?.id || "") === providerId) : null; + return String(provider?.windowsNativeDefaultWorkdir || option?.defaultWorkdir || queue?.windowsNativeCodexDefaultWorkdir || "/mnt/f/Work/ConStart"); +} + function providerDefaultWorkdir(queue: any, providerId: string): string { const id = String(providerId || "").trim(); const map = queue?.defaultWorkdirByProvider && typeof queue.defaultWorkdirByProvider === "object" ? queue.defaultWorkdirByProvider : {}; @@ -1310,6 +1376,7 @@ function TaskCard({ task, selected, onSelect, onCopy, onReference, onMarkRead, c h("div", { className: "codex-task-meta" }, h("span", null, `queue=${taskQueueLabel(task)}`), h("span", null, `provider=${task?.providerId || "main-server"}`), + h("span", null, `mode=${task?.executionMode || "default"}`), h("span", null, task?.model || "--"), h("span", null, taskDurationLabel(task)), ), @@ -1622,6 +1689,7 @@ function ProgressiveExecutionSummary({ task, attempt, attemptIndex, loading, onL const seq = String(step?.seq ?? ""); const detail = stepDetails[seq]; const summaryLines = Array.isArray(step?.summaryLines) ? step.summaryLines.slice(0, 4) : []; + const inlineSummary = summaryLines.find((line: any) => String(line || "").trim().length > 0); return h("details", { key: seq || `${step?.title}-${step?.at}`, className: `codex-trace-step ${String(step?.kind || "message")} ${traceStepIsError(step) ? "error" : ""}`, @@ -1634,6 +1702,7 @@ function ProgressiveExecutionSummary({ task, attempt, attemptIndex, loading, onL h("span", { className: "codex-output-channel" }, traceStepKindLabel(step?.kind)), h("strong", null, String(step?.title || "Trace step")), step?.status ? h("code", null, String(step.status)) : null, + inlineSummary ? h("span", { className: "codex-trace-step-inline-summary", title: String(inlineSummary) }, String(inlineSummary)) : null, h("time", null, fmtDate(step?.at)), ), h("div", { className: "codex-trace-step-summary" }, @@ -1695,6 +1764,7 @@ function ProgressiveJudge({ task, attempt, attemptIndex, testId = "codex-progres h(StatusBadge, { status: judge.decision }, judge.decision), h("strong", null, `${Math.round(Number(judge.confidence || 0) * 100)}% confidence`), h("p", { "data-testid": `${testId}-reason` }, judge.reason || "--"), + h(JudgeFailureDetails, { judge, testId: `${testId}-failure-details` }), judge.continuePrompt ? h("pre", { "data-testid": `${testId}-continue-prompt` }, String(judge.continuePrompt || "")) : null, ), ); @@ -1889,6 +1959,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi const [mergeDialogOpen, setMergeDialogOpen] = useState(false); const [mergeSourceQueueId, setMergeSourceQueueId] = useState(""); const [providerId, setProviderId] = useState("main-server"); + const [executionMode, setExecutionMode] = useState("default"); const [model, setModel] = useState("gpt-5.5"); const [cwd, setCwd] = useState("/root/unidesk"); const [maxAttempts, setMaxAttempts] = useState(99); @@ -1967,7 +2038,8 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi const submitDisabled = submitting || busy || enqueueCount === 0 || batchNeedsConfirmation; const codexModels = codexModelOptions(queue, model); const providerOptions = codexProviderOptions(queue, providerId); - const currentProviderDefaultWorkdir = providerDefaultWorkdir(queue, providerId); + const executionModeRows = codexExecutionModeOptions(queue, executionMode); + const currentProviderDefaultWorkdir = executionModeDefaultWorkdir(queue, executionMode, providerId); const selectedCanSteer = selectedTask?.id && selectedTask?.activeTurnId && String(selectedTask?.status) === "running"; const selectedCanInterrupt = selectedTask?.id && !["succeeded", "failed", "canceled"].includes(String(selectedTask?.status || "")); const selectedCanRetry = selectedTask?.id && ["succeeded", "failed", "canceled"].includes(String(selectedTask?.status || "")); @@ -2038,7 +2110,21 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi function changeSubmitProvider(nextProviderId: string): void { const next = String(nextProviderId || queue?.mainProviderId || "main-server").trim() || "main-server"; setProviderId(next); - setCwd(providerDefaultWorkdir(queue, next)); + setCwd(executionModeDefaultWorkdir(queue, executionMode, next)); + } + + function changeSubmitExecutionMode(nextMode: string): void { + const next = String(nextMode || "default").trim() || "default"; + let nextProvider = providerId; + if (next === "windows-native") { + const current = providerOptions.find((provider: any) => provider.id === providerId); + if (!current?.supportsWindowsNativeCodex) { + nextProvider = String(providerOptions.find((provider: any) => provider.supportsWindowsNativeCodex)?.id || providerId || "D601"); + setProviderId(nextProvider); + } + } + setExecutionMode(next); + setCwd(executionModeDefaultWorkdir(queue, next, nextProvider)); } function patchLoadedReadState(taskIds: string[], readAt: string, queuePatch: any = null, taskPatch: any = null): void { @@ -2872,6 +2958,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi prompt: text, queueId: submitQueueId, providerId, + executionMode, model, cwd, maxAttempts: Number(maxAttempts), @@ -3298,6 +3385,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi h("span", { className: `codex-trace-status-chip unread ${overallUnreadTerminalCount > 0 ? "warn" : ""}` }, h("b", null, "结束未读"), String(overallUnreadTerminalCount)), h("span", { className: "codex-trace-status-chip service" }, h("b", null, "服务"), `${runtime.providerStatus || "unknown"} · ${service?.providerId || "main-server"} · ${backend.public ? "公网暴露" : "仅 UniDesk frontend 代理访问"}`), h("span", { className: "codex-trace-status-chip" }, h("b", null, "执行节点"), providerOptions.map((provider: any) => provider.id).join(" / ")), + h("span", { className: "codex-trace-status-chip" }, h("b", null, "执行模式"), executionModeRows.map((mode: any) => mode.id).join(" / ")), h("span", { className: "codex-trace-status-chip" }, h("b", null, "模型"), codexModels.join(" / ")), h("span", { className: "codex-trace-status-chip" }, h("b", null, "加载"), loadStats?.phase === "complete" ? fmtPreciseMs(loadStats?.totalMs) : String(loadStats?.phase || "idle")), h("span", { className: "codex-trace-status-chip" }, h("b", null, "刷新"), refreshedAt ? fmtClock(refreshedAt) : "--"), @@ -3305,7 +3393,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi const sessionPanel = h(Panel, { title: selectedTask ? `Trace ${String(selectedTask.id).slice(0, 22)}` : "Trace 输出", - eyebrow: selectedTask ? `${selectedTask.status} / view=${selectedQueueName} / task queue=${taskQueueLabel(selectedTask)} / provider=${selectedTask.providerId || "main-server"} / ${selectedTask.model} / agent loop trace` : `Agent loop trace / view=${selectedQueueName}`, + eyebrow: selectedTask ? `${selectedTask.status} / view=${selectedQueueName} / task queue=${taskQueueLabel(selectedTask)} / provider=${selectedTask.providerId || "main-server"} / mode=${selectedTask.executionMode || "default"} / ${selectedTask.model} / agent loop trace` : `Agent loop trace / view=${selectedQueueName}`, summary: traceStatusSummary, loading: selectedDetailLoading || loadingMoreTasks || searchLoading || searchLoadingMoreTasks || loadStats?.phase === "loading", actions: h("div", { className: "panel-actions" }, @@ -3433,7 +3521,12 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi ), h("label", null, "执行 Provider", h("select", { value: providerId, disabled: submitting, onChange: (event: any) => changeSubmitProvider(String(event.target.value || "main-server")), "data-testid": "codex-provider-select" }, - providerOptions.map((provider: any) => h("option", { key: provider.id, value: provider.id }, `${provider.label || provider.id} · ${provider.defaultWorkdir || providerDefaultWorkdir(queue, provider.id)}`)), + providerOptions.map((provider: any) => h("option", { key: provider.id, value: provider.id }, `${provider.label || provider.id} · ${provider.defaultWorkdir || providerDefaultWorkdir(queue, provider.id)}${provider.supportsWindowsNativeCodex ? " · Windows native" : ""}`)), + ), + ), + h("label", null, "执行模式", + h("select", { value: executionMode, disabled: submitting, onChange: (event: any) => changeSubmitExecutionMode(String(event.target.value || "default")), "data-testid": "codex-execution-mode-select" }, + executionModeRows.map((mode: any) => h("option", { key: mode.id, value: mode.id }, `${mode.label || mode.id}${mode.id === "windows-native" ? " · 宿主 Codex" : ""}`)), ), ), h("label", null, "工作目录", h("input", { value: cwd, disabled: submitting, onChange: (event: any) => setCwd(event.target.value), placeholder: currentProviderDefaultWorkdir || queue?.defaultWorkdir || "/root/unidesk", "data-testid": "codex-cwd-input" })), @@ -3530,6 +3623,7 @@ export function CodeQueuePage({ microservices, onRaw, apiBaseUrl = "/api", initi h(StatusBadge, { status: selectedTask.lastJudge.decision }, selectedTask.lastJudge.decision), h("strong", null, `${Math.round(Number(selectedTask.lastJudge.confidence || 0) * 100)}% confidence`), h("p", { "data-testid": "codex-task-judge-reason" }, shortText(selectedTask.lastJudge.reason || "--", 180)), + h(JudgeFailureDetails, { judge: selectedTask.lastJudge, testId: "codex-task-judge-failure-details" }), selectedTask.lastJudge.continuePrompt ? h("code", { "data-testid": "codex-task-judge-continue-prompt" }, shortText(selectedTask.lastJudge.continuePrompt, 160)) : null, ) : h(EmptyState, { title: "尚未判定", text: "Codex turn 结束后会由 MiniMax M2.7 或 fallback judge 判定 complete/retry/fail;retry 会在已有 thread 追加继续执行 prompt。" }), ), diff --git a/src/components/frontend/src/trace.tsx b/src/components/frontend/src/trace.tsx index 9bbc621f..71bc8b20 100644 --- a/src/components/frontend/src/trace.tsx +++ b/src/components/frontend/src/trace.tsx @@ -864,6 +864,28 @@ function renderToolGroup(item: TraceItem): any { ); } +function traceSystemItemIsError(item: TraceItem): boolean { + const text = [ + item.title, + item.status, + item.bodyPreview, + item.commandPreview, + item.stderrPreview, + item.stdoutPreview, + ].map((value) => String(value || "")).join("\n"); + return /\b(error|failed|failure|interrupt|interrupted|cancell?ed|watchdog|timeout|closed|refused|aborted|exception)\b/iu.test(text); +} + +function filterTraceSystemEvents(items: TraceItem[], showSystemEvents: boolean): TraceItem[] { + if (showSystemEvents) return items; + return items.flatMap((item) => { + if (String(item.kind || "") === "system" && !traceSystemItemIsError(item)) return []; + if (String(item.kind || "") !== "toolGroup" || !Array.isArray(item.items)) return [item]; + const visibleItems = filterTraceSystemEvents(item.items, showSystemEvents); + return [{ ...item, items: visibleItems }]; + }); +} + const traceAutoScrollBottomThresholdPx = 16; function traceIsScrolledToBottom(element: HTMLElement): boolean { @@ -871,10 +893,10 @@ function traceIsScrolledToBottom(element: HTMLElement): boolean { return distanceToBottom <= traceAutoScrollBottomThresholdPx; } -export function TraceView({ items, input, port, autoScroll = false, loading = false, hasDetail = true, emptyText = "等待 Trace 输出...", loadingText = "正在加载完整 Trace...", testId = "trace-output", className = "codex-transcript", keepRecentToolCalls = 3, collapseTools = true }: AnyRecord) { +export function TraceView({ items, input, port, autoScroll = false, loading = false, hasDetail = true, emptyText = "等待 Trace 输出...", loadingText = "正在加载完整 Trace...", testId = "trace-output", className = "codex-transcript", keepRecentToolCalls = 3, collapseTools = true, showSystemEvents = false }: AnyRecord) { const ref = useRef(null); const shouldFollowTailRef = useRef(true); - const rawTrace = coalesceEditedFileChanges(port ? traceFromPort(port, input) : normalizeTraceItems(items)); + const rawTrace = filterTraceSystemEvents(coalesceEditedFileChanges(port ? traceFromPort(port, input) : normalizeTraceItems(items)), Boolean(showSystemEvents)); const trace = collapseTools ? collapseToolTraceRuns(rawTrace, keepRecentToolCalls) : rawTrace; const maxSeq = traceMaxSeq(rawTrace); useEffect(() => { diff --git a/src/components/microservices/code-queue/src/code-agent/codex.ts b/src/components/microservices/code-queue/src/code-agent/codex.ts index 50e7967e..cfd9bb9b 100644 --- a/src/components/microservices/code-queue/src/code-agent/codex.ts +++ b/src/components/microservices/code-queue/src/code-agent/codex.ts @@ -20,6 +20,7 @@ export interface CodexPortContext { recordNumberField: (record: Record | null, keys: string[]) => number | null; recordStringField: (record: Record | null, keys: string[]) => string; remoteAppServerCommand: (task: QueueTask) => string; + windowsNativeAppServerCommand: (task: QueueTask) => string; resolveReasoningEffort: (model: string, explicit?: string | null) => string | null; safePreview: (value: string, max?: number) => string; nowIso: () => string; @@ -36,6 +37,18 @@ function ctx(): CodexPortContext { return context; } +function windowsPathFromWslMount(path: string): string { + const match = path.match(/^\/mnt\/([a-zA-Z])(?:\/(.*))?$/u); + if (match === null) return path; + const drive = String(match[1]).toUpperCase(); + const rest = String(match[2] ?? "").replace(/\//gu, "\\"); + return rest.length > 0 ? `${drive}:\\${rest}` : `${drive}:\\`; +} + +function appServerCwdForTask(task: QueueTask): string { + return task.executionMode === "windows-native" ? windowsPathFromWslMount(task.cwd) : task.cwd; +} + class AppServerClient { private child: ChildProcessWithoutNullStreams; private nextId = 1; @@ -48,13 +61,16 @@ class AppServerClient { constructor(private readonly task: QueueTask, private readonly onNotification: (message: Record) => void) { this.closedPromise = new Promise((resolveClosed) => { this.closeResolve = resolveClosed; }); + const remoteCommand = task.executionMode === "windows-native" + ? ctx().windowsNativeAppServerCommand(task) + : ctx().remoteAppServerCommand(task); this.child = ctx().providerIsMain(task.providerId) ? spawn("codex", ["app-server", "--listen", "stdio://"], { cwd: task.cwd, env: { ...process.env, CODEX_HOME: ctx().config.codexHome, CODEX_INTERNAL_ORIGINATOR_OVERRIDE: "unidesk_code_queue" }, stdio: "pipe", }) - : spawn("bun", ["scripts/cli.ts", "ssh", task.providerId, ctx().remoteAppServerCommand(task)], { + : spawn("bun", ["scripts/cli.ts", "ssh", task.providerId, remoteCommand], { cwd: ctx().config.defaultWorkdir, env: process.env, stdio: "pipe", @@ -83,7 +99,7 @@ class AppServerClient { const response = await this.request("thread/resume", { threadId: this.task.codexThreadId, model: this.task.model, - cwd: this.task.cwd, + cwd: appServerCwdForTask(this.task), approvalPolicy: ctx().config.approvalPolicy, sandbox: ctx().config.sandbox, }); @@ -94,7 +110,7 @@ class AppServerClient { } const response = await this.request("thread/start", { model: this.task.model, - cwd: this.task.cwd, + cwd: appServerCwdForTask(this.task), approvalPolicy: ctx().config.approvalPolicy, sandbox: ctx().config.sandbox, serviceName: "unidesk-code-queue", @@ -108,7 +124,7 @@ class AppServerClient { const params: Record = { threadId, input: textInput(prompt), - cwd: this.task.cwd, + cwd: appServerCwdForTask(this.task), approvalPolicy: ctx().config.approvalPolicy, model: this.task.model, }; @@ -324,6 +340,9 @@ export async function runCodexTurn(task: QueueTask, prompt: string): Promise void; const terminalPromise = new Promise((resolveTerminal) => { terminalResolve = resolveTerminal; }); await ctx().ensureTaskExecutionContainer(task); + if (task.executionMode === "windows-native") { + ctx().appendOutput(task, "system", "windows-native execution: container stdio relay will connect to Codex on the provider Windows host\n", "execution/mode"); + } const app = new AppServerClient(task, (message) => { const method = typeof message.method === "string" ? message.method : "unknown"; if (method !== "thread/started" && method !== "turn/started") lastAppActivityAt = Date.now(); diff --git a/src/components/microservices/code-queue/src/code-agent/common.ts b/src/components/microservices/code-queue/src/code-agent/common.ts index 26c810a9..caeebe3a 100644 --- a/src/components/microservices/code-queue/src/code-agent/common.ts +++ b/src/components/microservices/code-queue/src/code-agent/common.ts @@ -1,6 +1,6 @@ // 重构前 index.ts 只读参考:commit 6a04144d3f5103014f75b637d7e6bc2f45bf007f,blob 56e590c1a6b5ca7ad128bf2c992f60e46c355a58;可用 `git show 6a04144d3f5103014f75b637d7e6bc2f45bf007f:src/components/microservices/code-queue/src/index.ts` 查看。 -import type { JsonValue } from "../types"; +import type { CodeExecutionMode, JsonValue } from "../types"; export type CodeAgentPortKind = "codex" | "opencode"; @@ -29,6 +29,8 @@ export interface ActiveRunSlotWaiter { export const minimaxM27Model = "minimax-m2.7"; export const defaultCodeModels = ["gpt-5.5", "gpt-5.4-mini", "gpt-5.4", minimaxM27Model]; export const opencodeNpmPackage = "opencode-ai@1.14.48"; +export const defaultCodeExecutionMode: CodeExecutionMode = "default"; +export const codeExecutionModes: CodeExecutionMode[] = ["default", "windows-native"]; export function normalizeCodeModel(value: string): string { const raw = String(value || "").trim(); @@ -43,6 +45,33 @@ export function codeAgentPortForModel(model: string): CodeAgentPortKind { return normalizeCodeModel(model) === minimaxM27Model ? "opencode" : "codex"; } +export function normalizeCodeExecutionMode(value: unknown): CodeExecutionMode { + const raw = typeof value === "string" ? value.trim().toLowerCase() : ""; + if (raw === "windows-native" || raw === "windows" || raw === "win32" || raw === "native-windows") return "windows-native"; + return defaultCodeExecutionMode; +} + +export function codeExecutionModeInfo(mode: CodeExecutionMode): Record { + if (mode === "windows-native") { + return { + kind: mode, + label: "Windows native Codex", + description: "Run Codex on the provider Windows host while the execution container relays stdio.", + codexRunsInContainer: false, + requiresProvider: true, + requiresWindowsCwd: true, + }; + } + return { + kind: mode, + label: "Default Codex runtime", + description: "Use the main-server Codex runtime or the provider execution container.", + codexRunsInContainer: true, + requiresProvider: false, + requiresWindowsCwd: false, + }; +} + export function opencodeModels(models: string[]): string[] { return models.filter((model) => codeAgentPortForModel(model) === "opencode"); } diff --git a/src/components/microservices/code-queue/src/dev-containers.ts b/src/components/microservices/code-queue/src/dev-containers.ts index d72a9ab9..8ee79f0e 100644 --- a/src/components/microservices/code-queue/src/dev-containers.ts +++ b/src/components/microservices/code-queue/src/dev-containers.ts @@ -103,7 +103,7 @@ export async function ensureTaskExecutionContainer(task: QueueTask): Promise { ctx().appendOutput(task, "system", `provider prepare start name=${command.name} target=${command.providerId} timeoutMs=${command.timeoutMs}\n`, "provider/container"); }, @@ -117,6 +117,7 @@ export async function ensureTaskExecutionContainer(task: QueueTask): Promise 0 && usage.swapCurrentBytes < Math.floor(usage.swapMaxBytes * 0.9)); - return usage !== null && usage.workingSetBytes >= threshold && !swapHasHeadroom ? { ...usage, thresholdBytes: threshold } : null; + let usage = readCgroupMemoryUsage(); + if (usage === null || usage.workingSetBytes < threshold) return null; + try { + (Bun as unknown as { gc?: (force?: boolean) => void }).gc?.(true); + usage = readCgroupMemoryUsage(); + } catch (error) { + logger("debug", "memory_watchdog_gc_failed", { error: errorToJson(error) }); + } + return usage !== null && usage.workingSetBytes >= threshold ? { ...usage, thresholdBytes: threshold } : null; } function startMemoryWatchdog(): void { @@ -749,6 +764,7 @@ function normalizeTask(task: QueueTask): QueueTask { task.activeTurnId ??= null; task.providerId = normalizeTaskProviderId(task.providerId); task.model ||= config.defaultModel; + task.executionMode = normalizeCodeExecutionMode(task.executionMode); task.cwd = resolveTaskCwd(task.providerId, task.cwd); task.reasoningEffort = resolveReasoningEffort(task.model, task.reasoningEffort); task.basePrompt ||= userPromptForDisplay(task.prompt); @@ -816,6 +832,7 @@ function isOpenCodeStepBoundaryMethod(method: string | undefined): boolean { function outputCanChangeStepCount(output: LiveOutput): boolean { if (output.channel === "user" && output.method === "enqueue") return false; + if (output.channel === "system") return false; return !isOpenCodeStepBoundaryMethod(output.method); } @@ -827,7 +844,8 @@ function commandStartedBeforeIn(outputs: LiveOutput[], output: LiveOutput): bool function outputStartsTraceStepInHistory(outputs: LiveOutput[], output: LiveOutput): boolean { if (output.channel === "user" && output.method === "enqueue") return false; if (isOpenCodeStepBoundaryMethod(output.method)) return false; - if (output.channel === "diff" || output.channel === "tool" || output.channel === "error" || output.channel === "assistant" || output.channel === "reasoning" || output.channel === "system") return true; + if (output.channel === "system") return false; + if (output.channel === "diff" || output.channel === "tool" || output.channel === "error" || output.channel === "assistant" || output.channel === "reasoning") return true; if (output.channel === "user") return true; if (output.channel !== "command") return true; const method = String(output.method || ""); @@ -900,6 +918,24 @@ function errorToJson(error: unknown): JsonValue { return String(error); } +function judgeFailureDetailsForOutput(judge: JudgeResult): string { + const details = judge.failureDetails; + if (details === undefined || details === null) return ""; + return [ + "", + `MiniMax failure details: stage=${details.stage}`, + `timedOut=${details.timedOut}`, + `durationMs=${details.durationMs}`, + `timeoutMs=${details.timeoutMs}`, + details.promptChars === undefined ? "" : `promptChars=${details.promptChars}`, + details.promptLines === undefined ? "" : `promptLines=${details.promptLines}`, + details.payloadBytes === undefined ? "" : `payloadBytes=${details.payloadBytes}`, + details.responseStatus === undefined || details.responseStatus === null ? "" : `responseStatus=${details.responseStatus}`, + `errorName=${details.errorName}`, + `error=${safePreview(details.errorMessage, 220)}`, + ].filter((part) => part.length > 0).join(" "); +} + function databaseErrorMessage(error: unknown): string { if (error instanceof Error) return error.message; return String(error); @@ -966,6 +1002,7 @@ async function upsertTaskToDatabase(client: SqlExecutor, task: QueueTask): Promi queue_id, status, provider_id, + execution_mode, model, cwd, prompt, @@ -995,6 +1032,7 @@ async function upsertTaskToDatabase(client: SqlExecutor, task: QueueTask): Promi ${queueIdOf(task)}, ${task.status}, ${task.providerId}, + ${task.executionMode}, ${task.model}, ${task.cwd}, ${task.prompt}, @@ -1024,6 +1062,7 @@ async function upsertTaskToDatabase(client: SqlExecutor, task: QueueTask): Promi status = EXCLUDED.status, queue_id = EXCLUDED.queue_id, provider_id = EXCLUDED.provider_id, + execution_mode = EXCLUDED.execution_mode, model = EXCLUDED.model, cwd = EXCLUDED.cwd, prompt = EXCLUDED.prompt, @@ -1352,6 +1391,7 @@ async function initDatabasePersistence(): Promise { queue_id TEXT NOT NULL DEFAULT 'default', status TEXT NOT NULL, provider_id TEXT NOT NULL DEFAULT 'main-server', + execution_mode TEXT NOT NULL DEFAULT 'default', model TEXT NOT NULL, cwd TEXT NOT NULL, prompt TEXT NOT NULL, @@ -1403,6 +1443,7 @@ async function initDatabasePersistence(): Promise { `; await sql`ALTER TABLE unidesk_code_queue_tasks ADD COLUMN IF NOT EXISTS queue_id TEXT NOT NULL DEFAULT 'default'`; await sql`ALTER TABLE unidesk_code_queue_tasks ADD COLUMN IF NOT EXISTS provider_id TEXT NOT NULL DEFAULT 'main-server'`; + await sql`ALTER TABLE unidesk_code_queue_tasks ADD COLUMN IF NOT EXISTS execution_mode TEXT NOT NULL DEFAULT 'default'`; await sql`ALTER TABLE unidesk_code_queue_tasks ADD COLUMN IF NOT EXISTS base_prompt TEXT NOT NULL DEFAULT ''`; await sql`ALTER TABLE unidesk_code_queue_tasks ADD COLUMN IF NOT EXISTS reference_task_ids JSONB NOT NULL DEFAULT '[]'::jsonb`; await sql`ALTER TABLE unidesk_code_queue_tasks ADD COLUMN IF NOT EXISTS reference_injection JSONB`; @@ -1419,6 +1460,7 @@ async function initDatabasePersistence(): Promise { await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_code_queue_tasks_status_updated ON unidesk_code_queue_tasks(status, updated_at DESC)`; await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_code_queue_tasks_queue_status_updated ON unidesk_code_queue_tasks(queue_id, status, updated_at DESC)`; await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_code_queue_tasks_provider_updated ON unidesk_code_queue_tasks(provider_id, updated_at DESC)`; + await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_code_queue_tasks_execution_mode_updated ON unidesk_code_queue_tasks(execution_mode, updated_at DESC)`; await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_code_queue_tasks_created ON unidesk_code_queue_tasks(created_at DESC)`; await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_code_queue_tasks_queue_created ON unidesk_code_queue_tasks(queue_id, created_at DESC, id DESC)`; await sql`CREATE INDEX IF NOT EXISTS idx_unidesk_code_queue_tasks_unread_terminal ON unidesk_code_queue_tasks(queue_id, updated_at DESC) WHERE read_at IS NULL AND status IN ('succeeded', 'failed', 'canceled')`; @@ -1669,18 +1711,29 @@ function normalizeRequest(value: unknown): QueueTaskRequest { if (typeof record.cwd === "string" && record.cwd.length > 0) request.cwd = record.cwd; if (typeof record.model === "string" && record.model.length > 0) request.model = record.model; if (typeof record.reasoningEffort === "string" && record.reasoningEffort.length > 0) request.reasoningEffort = record.reasoningEffort; + if (typeof record.executionMode === "string" && record.executionMode.length > 0) request.executionMode = normalizeCodeExecutionMode(record.executionMode); if (typeof record.maxAttempts === "number" && Number.isInteger(record.maxAttempts) && record.maxAttempts > 0) request.maxAttempts = Math.min(maxTaskAttempts, record.maxAttempts); const referenceTaskIds = collectReferenceTaskIds(record, record.prompt); if (referenceTaskIds.length > 0) request.referenceTaskIds = referenceTaskIds; return request; } +function validateExecutionModeForTask(providerId: string, cwd: string, model: string, executionMode: ReturnType): void { + if (executionMode !== "windows-native") return; + if (providerIsMain(providerId)) throw new Error("windows-native executionMode requires a non-main WSL provider"); + if (codeAgentPortForModel(model) !== "codex") throw new Error("windows-native executionMode only supports Codex models"); + if (!cwd.startsWith("/mnt/")) throw new Error("windows-native executionMode requires cwd under /mnt/"); +} + function createTask(request: QueueTaskRequest): QueueTask { const at = nowIso(); const basePrompt = request.basePrompt ?? userPromptForDisplay(request.prompt); const referenceTaskIds = request.referenceTaskIds ?? []; const providerId = normalizeTaskProviderId(request.providerId); const model = normalizeCodeModel(request.model ?? config.defaultModel); + const executionMode = normalizeCodeExecutionMode(request.executionMode); + const cwd = resolveTaskCwd(providerId, request.cwd); + validateExecutionModeForTask(providerId, cwd, model, executionMode); const queueId = normalizeQueueId(request.queueId); ensureQueue(queueId); return { @@ -1692,9 +1745,10 @@ function createTask(request: QueueTaskRequest): QueueTask { referenceTaskIds, referenceInjection: request.referenceInjection ?? null, providerId, - cwd: resolveTaskCwd(providerId, request.cwd), + cwd, model, reasoningEffort: resolveReasoningEffort(model, request.reasoningEffort), + executionMode, maxAttempts: request.maxAttempts ?? config.defaultMaxAttempts, status: "queued", createdAt: at, @@ -2067,6 +2121,7 @@ configureCodexPort({ recordNumberField, recordStringField, remoteAppServerCommand, + windowsNativeAppServerCommand, resolveReasoningEffort, safePreview, nowIso, @@ -2149,6 +2204,7 @@ function taskForJudgeProbe(probe: JudgeProbeCase): QueueTask { cwd: config.defaultWorkdir, model: config.defaultModel, reasoningEffort: resolveReasoningEffort(config.defaultModel, config.defaultReasoningEffort), + executionMode: "default", maxAttempts: 3, status: "judging", createdAt: at, @@ -2239,6 +2295,231 @@ async function runJudgeProbe(): Promise { }); } +function cloneJson(value: T): T { + return JSON.parse(JSON.stringify(value)) as T; +} + +function numberOrNull(value: unknown): number | null { + const parsed = Number(value); + return Number.isFinite(parsed) ? parsed : null; +} + +function maxOutputSeqBefore(output: LiveOutput[], exclusiveSeq: number): number | null { + let maxSeq: number | null = null; + for (const item of output) { + const seq = numberOrNull(item.seq); + if (seq === null || seq >= exclusiveSeq) continue; + maxSeq = maxSeq === null ? seq : Math.max(maxSeq, seq); + } + return maxSeq; +} + +function outputSeqAtOrBeforeTime(output: LiveOutput[], at: string | null): number | null { + const atMs = timestampMs(at); + if (atMs === null) return null; + let maxSeq: number | null = null; + for (const item of output) { + const itemMs = timestampMs(item.at); + if (itemMs === null || itemMs > atMs) continue; + const seq = numberOrNull(item.seq); + if (seq === null) continue; + maxSeq = maxSeq === null ? seq : Math.max(maxSeq, seq); + } + return maxSeq; +} + +function preJudgeOutputEndSeq(attempt: AttemptSummary, output: LiveOutput[]): { endSeq: number | null; source: string } { + const judgeSeq = numberOrNull(attempt.judgeSeq); + if (judgeSeq !== null) return { endSeq: maxOutputSeqBefore(output, judgeSeq), source: "before-judgeSeq" }; + const explicitEnd = numberOrNull(attempt.outputEndSeq); + if (explicitEnd !== null) { + const explicitItem = output.find((item) => numberOrNull(item.seq) === explicitEnd); + if (explicitItem?.method === "judge") return { endSeq: maxOutputSeqBefore(output, explicitEnd), source: "before-outputEndSeq-judge" }; + return { endSeq: explicitEnd, source: "outputEndSeq" }; + } + const byFinishedAt = outputSeqAtOrBeforeTime(output, attempt.finishedAt); + return { endSeq: byFinishedAt, source: byFinishedAt === null ? "unbounded" : "finishedAt" }; +} + +function outputBeforeJudge(output: LiveOutput[], endSeq: number | null): LiveOutput[] { + if (endSeq === null) return output; + return output.filter((item) => numberOrNull(item.seq) !== null && Number(item.seq) <= endSeq); +} + +function currentAttemptOutputCountForReplay(attempt: AttemptSummary, output: LiveOutput[], hotOutput: LiveOutput[], endSeq: number | null): number { + const startSeq = numberOrNull(attempt.outputStartSeq); + if (startSeq === null) return hotOutput.slice(-80).length; + return output.filter((item) => { + const seq = numberOrNull(item.seq); + return seq !== null && seq >= startSeq && (endSeq === null || seq <= endSeq); + }).length; +} + +function finalResponseForTaskBeforeJudge(attempts: AttemptSummary[]): string { + for (let index = attempts.length - 1; index >= 0; index -= 1) { + const finalResponse = String(attempts[index]?.finalResponse ?? ""); + if (finalResponse.trim().length > 0) return finalResponse; + } + return ""; +} + +function retainedEventsForAttempt(task: QueueTask, attempt: AttemptSummary): CodexRunResult["events"] { + const startedMs = timestampMs(attempt.startedAt); + const finishedMs = timestampMs(attempt.finishedAt); + return task.events.filter((event) => { + const eventMs = timestampMs(event.at); + if (eventMs === null) return false; + if (startedMs !== null && eventMs < startedMs) return false; + if (finishedMs !== null && eventMs > finishedMs + 1000) return false; + return true; + }); +} + +function attemptEventsForReplay(task: QueueTask, attempt: AttemptSummary): { events: CodexRunResult["events"]; source: string; exact: boolean } { + if (Array.isArray(attempt.events)) return { events: cloneJson(attempt.events), source: "attempt.events", exact: true }; + return { events: cloneJson(retainedEventsForAttempt(task, attempt)), source: "retained-task-events", exact: false }; +} + +function replayAttemptIndexFromUrl(task: QueueTask, url: URL): number { + const raw = url.searchParams.get("attempt") ?? url.searchParams.get("attemptId") ?? url.searchParams.get("attemptIndex"); + if (raw !== null) { + const value = Number(raw); + if (!Number.isInteger(value) || value <= 0) throw new Error("judge replay attempt must be a positive integer"); + return value; + } + const latest = task.attempts.at(-1)?.index ?? task.currentAttempt; + if (!Number.isInteger(latest) || latest <= 0) throw new Error("task has no completed attempt to judge"); + return latest; +} + +function buildJudgeReplay(task: QueueTask, attemptIndex: number): { + task: QueueTask; + result: CodexRunResult; + attempt: AttemptSummary; + replay: Record; +} { + const attempt = task.attempts.find((item) => item.index === attemptIndex); + if (attempt === undefined) throw new Error(`attempt ${attemptIndex} not found on task ${task.id}`); + const fullOutput = taskFullOutput(task); + const preJudge = preJudgeOutputEndSeq(attempt, fullOutput); + const beforeJudge = outputBeforeJudge(fullOutput, preJudge.endSeq); + const hotOutput = config.maxInMemoryOutputRecords > 0 ? beforeJudge.slice(-config.maxInMemoryOutputRecords) : beforeJudge; + const attempts = task.attempts + .filter((item) => item.index <= attempt.index) + .map((item) => cloneJson(item)); + const latestAttempt = attempts[attempts.length - 1]; + if (latestAttempt === undefined) throw new Error(`attempt ${attemptIndex} could not be prepared`); + latestAttempt.judge = null; + latestAttempt.judgeAt = null; + latestAttempt.judgeSeq = null; + latestAttempt.outputEndSeq = preJudge.endSeq; + const eventReplay = attemptEventsForReplay(task, attempt); + const previousAttempts = attempts.filter((item) => item.index < attempt.index); + const result: CodexRunResult = { + threadId: task.codexThreadId, + turnId: null, + finalResponse: String(attempt.finalResponse ?? ""), + terminalStatus: attempt.terminalStatus, + terminalError: attempt.error, + transportClosedBeforeTerminal: attempt.transportClosedBeforeTerminal, + appServerExit: { + code: attempt.appServerExitCode, + signal: attempt.appServerSignal, + stderrTail: String(attempt.stderrTail ?? ""), + }, + events: eventReplay.events, + }; + const replayTask: QueueTask = { + ...cloneJson(task), + status: "judging", + currentAttempt: attempt.index, + currentMode: attempt.mode, + attempts, + output: numberOrNull(attempt.outputStartSeq) === null ? hotOutput : beforeJudge, + events: eventReplay.events, + finalResponse: finalResponseForTaskBeforeJudge(attempts), + lastJudge: previousAttempts.at(-1)?.judge ?? null, + judgeFailCount: previousAttempts.filter((item) => item.judge?.decision === "fail").length, + activeTurnId: null, + finishedAt: null, + readAt: null, + nextPrompt: null, + nextMode: null, + }; + return { + task: replayTask, + result, + attempt, + replay: { + sameJudgeCodePath: true, + replayExact: eventReplay.exact, + taskId: task.id, + attemptIndex: attempt.index, + attemptMode: attempt.mode, + outputStartSeq: attempt.outputStartSeq ?? null, + storedOutputEndSeq: attempt.outputEndSeq ?? null, + replayOutputEndSeq: preJudge.endSeq, + replayOutputEndSeqSource: preJudge.source, + judgeSeq: attempt.judgeSeq ?? null, + fullOutputBeforeJudgeCount: beforeJudge.length, + hotOutputCount: hotOutput.length, + currentAttemptOutputCount: currentAttemptOutputCountForReplay(attempt, beforeJudge, hotOutput, preJudge.endSeq), + eventSource: eventReplay.source, + eventReplayExact: eventReplay.exact, + eventCount: eventReplay.events.length, + note: eventReplay.exact + ? "Replay uses attempt-stored event summaries plus the same judgeTask context builder and MiniMax call path." + : "Historical attempt did not store per-attempt events; replay falls back to retained task.events. Output, final response, terminal status, stderr, attempt window, prompt compaction, and MiniMax call path are reconstructed from persisted task/output archives.", + }, + }; +} + +async function runSingleTaskJudge(task: QueueTask, url: URL): Promise { + const attemptIndex = replayAttemptIndexFromUrl(task, url); + const dryRun = truthyParam(url, "dryRun") || truthyParam(url, "noCall"); + const includePrompt = truthyParam(url, "includePrompt"); + const replay = buildJudgeReplay(task, attemptIndex); + const context = judgeTaskInputDiagnostics(replay.task, replay.result, includePrompt); + const startedAt = Date.now(); + const judge = dryRun ? null : await judgeTask(replay.task, replay.result); + const durationMs = Date.now() - startedAt; + const storedJudge = replay.attempt.judge ?? null; + const storedFailure = storedJudge?.failureDetails ?? null; + const promptChars = Number(context.promptChars); + const payloadBytes = Number(context.payloadBytes); + return jsonResponse({ + ok: true, + dryRun, + configured: config.minimaxApiKey.length > 0, + model: config.minimaxModel, + taskId: task.id, + attempt: { + index: replay.attempt.index, + mode: replay.attempt.mode, + terminalStatus: replay.attempt.terminalStatus, + finalResponseChars: replay.attempt.finalResponseChars ?? String(replay.attempt.finalResponse ?? "").length, + startedAt: replay.attempt.startedAt, + finishedAt: replay.attempt.finishedAt, + }, + replay: replay.replay, + context, + judge, + durationMs, + storedJudge, + comparison: { + storedDecision: storedJudge?.decision ?? null, + storedSource: storedJudge?.source ?? null, + decisionMatchesStored: judge === null || storedJudge === null ? null : judge.decision === storedJudge.decision, + storedFailureTimedOut: storedFailure?.timedOut ?? null, + storedFailureStage: storedFailure?.stage ?? null, + storedPromptChars: storedFailure?.promptChars ?? null, + promptCharsDeltaFromStored: storedFailure?.promptChars === undefined || !Number.isFinite(promptChars) ? null : promptChars - storedFailure.promptChars, + storedPayloadBytes: storedFailure?.payloadBytes ?? null, + payloadBytesDeltaFromStored: storedFailure?.payloadBytes === undefined || !Number.isFinite(payloadBytes) ? null : payloadBytes - storedFailure.payloadBytes, + }, + }); +} + function attemptFromResult(task: QueueTask, mode: RunMode, startedAt: string, finishedAt: string, result: CodexRunResult, outputStartSeq: number | null = null, outputEndSeq: number | null = null, inputPrompt: string | null = null): AttemptSummary { const finalResponse = result.finalResponse; const attempt: AttemptSummary = { @@ -2246,11 +2527,14 @@ function attemptFromResult(task: QueueTask, mode: RunMode, startedAt: string, fi mode, startedAt, finishedAt, + providerId: task.providerId, + executionMode: task.executionMode, terminalStatus: result.terminalStatus, transportClosedBeforeTerminal: result.transportClosedBeforeTerminal, appServerExitCode: result.appServerExit.code, appServerSignal: result.appServerExit.signal, error: result.terminalError, + events: result.events, finalResponse, finalResponsePreview: safePreview(finalResponse, 3000), finalResponseChars: finalResponse.length, @@ -2323,7 +2607,7 @@ function failTaskForFallbackRetryLimit(task: QueueTask, judge: JudgeResult | nul } async function runTask(task: QueueTask): Promise { - logger("info", "task_processor_start", { taskId: task.id, queueId: queueIdOf(task), providerId: task.providerId, cwd: task.cwd, maxAttempts: task.maxAttempts, model: task.model, agentPort: codeAgentPortForModel(task.model), promptPreview: safePreview(task.prompt, 240) }); + logger("info", "task_processor_start", { taskId: task.id, queueId: queueIdOf(task), providerId: task.providerId, executionMode: task.executionMode, cwd: task.cwd, maxAttempts: task.maxAttempts, model: task.model, agentPort: codeAgentPortForModel(task.model), promptPreview: safePreview(task.prompt, 240) }); if (task.status === "retry_wait" && task.lastJudge?.source === "fallback" && task.lastJudge.decision === "retry" && fallbackJudgeRetryCount(task) >= fallbackJudgeRetryLimit) { failTaskForFallbackRetryLimit(task, task.lastJudge); return; @@ -2354,8 +2638,8 @@ async function runTask(task: QueueTask): Promise { task.readAt = null; task.finishedAt = null; task.updatedAt = startedAt; - logger("info", "task_run_start", { taskId: task.id, queueId: queueIdOf(task), attempt: task.currentAttempt, mode, providerId: task.providerId, cwd: task.cwd, maxAttempts: task.maxAttempts, model: task.model, agentPort: codeAgentPortForModel(task.model), freshRecovery: needsFreshRecoveryPrompt }); - const attemptStartOutput = appendOutput(task, "system", `attempt ${task.currentAttempt}/${task.maxAttempts} queue=${queueIdOf(task)} provider=${task.providerId} cwd=${task.cwd} mode=${mode} model=${task.model} port=${codeAgentPortForModel(task.model)}\n`, "queue"); + logger("info", "task_run_start", { taskId: task.id, queueId: queueIdOf(task), attempt: task.currentAttempt, mode, providerId: task.providerId, executionMode: task.executionMode, cwd: task.cwd, maxAttempts: task.maxAttempts, model: task.model, agentPort: codeAgentPortForModel(task.model), freshRecovery: needsFreshRecoveryPrompt }); + const attemptStartOutput = appendOutput(task, "system", `attempt ${task.currentAttempt}/${task.maxAttempts} queue=${queueIdOf(task)} provider=${task.providerId} executionMode=${task.executionMode} cwd=${task.cwd} mode=${mode} model=${task.model} port=${codeAgentPortForModel(task.model)}\n`, "queue"); let result: CodexRunResult; try { @@ -2374,7 +2658,7 @@ async function runTask(task: QueueTask): Promise { if (task.cancelRequested) break; const judge = await judgeTask(task, result); task.lastJudge = judge; - const judgeOutput = appendOutput(task, judge.decision === "complete" ? "system" : judge.decision === "fail" ? "error" : "system", `judge=${judge.decision} confidence=${judge.confidence.toFixed(2)} source=${judge.source}: ${judge.reason}\n`, "judge"); + const judgeOutput = appendOutput(task, judge.decision === "complete" ? "system" : judge.decision === "fail" ? "error" : "system", `judge=${judge.decision} confidence=${judge.confidence.toFixed(2)} source=${judge.source}: ${judge.reason}${judgeFailureDetailsForOutput(judge)}\n`, "judge"); const latestAttempt = task.attempts.at(-1); if (latestAttempt !== undefined && latestAttempt.index === task.currentAttempt) { latestAttempt.judge = judge; @@ -2382,7 +2666,7 @@ async function runTask(task: QueueTask): Promise { latestAttempt.judgeSeq = judgeOutput?.seq ?? null; latestAttempt.outputEndSeq = judgeOutput?.seq ?? latestAttempt.outputEndSeq ?? null; } - logger("info", "task_judged", { taskId: task.id, attempt: task.currentAttempt, decision: judge.decision, confidence: judge.confidence, source: judge.source, reason: safePreview(judge.reason, 500) }); + logger("info", "task_judged", { taskId: task.id, attempt: task.currentAttempt, decision: judge.decision, confidence: judge.confidence, source: judge.source, reason: safePreview(judge.reason, 500), failureDetails: judge.failureDetails ?? null } as unknown as JsonValue); if (judge.decision === "complete") { task.status = "succeeded"; @@ -2856,6 +3140,7 @@ function requestErrorResponse(error: unknown): Response | null { || error.message.startsWith("referenceTaskIds supports at most ") || error.message.startsWith("queueId must match ") || error.message.startsWith("queue name must be ") + || error.message.startsWith("windows-native executionMode ") )) { return jsonResponse({ ok: false, error: error.message }, 400); } @@ -2889,7 +3174,7 @@ async function createTasks(req: Request): Promise { for (const task of tasks) publishTaskOaEvent(task, "enqueue"); for (const id of new Set(tasks.map(queueIdOf))) publishQueueEvent("enqueue", id); persistState(); - logger("info", "tasks_enqueued", { count: tasks.length, ids: tasks.map((task) => task.id), queueIds: Array.from(new Set(tasks.map(queueIdOf))), providerIds: Array.from(new Set(tasks.map((task) => task.providerId))) }); + logger("info", "tasks_enqueued", { count: tasks.length, ids: tasks.map((task) => task.id), queueIds: Array.from(new Set(tasks.map(queueIdOf))), providerIds: Array.from(new Set(tasks.map((task) => task.providerId))), executionModes: Array.from(new Set(tasks.map((task) => task.executionMode))) }); scheduleQueue(); await flushDirtyTasksToDatabase(true); return jsonResponse({ ok: true, tasks: tasks.map((task) => taskForResponse(task)), queue: await queueSummaryForResponse() }, 202); @@ -3402,7 +3687,7 @@ async function route(req: Request): Promise { const url = new URL(req.url); if (req.method === "OPTIONS") return jsonResponse({ ok: true }); try { - if (url.pathname === "/" || url.pathname === "/health") return jsonResponse({ ok: true, service: "code-queue", queue: await queueSummaryForHealth(), startedAt: serviceStartedAt }); + if (url.pathname === "/" || url.pathname === "/health") return jsonResponse({ ok: true, service: "code-queue", queue: await queueSummaryForHealth(false), startedAt: serviceStartedAt }); if (url.pathname === "/logs") return jsonResponse({ ok: true, logs: recentLogs.slice(-parseLimit(url)) }); if (url.pathname === "/api/events" && req.method === "GET") return jsonResponse({ ok: false, error: "Code Queue private SSE was removed; subscribe to oa-event-flow /api/events/stream with service:code-queue tags." }, 410); if (url.pathname === "/api/dev-ready" && req.method === "GET") return jsonResponse({ ok: true, devReady: collectDevReady() }); @@ -3546,6 +3831,12 @@ async function route(req: Request): Promise { if (task === null) return jsonResponse({ ok: false, error: "task not found" }, 404); return await taskTraceStepDetailResponse(task, url); } + const judgeTaskMatch = url.pathname.match(/^\/api\/tasks\/([^/]+)\/judge$/u); + if (judgeTaskMatch !== null && (req.method === "GET" || req.method === "POST")) { + const task = await findTaskForRead(decodeURIComponent(judgeTaskMatch[1] ?? "")); + if (task === null) return jsonResponse({ ok: false, error: "task not found" }, 404); + return await runSingleTaskJudge(task, url); + } const summaryMatch = url.pathname.match(/^\/api\/tasks\/([^/]+)\/summary$/u); if (summaryMatch !== null && req.method === "GET") { const task = await findTaskForRead(decodeURIComponent(summaryMatch[1] ?? "")); diff --git a/src/components/microservices/code-queue/src/judge.ts b/src/components/microservices/code-queue/src/judge.ts index 56465521..d81c3eac 100644 --- a/src/components/microservices/code-queue/src/judge.ts +++ b/src/components/microservices/code-queue/src/judge.ts @@ -4,6 +4,7 @@ import type { CodexRunResult, FeedbackPromptRecord, JudgeDecision, + JudgeFailureDetails, JudgeProbeCase, JudgeResult, JsonValue, @@ -80,7 +81,13 @@ function promptLineCount(text: string): number { return ctx().promptLineCount(text); } -function fallbackJudge(result: CodexRunResult, minimaxError?: string): JudgeResult { +function failureDetailReason(detail: JudgeFailureDetails): string { + const timeout = detail.timedOut ? `timed out after ${detail.timeoutMs}ms` : detail.errorMessage; + const promptSize = detail.promptChars === undefined ? "" : `,prompt=${detail.promptChars} chars/${detail.promptLines ?? "?"} lines`; + return `MiniMax judge ${timeout}${promptSize}`; +} + +function fallbackJudge(result: CodexRunResult, minimaxError?: string | JudgeFailureDetails): JudgeResult { if (result.transportClosedBeforeTerminal || result.terminalStatus === null) { return { decision: "retry", confidence: 0.75, reason: "Codex app-server 在 turn/completed 之前关闭。", continuePrompt: retryInstruction, source: "fallback" }; } @@ -94,11 +101,17 @@ function fallbackJudge(result: CodexRunResult, minimaxError?: string): JudgeResu return { decision: "retry", confidence: 0.78, reason: "Codex turn 没有返回最终 assistant response,不能视为任务已完成。", continuePrompt: retryInstruction, source: "fallback" }; } if (minimaxError !== undefined) { + const failureDetails = typeof minimaxError === "string" ? null : minimaxError; + const errorText = typeof minimaxError === "string" ? minimaxError : failureDetailReason(minimaxError); return { decision: "retry", confidence: 0.65, - reason: `MiniMax judge 失败(${safePreview(minimaxError, 240)});安全 fallback 将继续现有 session,而不是把 turn/completed 当作任务已完成。`, + reason: `MiniMax judge 失败(${safePreview(errorText, 300)});安全 fallback 将继续现有 session,而不是把 turn/completed 当作任务已完成。`, source: "fallback", + failureDetails, + raw: failureDetails === null + ? { minimaxFailure: { errorMessage: String(minimaxError) } } + : { minimaxFailure: failureDetails as unknown as JsonValue }, }; } return { decision: "complete", confidence: 0.65, reason: "Codex 输出了 completed 状态的 turn/completed,且未配置 MiniMax judge。", source: "fallback" }; @@ -135,21 +148,99 @@ function judgeEvidenceText(task: QueueTask, result: CodexRunResult): string { ].join("\n"); } +function encodedBytes(value: string): number { + return new TextEncoder().encode(value).length; +} + +function compactJudgeOutputItems(output: LiveOutput[]): { items: Array<{ channel: string; text: string; method?: string; seq?: number; at?: string }>; omitted: number; totalTextChars: number } { + const important = output.filter((item) => { + const method = String(item.method || ""); + const text = String(item.text || ""); + return item.channel === "error" + || method === "turn/completed" + || method === "item/completed" + || method === "item/started" + || method === "provider/container" + || method === "execution/mode" + || method.includes("watchdog") + || /(error|failed|失败|timeout|timed out|aborted|rebuild|health|succeeded|verified|passed|judge)/iu.test(text); + }); + const bySeq = new Map(); + for (const item of [...important.slice(-32), ...output.slice(-28)]) { + const seq = Number(item.seq); + if (Number.isFinite(seq)) bySeq.set(seq, item); + } + const selected = Array.from(bySeq.values()).sort((left, right) => Number(left.seq) - Number(right.seq)); + const items: Array<{ channel: string; text: string; method?: string; seq?: number; at?: string }> = []; + let remainingChars = 14_000; + let totalTextChars = 0; + for (const item of selected) { + const rawText = String(item.text || ""); + totalTextChars += rawText.length; + if (remainingChars <= 0) break; + const perItem = item.channel === "error" ? 700 : 360; + const max = Math.max(120, Math.min(perItem, remainingChars)); + const text = safePreview(rawText, max); + remainingChars -= text.length; + items.push({ + channel: item.channel, + method: item.method, + seq: item.seq, + at: item.at, + text, + }); + } + return { items, omitted: Math.max(0, output.length - items.length), totalTextChars }; +} + +function compactJudgeEvents(events: CodexRunResult["events"]): { events: CodexRunResult["events"]; omitted: number } { + const selected = events.slice(-30).map((event) => ({ + ...event, + message: event.message === undefined ? undefined : safePreview(event.message, 300), + textPreview: event.textPreview === undefined ? undefined : safePreview(event.textPreview, 300), + })); + return { events: selected, omitted: Math.max(0, events.length - selected.length) }; +} + function hasServiceLimitOrTransportError(text: string): boolean { return /(429|Too Many Requests|rate limit|quota exceeded|overloaded|exceeded retry limit|stream disconnected|no activity timeout|app-server closed|ECONNRESET|ETIMEDOUT)/iu.test(text); } +function compactLatestAttemptForJudge(attempt: QueueTask["attempts"][number] | null): Record | null { + if (attempt === null) return null; + return { + index: attempt.index, + mode: attempt.mode, + startedAt: attempt.startedAt, + finishedAt: attempt.finishedAt, + providerId: attempt.providerId, + executionMode: attempt.executionMode, + terminalStatus: attempt.terminalStatus, + transportClosedBeforeTerminal: attempt.transportClosedBeforeTerminal, + appServerExitCode: attempt.appServerExitCode, + appServerSignal: attempt.appServerSignal, + error: attempt.error, + finalResponsePreview: safePreview(String(attempt.finalResponsePreview || attempt.finalResponse || ""), 1200), + finalResponseChars: Number(attempt.finalResponseChars ?? String(attempt.finalResponse || "").length), + stderrTail: safePreview(String(attempt.stderrTail || ""), 1200), + outputStartSeq: attempt.outputStartSeq ?? null, + outputEndSeq: attempt.outputEndSeq ?? null, + }; +} + function judgePrompt(task: QueueTask, result: CodexRunResult): string { const latestAttempt = task.attempts[task.attempts.length - 1] ?? null; const originalUserTask = task.basePrompt || userPromptForDisplay(task.prompt); - const resolvedPromptForCodex = task.prompt === originalUserTask ? null : safePreview(task.prompt, 12000); + const resolvedPromptForCodex = task.prompt === originalUserTask ? null : safePreview(task.prompt, 6000); const currentAttemptOutput = currentAttemptOutputForJudge(task); + const outputEvidence = compactJudgeOutputItems(currentAttemptOutput); + const eventEvidence = compactJudgeEvents(result.events); // Keep this record factual. Do not add local completion gates here; MiniMax // is authoritative whenever it returns a valid judge JSON. return JSON.stringify({ instruction: "请判定一个 Codex 编码任务是否真正完成、是否应通过向现有 Codex thread 追加 continuation prompt 继续重试,或是否应作为不可重试失败处理。只能返回 JSON,不要输出 Markdown fence、解释性正文或注释。所有自然语言字段必须使用中文,尤其是 reason 和 continuePrompt。重要:普通的 Codex turn/completed 状态只表示传输/session 终止事件,不等于用户任务已完成。决策前必须检查当前尝试的 transcript、最终回复、命令/文件变更事件、stderr 和原始任务。请严格判定:如果用户任务中的任一显式验收项缺少已完成证据,就选择 retry。最常见错误是把未完成或跑偏的工作标成 fail;未完成工作必须选择 retry,让同一个 session 继续。不要把更早 attempt 的限流/中断证据自动当作当前 attempt 的完成门禁;如果当前最新 attempt 已经提供完整完成证据,可以判定 complete。", schema: { decision: "complete|retry|fail", confidence: "0..1", reason: "中文短句", continuePrompt: "decision=retry 时必填,除非确实没有可用的继续提示;内容必须是中文,保持简洁,不要粘贴原始任务、引用上下文、transcript 或 JSON" }, - originalTask: originalUserTask, + originalTask: safePreview(originalUserTask, 6000), resolvedPromptForCodex, attempt: task.currentAttempt, maxAttempts: task.maxAttempts, @@ -163,12 +254,15 @@ function judgePrompt(task: QueueTask, result: CodexRunResult): string { finalResponse: safePreview(result.finalResponse, 6000), finalResponseChars: result.finalResponse.length, finalResponseMissing: result.finalResponse.trim().length === 0, - latestAttempt, + latestAttempt: compactLatestAttemptForJudge(latestAttempt), judgeFailCount: task.judgeFailCount, judgeFailRetryLimit: ctx().judgeFailRetryLimit, cancelRequested: task.cancelRequested, - currentAttemptOutput: currentAttemptOutput.slice(-80).map((item) => ({ channel: item.channel, text: safePreview(item.text, 500), method: item.method })), - currentAttemptEvents: result.events.slice(-60), + currentAttemptOutput: outputEvidence.items, + currentAttemptOutputOmitted: outputEvidence.omitted, + currentAttemptOutputTotalTextChars: outputEvidence.totalTextChars, + currentAttemptEvents: eventEvidence.events, + currentAttemptEventsOmitted: eventEvidence.omitted, }, policy: { complete: "仅当 transcript/最终回复证明当前任务确实完成,并且每个显式验收项都有证据时使用;队列 worker 随后会推进到下一个 queued 任务。", @@ -513,6 +607,102 @@ export function miniMaxJudgeMessages(userContent: string, repair: JudgeRepairCon return messages; } +class MiniMaxJudgeFailure extends Error { + readonly details: JudgeFailureDetails; + + constructor(details: JudgeFailureDetails) { + super(details.errorMessage); + this.name = "MiniMaxJudgeFailure"; + this.details = details; + } +} + +function errorName(error: unknown): string { + return error instanceof Error ? error.name || "Error" : typeof error; +} + +function errorMessage(error: unknown): string { + return error instanceof Error ? error.message : String(error); +} + +function minimaxFailureDetails(input: { + stage: JudgeFailureDetails["stage"]; + error: unknown; + startedAt: number; + finishedAt?: number; + timedOut?: boolean; + repairAttempt?: number; + maxRepairAttempts?: number; + promptChars?: number; + promptLines?: number; + payloadBytes?: number; + responseStatus?: number | null; + responseText?: string; + responseContent?: string; +}): JudgeFailureDetails { + const finishedAt = input.finishedAt ?? Date.now(); + return { + provider: "minimax", + stage: input.stage, + model: config().minimaxModel, + apiBase: config().minimaxApiBase, + occurredAt: new Date(finishedAt).toISOString(), + durationMs: Math.max(0, finishedAt - input.startedAt), + timeoutMs: config().judgeTimeoutMs, + timedOut: input.timedOut === true, + errorName: errorName(input.error), + errorMessage: errorMessage(input.error), + repairAttempt: input.repairAttempt, + maxRepairAttempts: input.maxRepairAttempts, + promptChars: input.promptChars, + promptLines: input.promptLines, + payloadBytes: input.payloadBytes, + responseStatus: input.responseStatus, + responseTextPreview: input.responseText === undefined ? undefined : safePreview(input.responseText, 1000), + responseTextChars: input.responseText?.length, + responseContentPreview: input.responseContent === undefined ? undefined : safePreview(input.responseContent, 1000), + responseContentChars: input.responseContent?.length, + }; +} + +function messagePromptStats(messages: Array<{ role: string; content: string }>): { promptChars: number; promptLines: number } { + return messages.reduce((stats, message) => { + const content = String(message.content || ""); + stats.promptChars += content.length; + stats.promptLines += promptLineCount(content); + return stats; + }, { promptChars: 0, promptLines: 0 }); +} + +export function judgeTaskInputDiagnostics(task: QueueTask, result: CodexRunResult, includePrompt = false): Record { + const judgePromptContent = judgePrompt(task, result); + const messages = miniMaxJudgeMessages(judgePromptContent, null); + const promptStats = messagePromptStats(messages); + const body = JSON.stringify({ + model: config().minimaxModel, + temperature: 0, + max_tokens: config().judgeMaxTokens, + messages, + }); + return { + provider: "minimax", + model: config().minimaxModel, + apiBase: config().minimaxApiBase, + configured: config().minimaxApiKey.length > 0, + timeoutMs: config().judgeTimeoutMs, + repairAttempts: config().judgeRepairAttempts, + maxTokens: config().judgeMaxTokens, + messageCount: messages.length, + judgePromptChars: judgePromptContent.length, + judgePromptLines: promptLineCount(judgePromptContent), + promptChars: promptStats.promptChars, + promptLines: promptStats.promptLines, + payloadBytes: encodedBytes(body), + promptPreview: safePreview(judgePromptContent, 1200), + ...(includePrompt ? { prompt: judgePromptContent } : {}), + }; +} + function judgeScopeText(task: QueueTask, result: CodexRunResult): string { return [ task.basePrompt, @@ -673,12 +863,13 @@ function applyJudgeSafetyOverrides(task: QueueTask, result: CodexRunResult, judg export async function judgeTask(task: QueueTask, result: CodexRunResult): Promise { if (config().minimaxApiKey.length === 0) return applyJudgeSafetyOverrides(task, result, fallbackJudge(result)); const judgePromptContent = judgePrompt(task, result); + const basePromptStats = { promptChars: judgePromptContent.length, promptLines: promptLineCount(judgePromptContent) }; try { let lastParseError: string | null = null; let repairContext: JudgeRepairContext | null = null; for (let repairAttempt = 0; repairAttempt <= config().judgeRepairAttempts; repairAttempt += 1) { const messages = miniMaxJudgeMessages(judgePromptContent, repairContext); - const response = await requestMiniMaxJudge(messages); + const response = await requestMiniMaxJudge(messages, repairAttempt); const preDenoiseContent = response.content; try { const parsedResult = parseJudgeJson(preDenoiseContent); @@ -695,12 +886,32 @@ export async function judgeTask(task: QueueTask, result: CodexRunResult): Promis reason: typeof parsed.reason === "string" ? parsed.reason : "MiniMax judge returned a decision.", continuePrompt, source: "minimax", - raw: { ...(parsed as Record), _parseSource: parsedResult.source, _repairAttempt: repairAttempt }, + raw: { + ...(parsed as Record), + _parseSource: parsedResult.source, + _repairAttempt: repairAttempt, + _request: response.diagnostics as unknown as JsonValue, + }, }; return applyJudgeSafetyOverrides(task, result, judge); } catch (error) { lastParseError = error instanceof Error ? error.message : String(error); - if (repairAttempt >= config().judgeRepairAttempts) throw new Error(lastParseError); + if (repairAttempt >= config().judgeRepairAttempts) { + throw new MiniMaxJudgeFailure(minimaxFailureDetails({ + stage: /continuePrompt exceeds source budget/iu.test(lastParseError) ? "validation" : "parse", + error: new Error(lastParseError), + startedAt: Date.now() - response.diagnostics.durationMs, + finishedAt: Date.now(), + repairAttempt, + maxRepairAttempts: config().judgeRepairAttempts, + promptChars: response.diagnostics.promptChars, + promptLines: response.diagnostics.promptLines, + payloadBytes: response.diagnostics.payloadBytes, + responseStatus: response.diagnostics.responseStatus, + responseText: response.rawText, + responseContent: preDenoiseContent, + })); + } logger("warn", "judge_json_parse_retry", { taskId: task.id, repairAttempt: repairAttempt + 1, @@ -713,29 +924,99 @@ export async function judgeTask(task: QueueTask, result: CodexRunResult): Promis } throw new Error(lastParseError ?? "MiniMax judge exhausted JSON repair attempts"); } catch (error) { - const message = error instanceof Error ? error.message : String(error); - logger("warn", "judge_failed_fallback", { taskId: task.id, error: message }); - return applyJudgeSafetyOverrides(task, result, fallbackJudge(result, message)); + const detail = error instanceof MiniMaxJudgeFailure + ? error.details + : minimaxFailureDetails({ stage: "unknown", error, startedAt: Date.now(), promptChars: basePromptStats.promptChars, promptLines: basePromptStats.promptLines }); + logger("warn", "judge_failed_fallback", { + taskId: task.id, + error: detail.errorMessage, + errorName: detail.errorName, + stage: detail.stage, + timedOut: detail.timedOut, + durationMs: detail.durationMs, + timeoutMs: detail.timeoutMs, + promptChars: detail.promptChars, + promptLines: detail.promptLines, + payloadBytes: detail.payloadBytes, + responseStatus: detail.responseStatus, + repairAttempt: detail.repairAttempt, + maxRepairAttempts: detail.maxRepairAttempts, + } as unknown as JsonValue); + return applyJudgeSafetyOverrides(task, result, fallbackJudge(result, detail)); } } -async function requestMiniMaxJudge(messages: Array<{ role: "system" | "user" | "assistant"; content: string }>): Promise { +async function requestMiniMaxJudge(messages: Array<{ role: "system" | "user" | "assistant"; content: string }>, repairAttempt: number): Promise { const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), config().judgeTimeoutMs); + let timedOut = false; + const startedAt = Date.now(); + const promptStats = messagePromptStats(messages); + const body = JSON.stringify({ + model: config().minimaxModel, + temperature: 0, + max_tokens: config().judgeMaxTokens, + messages, + }); + const payloadBytes = encodedBytes(body); + const timer = setTimeout(() => { + timedOut = true; + controller.abort(); + }, config().judgeTimeoutMs); try { - const response = await fetch(`${config().minimaxApiBase}/chat/completions`, { - method: "POST", - headers: { authorization: `Bearer ${config().minimaxApiKey}`, "content-type": "application/json" }, - body: JSON.stringify({ - model: config().minimaxModel, - temperature: 0, - max_tokens: config().judgeMaxTokens, - messages, - }), - signal: controller.signal, - }); - const rawText = await response.text(); - if (!response.ok) throw new Error(`MiniMax HTTP ${response.status}: ${safePreview(rawText, 1000)}`); + let response: Response; + try { + response = await fetch(`${config().minimaxApiBase}/chat/completions`, { + method: "POST", + headers: { authorization: `Bearer ${config().minimaxApiKey}`, "content-type": "application/json" }, + body, + signal: controller.signal, + }); + } catch (error) { + throw new MiniMaxJudgeFailure(minimaxFailureDetails({ + stage: "request", + error, + startedAt, + timedOut, + repairAttempt, + maxRepairAttempts: config().judgeRepairAttempts, + promptChars: promptStats.promptChars, + promptLines: promptStats.promptLines, + payloadBytes, + })); + } + let rawText: string; + try { + rawText = await response.text(); + } catch (error) { + throw new MiniMaxJudgeFailure(minimaxFailureDetails({ + stage: "request", + error, + startedAt, + timedOut, + repairAttempt, + maxRepairAttempts: config().judgeRepairAttempts, + promptChars: promptStats.promptChars, + promptLines: promptStats.promptLines, + payloadBytes, + responseStatus: response.status, + })); + } + const finishedAt = Date.now(); + if (!response.ok) { + throw new MiniMaxJudgeFailure(minimaxFailureDetails({ + stage: "http", + error: new Error(`MiniMax HTTP ${response.status}: ${safePreview(rawText, 1000)}`), + startedAt, + finishedAt, + repairAttempt, + maxRepairAttempts: config().judgeRepairAttempts, + promptChars: promptStats.promptChars, + promptLines: promptStats.promptLines, + payloadBytes, + responseStatus: response.status, + responseText: rawText, + })); + } let content = rawText; try { const payload = JSON.parse(rawText) as Record; @@ -749,7 +1030,23 @@ async function requestMiniMaxJudge(messages: Array<{ role: "system" | "user" | " } catch { content = rawText; } - return { rawText, content }; + return { + rawText, + content, + diagnostics: { + provider: "minimax", + model: config().minimaxModel, + apiBase: config().minimaxApiBase, + durationMs: finishedAt - startedAt, + timeoutMs: config().judgeTimeoutMs, + promptChars: promptStats.promptChars, + promptLines: promptStats.promptLines, + payloadBytes, + responseStatus: response.status, + responseTextChars: rawText.length, + responseContentChars: content.length, + }, + }; } finally { clearTimeout(timer); } diff --git a/src/components/microservices/code-queue/src/oa-events.ts b/src/components/microservices/code-queue/src/oa-events.ts index b8d5c1e4..c8e9d77a 100644 --- a/src/components/microservices/code-queue/src/oa-events.ts +++ b/src/components/microservices/code-queue/src/oa-events.ts @@ -184,6 +184,7 @@ function taskStatusPayload(task: QueueTask, queueId: string, reason: string, ste finishedAt: task.finishedAt, readAt: task.readAt, providerId: task.providerId, + executionMode: task.executionMode, model: task.model, currentAttempt: task.currentAttempt, stepCount, diff --git a/src/components/microservices/code-queue/src/provider-runtime.ts b/src/components/microservices/code-queue/src/provider-runtime.ts index 6d19111a..be0aa6fe 100644 --- a/src/components/microservices/code-queue/src/provider-runtime.ts +++ b/src/components/microservices/code-queue/src/provider-runtime.ts @@ -3,12 +3,12 @@ import { spawn } from "node:child_process"; import { existsSync, readFileSync } from "node:fs"; import { resolve } from "node:path"; -import { opencodeNpmPackage } from "./code-agent/common"; +import { codeExecutionModeInfo, opencodeNpmPackage } from "./code-agent/common"; import type { DevContainerCommandLog, DevContainerPlan, JsonValue, QueueTask, RuntimeConfig } from "./types"; export interface ProviderRuntimeContext { config: Pick; safePreview: (value: string, max?: number) => string; } @@ -73,10 +73,29 @@ function executionProviderOptions(): JsonValue[] { label: providerIsMain(providerId) ? `${providerId} (master)` : providerId, kind: providerIsMain(providerId) ? "local" : "remote-dev-container", defaultWorkdir: defaultWorkdirForProvider(providerId), + supportsWindowsNativeCodex: !providerIsMain(providerId), + windowsNativeDefaultWorkdir: providerIsMain(providerId) ? null : ctx().config.windowsNativeCodexDefaultWorkdir, containerName: providerIsMain(providerId) ? null : buildDevContainerPlan(providerId, {}).containerName, })); } +function executionModeOptions(): JsonValue[] { + return [ + { + ...codeExecutionModeInfo("default"), + id: "default", + defaultWorkdir: null, + }, + { + ...codeExecutionModeInfo("windows-native"), + id: "windows-native", + defaultWorkdir: ctx().config.windowsNativeCodexDefaultWorkdir, + bridgeDir: ctx().config.windowsNativeCodexBridgeDir, + connectHost: ctx().config.windowsNativeCodexConnectHost, + }, + ]; +} + function numericIdFromProvider(providerId: string): number { const digits = providerId.match(/\d+/u)?.[0] ?? ""; if (digits.length > 0) { @@ -457,6 +476,321 @@ CONTAINER=${shellQuote(plan.containerName)} docker exec "$CONTAINER" bash -lc 'export PATH=/tmp/unidesk-tools:$PATH; echo route=$(ip route show default | head -1); echo resolv=$(tr "\\n" " " ") + if not os.path.isdir(args.cwd): + raise SystemExit("windows-native Codex cwd does not exist: " + args.cwd) + + env = os.environ.copy() + home = os.path.expanduser("~") + env["PATH"] = os.path.join(home, ".local", "bin") + os.pathsep + env.get("PATH", "") + env["CODEX_INTERNAL_ORIGINATOR_OVERRIDE"] = "unidesk_code_queue_windows_native" + bridge_env_keys = [ + "OPENAI_API_KEY", + "CRS_OAI_KEY", + "OPENAI_BASE_URL", + "OPENAI_API_BASE", + "MINIMAX_API_KEY", + "MINIMAX_API_BASE", + "MINIMAX_MODEL", + "CODEX_INTERNAL_ORIGINATOR_OVERRIDE", + ] + existing_wsl_env = [item for item in env.get("WSLENV", "").split(":") if item] + existing_wsl_names = {item.split("/", 1)[0] for item in existing_wsl_env} + for key in bridge_env_keys: + if key in env and key not in existing_wsl_names: + existing_wsl_env.append(key) + env["WSLENV"] = ":".join(existing_wsl_env) + + child = subprocess.Popen( + ["win-cmd", args.codex_command], + cwd=args.cwd, + env=env, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + bufsize=0, + ) + + clients = set() + lock = threading.Lock() + last_empty_at = time.time() + ever_connected = False + stop_event = threading.Event() + + def log(message): + print(message, file=sys.stderr, flush=True) + + def close_client(conn): + try: + conn.close() + except OSError: + pass + with lock: + clients.discard(conn) + + def broadcast(data): + dead = [] + with lock: + snapshot = list(clients) + for conn in snapshot: + try: + conn.sendall(data) + except OSError: + dead.append(conn) + for conn in dead: + close_client(conn) + + def pump_stdout(): + with open(args.stdout_log, "ab", buffering=0) as log_file: + while True: + data = child.stdout.readline() if child.stdout is not None else b"" + if not data: + break + log_file.write(data) + broadcast(data) + stop_event.set() + with lock: + snapshot = list(clients) + for conn in snapshot: + close_client(conn) + + def pump_stderr(): + with open(args.stderr_log, "ab", buffering=0) as log_file: + while True: + data = child.stderr.readline() if child.stderr is not None else b"" + if not data: + break + log_file.write(data) + + threading.Thread(target=pump_stdout, daemon=True).start() + threading.Thread(target=pump_stderr, daemon=True).start() + + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server.bind((args.bind_host, args.port)) + server.listen(8) + server.settimeout(1) + port = server.getsockname()[1] + os.makedirs(os.path.dirname(args.port_file), exist_ok=True) + write_text(args.port_file, str(port)) + write_text(args.pid_file, str(os.getpid())) + log("windows_native_codex_bridge_ready session=%s pid=%s port=%s child=%s cwd=%s" % (args.session, os.getpid(), port, child.pid, args.cwd)) + + def handle_client(conn): + nonlocal last_empty_at + try: + while True: + data = conn.recv(65536) + if not data: + break + if child.stdin is not None: + child.stdin.write(data) + child.stdin.flush() + except (BrokenPipeError, OSError): + pass + finally: + close_client(conn) + with lock: + if len(clients) == 0: + last_empty_at = time.time() + + try: + while not stop_event.is_set(): + if child.poll() is not None: + break + with lock: + empty_for = time.time() - last_empty_at if len(clients) == 0 else 0 + no_client_yet = not ever_connected and len(clients) == 0 + if no_client_yet and empty_for >= args.initial_connect_timeout: + log("windows_native_codex_bridge_initial_connect_timeout session=%s seconds=%.1f" % (args.session, empty_for)) + break + if not no_client_yet and empty_for >= args.idle_timeout: + log("windows_native_codex_bridge_idle_timeout session=%s seconds=%.1f" % (args.session, empty_for)) + break + try: + conn, _addr = server.accept() + except socket.timeout: + continue + with lock: + clients.add(conn) + ever_connected = True + threading.Thread(target=handle_client, args=(conn,), daemon=True).start() + finally: + try: + server.close() + except OSError: + pass + if child.poll() is None: + child.terminate() + try: + child.wait(timeout=5) + except subprocess.TimeoutExpired: + child.kill() + try: + os.remove(args.port_file) + except OSError: + pass + log("windows_native_codex_bridge_exit session=%s childExit=%s" % (args.session, child.poll())) + + +if __name__ == "__main__": + main() +`; +} + +function windowsNativeContainerClientSource(): string { + return String.raw`const fs = require("node:fs"); +const dns = require("node:dns"); +const net = require("node:net"); +const { spawnSync } = require("node:child_process"); + +const host = process.env.UNIDESK_WINDOWS_NATIVE_CODEX_HOST || "host.docker.internal"; +const port = Number(process.env.UNIDESK_WINDOWS_NATIVE_CODEX_PORT); +const extraHosts = String(process.env.UNIDESK_WINDOWS_NATIVE_CODEX_EXTRA_HOSTS || "").split(/[,\s]+/u).filter(Boolean); +const connectDeadlineMs = Math.max(5000, Number(process.env.UNIDESK_WINDOWS_NATIVE_CODEX_CONNECT_TIMEOUT_MS || 60000)); +if (!Number.isInteger(port) || port <= 0) throw new Error("UNIDESK_WINDOWS_NATIVE_CODEX_PORT is invalid"); + +function gatewayFromHex(value) { + const bytes = value.match(/../g); + return bytes ? bytes.reverse().map((item) => Number.parseInt(item, 16)).join(".") : ""; +} + +function routeGateways() { + try { + return fs.readFileSync("/proc/net/route", "utf8").trim().split(/\n/u).slice(1).flatMap((line) => { + const parts = line.trim().split(/\s+/u); + if (parts.length < 3 || parts[0].startsWith("tun") || parts[2] === "00000000") return []; + const gateway = gatewayFromHex(parts[2]); + return gateway.length > 0 ? [{ iface: parts[0], gateway }] : []; + }); + } catch { + return []; + } +} + +function lookup4(name) { + return new Promise((resolve) => { + dns.lookup(name, { family: 4, all: true }, (error, addresses) => { + resolve(error ? [] : [...new Set(addresses.map((item) => item.address))]); + }); + }); +} + +function ensureHostRoutes(ips) { + const ipBin = fs.existsSync("/tmp/unidesk-tools/ip") ? "/tmp/unidesk-tools/ip" : "ip"; + for (const { iface, gateway } of routeGateways()) { + for (const ip of ips) { + spawnSync(ipBin, ["route", "replace", ip + "/32", "via", gateway, "dev", iface], { stdio: "ignore" }); + } + } +} + +function connectOnce(candidate) { + return new Promise((resolve, reject) => { + const socket = net.createConnection({ host: candidate, port }); + const timer = setTimeout(() => socket.destroy(new Error("connect timeout")), 2500); + socket.once("connect", () => { + clearTimeout(timer); + resolve(socket); + }); + socket.once("error", (error) => { + clearTimeout(timer); + reject(error); + }); + }); +} + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +async function connect() { + const hostIps = await lookup4(host); + ensureHostRoutes(hostIps); + const candidates = [...new Set([...hostIps, host, ...extraHosts, ...routeGateways().map((item) => item.gateway), "172.17.0.1"].filter(Boolean))]; + const errors = []; + const deadline = Date.now() + connectDeadlineMs; + let attempt = 0; + while (Date.now() < deadline) { + attempt += 1; + for (const candidate of candidates) { + try { + return await connectOnce(candidate); + } catch (error) { + errors.push(candidate + "=" + (error && error.message ? error.message : String(error))); + while (errors.length > 24) errors.shift(); + } + } + await sleep(500); + } + throw new Error("could not connect to Windows native Codex bridge after " + attempt + " attempts in " + connectDeadlineMs + "ms: " + errors.join("; ")); +} + +(async () => { + const socket = await connect(); + socket.setNoDelay(true); + socket.on("data", (chunk) => { + if (!process.stdout.write(chunk)) socket.pause(); + }); + process.stdout.on("drain", () => socket.resume()); + socket.on("end", () => process.exit(0)); + socket.on("close", () => process.exit(0)); + socket.on("error", (error) => { + console.error(error && error.stack ? error.stack : String(error)); + process.exit(1); + }); + process.stdin.on("data", (chunk) => { + if (!socket.write(chunk)) process.stdin.pause(); + }); + socket.on("drain", () => process.stdin.resume()); + process.stdin.on("end", () => socket.end()); +})().catch((error) => { + console.error(error && error.stack ? error.stack : String(error)); + process.exit(1); +});`; +} + +function windowsNativeBridgeInstallScript(): string { + const bridgeBase64 = base64Text(windowsNativeBridgeServerSource()); + return `mkdir -p ${shellQuote(ctx().config.windowsNativeCodexBridgeDir)} +printf %s ${shellQuote(bridgeBase64)} | base64 -d > ${shellQuote(resolve(ctx().config.windowsNativeCodexBridgeDir, "bridge.py"))} +chmod 700 ${shellQuote(resolve(ctx().config.windowsNativeCodexBridgeDir, "bridge.py"))}`; +} + function remoteCodexRuntimePrepareScript(plan: DevContainerPlan): string { return `set -euo pipefail CONTAINER=${shellQuote(plan.containerName)} @@ -500,12 +834,56 @@ function remoteAppServerCommand(task: QueueTask): string { return `docker exec -i ${shellQuote(plan.containerName)} bash -lc ${shellQuote(inner)}`; } +function windowsNativeSessionName(task: QueueTask): string { + return safeDockerName(`${task.id}-attempt-${task.currentAttempt || 0}`).slice(0, 120); +} + +function windowsNativeAppServerCommand(task: QueueTask): string { + const plan = buildDevContainerPlan(task.providerId, { workdir: remoteHostWorkdirForTask(task) }); + const session = windowsNativeSessionName(task); + const sessionDir = resolve(ctx().config.windowsNativeCodexBridgeDir, "sessions", session); + const portFile = resolve(sessionDir, "port"); + const pidFile = resolve(sessionDir, "pid"); + const stdoutLog = resolve(sessionDir, "codex.stdout.jsonl"); + const stderrLog = resolve(sessionDir, "codex.stderr.log"); + const serverLog = resolve(sessionDir, "bridge.log"); + const bridgePy = resolve(ctx().config.windowsNativeCodexBridgeDir, "bridge.py"); + const clientSource = windowsNativeContainerClientSource(); + const install = windowsNativeBridgeInstallScript(); + const idleSeconds = Math.max(30, Math.floor(ctx().config.windowsNativeCodexIdleTimeoutMs / 1000)); + const initialConnectSeconds = Math.max(45, Math.min(120, idleSeconds)); + return [ + "set -euo pipefail", + `export PATH="$HOME/.local/bin:$PATH"`, + `CWD=${shellQuote(task.cwd)}`, + `case "$CWD" in /mnt/*) ;; *) echo "windows-native executionMode requires cwd under /mnt/, got $CWD" >&2; exit 64 ;; esac`, + `test -d "$CWD" || { echo "windows-native cwd does not exist: $CWD" >&2; exit 64; }`, + install, + `SESSION_DIR=${shellQuote(sessionDir)}`, + `PORT_FILE=${shellQuote(portFile)}`, + `PID_FILE=${shellQuote(pidFile)}`, + `KEY_DIR=${shellQuote(plan.keyDir)}`, + `[ ! -r "$KEY_DIR/codex-env" ] || { set -a; . "$KEY_DIR/codex-env"; set +a; }`, + `mkdir -p "$SESSION_DIR"`, + `if [ -s "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" >/dev/null 2>&1 && [ -s "$PORT_FILE" ]; then :; else rm -f "$PORT_FILE" "$PID_FILE"; nohup python3 ${shellQuote(bridgePy)} --session ${shellQuote(session)} --cwd "$CWD" --codex-command ${shellQuote(ctx().config.windowsNativeCodexCommand)} --bind-host 0.0.0.0 --port 0 --port-file "$PORT_FILE" --pid-file "$PID_FILE" --idle-timeout ${shellQuote(String(idleSeconds))} --initial-connect-timeout ${shellQuote(String(initialConnectSeconds))} --stdout-log ${shellQuote(stdoutLog)} --stderr-log ${shellQuote(stderrLog)} > ${shellQuote(serverLog)} 2>&1 & fi`, + `for i in $(seq 1 120); do [ -s "$PORT_FILE" ] && break; sleep 0.25; done`, + `if [ ! -s "$PORT_FILE" ]; then echo "windows-native Codex bridge did not become ready; log follows:" >&2; tail -80 ${shellQuote(serverLog)} >&2 2>/dev/null || true; exit 65; fi`, + `PORT=$(cat "$PORT_FILE")`, + `WSL_HOSTS=$(hostname -I 2>/dev/null | tr ' ' ',' | sed 's/,,*/,/g; s/^,//; s/,$//')`, + `echo "windows_native_codex_stdio provider=${task.providerId} session=${session} container=${plan.containerName} port=$PORT cwd=$CWD" >&2`, + `CLIENT_SOURCE=${shellQuote(clientSource)}`, + `CLIENT_CMD='if command -v node >/dev/null 2>&1; then exec node -e "$UNIDESK_WINDOWS_NATIVE_CODEX_CLIENT_SOURCE"; fi; if command -v bun >/dev/null 2>&1; then exec bun -e "$UNIDESK_WINDOWS_NATIVE_CODEX_CLIENT_SOURCE"; fi; echo "windows-native relay container requires node or bun" >&2; exit 127'`, + `docker exec -i -e UNIDESK_WINDOWS_NATIVE_CODEX_HOST=${shellQuote(ctx().config.windowsNativeCodexConnectHost)} -e UNIDESK_WINDOWS_NATIVE_CODEX_PORT="$PORT" -e UNIDESK_WINDOWS_NATIVE_CODEX_EXTRA_HOSTS="$WSL_HOSTS" -e UNIDESK_WINDOWS_NATIVE_CODEX_CONNECT_TIMEOUT_MS=60000 -e UNIDESK_WINDOWS_NATIVE_CODEX_CLIENT_SOURCE="$CLIENT_SOURCE" ${shellQuote(plan.containerName)} bash -lc "$CLIENT_CMD"`, + ].join("; "); +} + export { buildDevContainerPlan, containerTunnelStartScript, defaultWorkdirForProvider, devContainerPingScript, + executionModeOptions, executionProviderOptions, masterKeyReadScript, masterKeySetupScript, @@ -525,4 +903,5 @@ export { runCodeQueueSsh, shellQuote, throwIfCommandFailed, + windowsNativeAppServerCommand, }; diff --git a/src/components/microservices/code-queue/src/queue-api.ts b/src/components/microservices/code-queue/src/queue-api.ts index b6b6a036..14534f8e 100644 --- a/src/components/microservices/code-queue/src/queue-api.ts +++ b/src/components/microservices/code-queue/src/queue-api.ts @@ -1,9 +1,9 @@ // 重构前 index.ts 只读参考:commit 6a04144d3f5103014f75b637d7e6bc2f45bf007f,blob 56e590c1a6b5ca7ad128bf2c992f60e46c355a58;可用 `git show 6a04144d3f5103014f75b637d7e6bc2f45bf007f:src/components/microservices/code-queue/src/index.ts` 查看。 import postgres from "postgres"; -import { codeAgentPortForModel, codeAgentPortInfo, codeModelPorts as codeModelPortsFor, opencodeModels as opencodeModelsFor } from "./code-agent/common"; +import { codeAgentPortForModel, codeAgentPortInfo, codeExecutionModeInfo, codeExecutionModes, codeModelPorts as codeModelPortsFor, opencodeModels as opencodeModelsFor } from "./code-agent/common"; import { claudeQqNotificationOutboxStats, notificationTargetConfigured, notificationTargetLabel } from "./notifications"; -import { executionProviderOptions } from "./provider-runtime"; +import { executionModeOptions, executionProviderOptions } from "./provider-runtime"; import { taskFullOutput } from "./task-output"; import { applyOaTraceStatsToTaskJson, taskScopeId, type OaTraceStats } from "./oa-events"; import { buildCompactTaskTranscript, buildTaskTranscript, cachedPreviewTranscript, fullTranscript, prefixPreview, safePreview, statsDaysFromUrl, taskForCompactMetaResponse, taskForMetaResponse, taskStatisticsSummary, taskTiming, timestampMs } from "./task-view"; @@ -12,7 +12,7 @@ import type { ActiveRun, ActiveRunSlotWaiter } from "./code-agent/common"; import type { JsonValue, QueueRecord, QueuedStatusReason, QueueTask, RuntimeConfig, TaskStatus, TranscriptLine } from "./types"; export interface QueueApiContext { - config: Pick; + config: Pick; activeRunSlotQueueIds: () => string[]; activeRunSlotWaiterSummaries: () => JsonValue[]; activeRuns: Map; @@ -186,6 +186,8 @@ function taskForListResponse(task: QueueTask, lite = false, queueTasks?: QueueTa truncated: task.referenceInjection.truncated, }, providerId: task.providerId, + executionMode: task.executionMode, + executionModeInfo: codeExecutionModeInfo(task.executionMode), cwd: task.cwd, model: task.model, agentPort: codeAgentPortForModel(task.model), @@ -240,6 +242,8 @@ function taskForListResponse(task: QueueTask, lite = false, queueTasks?: QueueTa referenceTaskIds: task.referenceTaskIds, referenceInjection: task.referenceInjection, providerId: task.providerId, + executionMode: task.executionMode, + executionModeInfo: codeExecutionModeInfo(task.executionMode), cwd: task.cwd, model: task.model, agentPort: codeAgentPortForModel(task.model), @@ -376,6 +380,8 @@ function queueSummary(includeDevReady = true, tasks: QueueTask[] = ctx().tasks() codexModels: ctx().config.codexModels, opencodeModels: opencodeModelsFor(ctx().config.codeModels), modelPorts: codeModelPortsFor(ctx().config.codeModels) as unknown as JsonValue, + executionModes: executionModeOptions(), + executionModeInfo: Object.fromEntries(codeExecutionModes.map((mode) => [mode, codeExecutionModeInfo(mode)])) as unknown as JsonValue, agentPorts: { codex: codeAgentPortInfo("codex"), opencode: codeAgentPortInfo("opencode"), @@ -386,6 +392,7 @@ function queueSummary(includeDevReady = true, tasks: QueueTask[] = ctx().tasks() mainProviderId: ctx().config.mainProviderId, defaultWorkdir: ctx().config.defaultWorkdir, remoteDefaultWorkdir: ctx().config.remoteDefaultWorkdir, + windowsNativeCodexDefaultWorkdir: ctx().config.windowsNativeCodexDefaultWorkdir, maxActiveQueues: ctx().config.maxActiveQueues, executionProviders: executionProviderOptions(), defaultWorkdirByProvider: Object.fromEntries((executionProviderOptions() as Array>).map((provider) => [String(provider.id), provider.defaultWorkdir ?? ctx().config.defaultWorkdir])) as JsonValue, @@ -586,6 +593,7 @@ function taskMatchesSearch(task: QueueTask, terms: string[]): boolean { queued.queuedReason?.code ?? "", queued.queuedReason?.message ?? "", task.providerId, + task.executionMode, task.cwd, task.model, task.reasoningEffort ?? "", diff --git a/src/components/microservices/code-queue/src/references.ts b/src/components/microservices/code-queue/src/references.ts index dd2229ca..23a5bde7 100644 --- a/src/components/microservices/code-queue/src/references.ts +++ b/src/components/microservices/code-queue/src/references.ts @@ -56,6 +56,7 @@ function referenceSummaryItem(task: QueueTask, round: number, roundIndex: number viaTaskId, status: task.status, providerId: task.providerId, + executionMode: task.executionMode, model: task.model, cwd: task.cwd, createdAt: task.createdAt, diff --git a/src/components/microservices/code-queue/src/self-tests.ts b/src/components/microservices/code-queue/src/self-tests.ts index faa8a837..bcc885e9 100644 --- a/src/components/microservices/code-queue/src/self-tests.ts +++ b/src/components/microservices/code-queue/src/self-tests.ts @@ -56,6 +56,7 @@ function testTask(id: string, prompt: string, finalResponse: string, referenceTa cwd: ctx().config.defaultWorkdir, model: ctx().config.defaultModel, reasoningEffort: ctx().resolveReasoningEffort(ctx().config.defaultModel, ctx().config.defaultReasoningEffort), + executionMode: "default", maxAttempts: 1, status: "succeeded", createdAt, @@ -344,6 +345,28 @@ function runTracePortSelfTest(): JsonValue { assertReferenceTest(String(edited.bodyPreview || "").includes("+const after = true;"), "opencode edit should use metadata diff for line diff display"); assertReferenceTest(!transcript.some((line) => line.status === "opencode/step-start" || line.status === "opencode/step-finish"), "opencode step boundaries should stay out of trace"); assertReferenceTest(!transcript.some((line) => String(line.bodyPreview || "").includes("hidden reasoning")), "reasoning-only opencode assistant text should not duplicate reasoning"); + + const codexTask = testTask("codex_5002_interleaved_command", "codex command prompt", "", [], "2026-05-12T00:02:00.000Z"); + codexTask.output = [ + { seq: 10, at: "2026-05-12T00:02:00.000Z", channel: "command", method: "item/started", itemId: "call_long", text: "item/started: /bin/bash -lc \"python3 - <<'PY'\\nprint('hello')\\nPY\" status=inProgress\n" }, + { seq: 11, at: "2026-05-12T00:02:01.000Z", channel: "command", method: "item/commandExecution/outputDelta", itemId: "call_long", text: "first line\n" }, + { seq: 12, at: "2026-05-12T00:02:02.000Z", channel: "system", method: "startup", text: "Service restarted while task was active; task queued for retry\n" }, + { seq: 13, at: "2026-05-12T00:02:03.000Z", channel: "command", method: "item/commandExecution/outputDelta", itemId: "call_long", text: "second line\n" }, + { seq: 14, at: "2026-05-12T00:02:04.000Z", channel: "command", method: "item/started", itemId: "call_other", text: "item/started: /bin/bash -lc \"git status --short\" status=inProgress\n" }, + { seq: 15, at: "2026-05-12T00:02:05.000Z", channel: "command", method: "item/completed", itemId: "call_other", text: "item/completed: /bin/bash -lc \"git status --short\" status=completed\n" }, + { seq: 16, at: "2026-05-12T00:02:06.000Z", channel: "command", method: "item/commandExecution/outputDelta", itemId: "call_long", text: "third line\n" }, + { seq: 17, at: "2026-05-12T00:02:07.000Z", channel: "command", method: "item/completed", itemId: "call_long", text: "item/completed: /bin/bash -lc \"python3 - <<'PY'\\nprint('hello')\\nPY\" status=completed\n" }, + ]; + const codexTranscript = buildTaskTranscript(codexTask, 20, 0); + const longCommandLines = codexTranscript.filter((line) => line.rawSeqs.includes(11) || line.rawSeqs.includes(13) || line.rawSeqs.includes(16)); + assertReferenceTest(longCommandLines.length === 1, "interleaved command output deltas should stay in one trace command line"); + const longCommand = longCommandLines[0]; + if (longCommand === undefined) throw new Error("interleaved command trace line missing"); + assertReferenceTest(longCommand.kind === "ran", "interleaved shell command should be a ran trace line"); + assertReferenceTest(String(longCommand.commandPreview || "").includes("python3 - <<"), "interleaved command trace line should retain command preview"); + assertReferenceTest(["first line", "second line", "third line"].every((part) => String(longCommand.bodyPreview || "").includes(part)), "interleaved command trace line should aggregate all output chunks"); + assertReferenceTest(transcriptLineSummaryLines(longCommand).some((line) => line.includes("$ python3 - <<")), "interleaved command summary should expose the command before expansion"); + const remoteTask = testTask("codex_5001_remote_opencode", "remote command prompt", "", [], "2026-05-12T00:01:00.000Z"); remoteTask.providerId = "D601"; remoteTask.cwd = "/home/ubuntu"; @@ -363,6 +386,8 @@ function runTracePortSelfTest(): JsonValue { { name: "partial_opencode_tool_to_explored", ok: true, title: partial?.title ?? null }, { name: "step_boundaries_filtered", ok: true }, { name: "reasoning_duplicate_filtered", ok: true }, + { name: "interleaved_command_output_single_trace_line", ok: true, rawSeqs: longCommand?.rawSeqs ?? [] }, + { name: "interleaved_command_summary_has_command", ok: true, summaryLines: longCommand ? transcriptLineSummaryLines(longCommand) : [] }, { name: "duration_preserved", ok: true, durationMs: explored?.durationMs ?? null }, { name: "remote_opencode_exec_includes_binary", ok: true }, { name: "opencode_exit0_final_without_step_finish_is_terminal", ok: true }, diff --git a/src/components/microservices/code-queue/src/task-output.ts b/src/components/microservices/code-queue/src/task-output.ts index 8aaa2c6d..ca78c026 100644 --- a/src/components/microservices/code-queue/src/task-output.ts +++ b/src/components/microservices/code-queue/src/task-output.ts @@ -16,7 +16,13 @@ export interface TaskOutputContext { } const outputArchiveSeededTasks = new Set(); -const archivedOutputCache = new Map(); +const archivedOutputCache = new Map(); +const archivedOutputCacheMaxEntries = 16; +const archivedOutputCacheMaxBytes = 32 * 1024 * 1024; +const archivedOutputCacheMaxSingleBytes = 8 * 1024 * 1024; +const outputGcByteInterval = 8 * 1024 * 1024; +let archivedOutputCacheBytes = 0; +let outputBytesSinceGc = 0; let context: TaskOutputContext | null = null; export function configureTaskOutput(runtimeContext: TaskOutputContext): void { @@ -58,14 +64,60 @@ function ensureTaskOutputArchiveSeeded(task: QueueTask): void { function appendOutputArchive(task: QueueTask, output: LiveOutput, op: ArchivedLiveOutput["op"], text: string): void { try { - archivedOutputCache.delete(task.id); + deleteArchivedOutputCache(task.id); mkdirSync(ctx().config.outputArchiveDir, { recursive: true }); appendFileSync(taskOutputArchivePath(task.id), serializeArchivedOutput(output, op, text), "utf8"); + maybeCollectGarbageAfterOutput(text.length); } catch (error) { ctx().logger("error", "codex_output_archive_write_failed", { taskId: task.id, error: ctx().errorToJson(error) }); } } +function estimateCachedOutputBytes(output: LiveOutput[]): number { + return output.reduce((total, item) => total + String(item.text || "").length * 2 + 256, 0); +} + +function deleteArchivedOutputCache(taskId: string): void { + const cached = archivedOutputCache.get(taskId); + if (cached !== undefined) { + archivedOutputCacheBytes = Math.max(0, archivedOutputCacheBytes - cached.bytes); + archivedOutputCache.delete(taskId); + } +} + +function pruneArchivedOutputCache(requiredBytes = 0): void { + while ( + archivedOutputCache.size > archivedOutputCacheMaxEntries + || archivedOutputCacheBytes + requiredBytes > archivedOutputCacheMaxBytes + ) { + const firstKey = archivedOutputCache.keys().next().value; + if (typeof firstKey !== "string") break; + deleteArchivedOutputCache(firstKey); + } +} + +function setArchivedOutputCache(taskId: string, signature: string, output: LiveOutput[]): void { + const bytes = estimateCachedOutputBytes(output); + if (bytes > archivedOutputCacheMaxSingleBytes) return; + deleteArchivedOutputCache(taskId); + pruneArchivedOutputCache(bytes); + if (bytes > archivedOutputCacheMaxBytes) return; + archivedOutputCache.set(taskId, { signature, output, bytes }); + archivedOutputCacheBytes += bytes; + pruneArchivedOutputCache(); +} + +function maybeCollectGarbageAfterOutput(textBytes: number): void { + outputBytesSinceGc += Math.max(0, textBytes); + if (outputBytesSinceGc < outputGcByteInterval) return; + outputBytesSinceGc = 0; + try { + (Bun as unknown as { gc?: (force?: boolean) => void }).gc?.(false); + } catch (error) { + ctx().logger("debug", "codex_output_gc_failed", { error: ctx().errorToJson(error) }); + } +} + function archiveRecordToOutput(value: unknown): ArchivedLiveOutput | null { if (typeof value !== "object" || value === null || Array.isArray(value)) return null; const record = value as Record; @@ -114,11 +166,7 @@ function archivedTaskOutput(task: QueueTask): LiveOutput[] { return []; } const output = Array.from(bySeq.values()).sort((left, right) => Number(left.seq) - Number(right.seq)); - archivedOutputCache.set(task.id, { signature, output }); - while (archivedOutputCache.size > 80) { - const firstKey = archivedOutputCache.keys().next().value; - if (typeof firstKey === "string") archivedOutputCache.delete(firstKey); - } + setArchivedOutputCache(task.id, signature, output); return output; } diff --git a/src/components/microservices/code-queue/src/task-view.ts b/src/components/microservices/code-queue/src/task-view.ts index 866f7fd6..7b58afe4 100644 --- a/src/components/microservices/code-queue/src/task-view.ts +++ b/src/components/microservices/code-queue/src/task-view.ts @@ -18,7 +18,7 @@ import type { TranscriptKind, TranscriptLine, } from "./types"; -import { codeAgentPortForModel, codeAgentPortInfo, extractRecord } from "./code-agent/common"; +import { codeAgentPortForModel, codeAgentPortInfo, codeExecutionModeInfo, extractRecord } from "./code-agent/common"; import { currentTaskPromptMarker, resolvedReferenceContextTitle, stripCodeQueueEnvironmentHint, userPromptForDisplay } from "./prompts"; import { outputArchiveSignature, taskFullOutput } from "./task-output"; import { retryPrompt } from "./judge"; @@ -948,25 +948,53 @@ function buildTaskTranscript(task: QueueTask, limit = 180, rawOutputWindow = 0, const promptHistoryLines = promptHistoryTranscriptLines(task, fullText); const promptHistorySeqs = new Set(promptHistoryLines.map((line) => line.seq)); entries.push(...promptHistoryLines); - let activeCommand: { seq: number; at: string; command: string; status?: string; body: string; rawSeqs: number[]; itemId?: string } | null = null; + type ActiveCommand = { seq: number; at: string; command: string; status?: string; body: string; rawSeqs: number[]; itemId?: string }; + let activeCommand: ActiveCommand | null = null; + const activeCommandsByItemId = new Map(); - const flushCommand = (): void => { - if (activeCommand === null) return; - const kind = commandKind(activeCommand.command); - const output = activeCommand.itemId === undefined ? null : commandOutputs.get(activeCommand.itemId) ?? null; - const body = activeCommand.body.length > 0 ? activeCommand.body : formatCommandOutput(output); + const pushRawSeq = (command: ActiveCommand, seq: number): void => { + if (!command.rawSeqs.includes(seq)) command.rawSeqs.push(seq); + }; + + const flushCommand = (command: ActiveCommand | null = activeCommand): void => { + if (command === null) return; + const kind = commandKind(command.command); + const output = command.itemId === undefined ? null : commandOutputs.get(command.itemId) ?? null; + const body = command.body.length > 0 ? command.body : formatCommandOutput(output); + const title = command.command.trim().length > 0 ? shortCommandTitle(command.command) : "Command output"; entries.push(addCommandOutputStreams(transcriptLine( kind, - activeCommand.at, - activeCommand.seq, - shortCommandTitle(activeCommand.command), - activeCommand.rawSeqs, + command.at, + command.seq, + title, + command.rawSeqs, body, - activeCommand.command, - activeCommand.status, + command.command, + command.status, fullText, ), output, fullText)); - activeCommand = null; + if (command === activeCommand) activeCommand = null; + if (command.itemId !== undefined && activeCommandsByItemId.get(command.itemId) === command) { + activeCommandsByItemId.delete(command.itemId); + } + }; + + const itemIdCommand = (item: LiveOutput, parsed: { command: string; status?: string } | null = null): ActiveCommand | null => { + if (typeof item.itemId !== "string" || item.itemId.length === 0) return null; + let command = activeCommandsByItemId.get(item.itemId); + if (command === undefined) { + command = { + seq: item.seq, + at: item.at, + command: parsed?.command ?? "", + status: parsed?.status, + body: "", + rawSeqs: [], + itemId: item.itemId, + }; + activeCommandsByItemId.set(item.itemId, command); + } + return command; }; const outputSource = rawOutputWindow > 0 ? task.output : taskFullOutput(task); @@ -984,8 +1012,18 @@ function buildTaskTranscript(task: QueueTask, limit = 180, rawOutputWindow = 0, if (item.channel === "user" && item.method === "turn/steer" && promptHistorySeqs.has(item.seq)) continue; if (isOpenCodeStepBoundaryMethod(item.method)) continue; if (item.channel === "command" && item.method === "item/started") { - flushCommand(); const parsed = parseCommandLine(item.text); + const groupedCommand = itemIdCommand(item, parsed); + if (groupedCommand !== null) { + flushCommand(); + groupedCommand.seq = item.seq; + groupedCommand.at = item.at; + groupedCommand.command = parsed?.command || item.text; + groupedCommand.status = parsed?.status; + pushRawSeq(groupedCommand, item.seq); + continue; + } + flushCommand(); activeCommand = { seq: item.seq, at: item.at, @@ -998,9 +1036,13 @@ function buildTaskTranscript(task: QueueTask, limit = 180, rawOutputWindow = 0, continue; } if (item.channel === "command" && item.method === "item/commandExecution/outputDelta") { - if (activeCommand !== null) { + const groupedCommand = itemIdCommand(item); + if (groupedCommand !== null) { + groupedCommand.body += item.text; + pushRawSeq(groupedCommand, item.seq); + } else if (activeCommand !== null) { activeCommand.body += item.text; - activeCommand.rawSeqs.push(item.seq); + pushRawSeq(activeCommand, item.seq); } else { const output = typeof item.itemId === "string" ? commandOutputs.get(item.itemId) ?? null : null; entries.push(addCommandOutputStreams(transcriptLine("ran", item.at, item.seq, "Command output", [item.seq], item.text || formatCommandOutput(output), "", undefined, fullText), output, fullText)); @@ -1009,9 +1051,15 @@ function buildTaskTranscript(task: QueueTask, limit = 180, rawOutputWindow = 0, } if (item.channel === "command" && item.method === "item/completed") { const parsed = parseCommandLine(item.text); - if (activeCommand !== null) { + const groupedCommand = itemIdCommand(item, parsed); + if (groupedCommand !== null) { + if (parsed?.command) groupedCommand.command = parsed.command; + groupedCommand.status = parsed?.status ?? groupedCommand.status; + pushRawSeq(groupedCommand, item.seq); + flushCommand(groupedCommand); + } else if (activeCommand !== null) { activeCommand.status = parsed?.status ?? activeCommand.status; - activeCommand.rawSeqs.push(item.seq); + pushRawSeq(activeCommand, item.seq); flushCommand(); } else { const command = parsed?.command || item.text; @@ -1049,73 +1097,14 @@ function buildTaskTranscript(task: QueueTask, limit = 180, rawOutputWindow = 0, } } flushCommand(); + for (const command of Array.from(activeCommandsByItemId.values()).sort((left, right) => left.seq - right.seq)) { + flushCommand(command); + } return boundedTranscript(entries, limit); } -function compactTaskTranscriptLine(item: LiveOutput, title: string, kind: TranscriptKind): TranscriptLine { - return { - seq: item.seq, - at: item.at, - kind, - title, - status: item.method, - bodyPreview: prefixPreview(item.text.replace(/\u001b\[[0-9;]*m/gu, ""), 900), - rawSeqs: [item.seq], - }; -} - function buildCompactTaskTranscript(task: QueueTask, limit = 12, rawOutputWindow = 24): TranscriptLine[] { - const entries: TranscriptLine[] = []; - for (const item of task.promptHistory.slice(-2)) { - entries.push({ - seq: item.seq, - at: item.at, - kind: "message", - title: "Steer prompt", - status: item.method, - bodyPreview: prefixPreview(item.text, 900), - rawSeqs: [item.seq], - }); - } - const outputItems = task.output.slice(-rawOutputWindow); - const fileChangeInputs = outputItems.some((item) => item.channel === "diff" && item.method === "item/fileChange/outputDelta" && typeof item.itemId === "string") - ? codexSessionFileChangesByCallId(task) - : new Map(); - for (const item of outputItems) { - if (item.channel === "user" && item.method === "enqueue") continue; - if (isOpenCodeStepBoundaryMethod(item.method)) continue; - if (item.channel === "command") { - const isOutput = item.method === "item/commandExecution/outputDelta"; - entries.push({ - seq: item.seq, - at: item.at, - kind: isOutput ? "ran" : item.method === "item/started" ? "ran" : "system", - title: isOutput ? "Command output" : item.method === "item/started" ? "Command started" : "Command completed", - status: item.method, - commandPreview: isOutput ? undefined : prefixPreview(item.text, 900), - bodyPreview: isOutput ? prefixPreview(item.text, 900) : undefined, - rawSeqs: [item.seq], - }); - } else if (item.channel === "diff") { - entries.push(compactTaskTranscriptLine({ ...item, text: fileChangeTextWithInlinePatch(item, fileChangeInputs) }, "Edited files", "edited")); - } else if (item.channel === "error") { - entries.push(compactTaskTranscriptLine(item, "Error", "error")); - } else if (item.channel === "assistant" || item.channel === "reasoning" || item.channel === "user") { - const body = item.channel === "assistant" && String(item.method || "").startsWith("opencode/") ? openCodeVisibleAssistantText(item.text) : item.text; - if (body.length > 0) entries.push(compactTaskTranscriptLine({ ...item, text: body }, item.channel === "assistant" ? "Assistant message" : item.channel === "reasoning" ? "Reasoning" : "User prompt", "message")); - } else if (item.channel === "tool" && String(item.method || "").startsWith("opencode/")) { - const line = openCodeToolTranscriptLine(item, false); - entries.push(line ?? compactTaskTranscriptLine(item, "OpenCode tool", "system")); - } else { - const title = item.method === "judge" - ? "Judge result" - : item.method === "startup" || item.method === "shutdown" - ? "Recovered thread execution" - : "System"; - entries.push(compactTaskTranscriptLine(item, title, "system")); - } - } - return boundedTranscript(entries, limit); + return buildTaskTranscript(task, limit, rawOutputWindow, false); } function transcriptSignature(task: QueueTask): string { @@ -1269,6 +1258,8 @@ function taskForMetaResponse(task: QueueTask): JsonValue { referenceTaskIds: task.referenceTaskIds, referenceInjection: task.referenceInjection, providerId: task.providerId, + executionMode: task.executionMode, + executionModeInfo: codeExecutionModeInfo(task.executionMode), cwd: task.cwd, model: task.model, agentPort: codeAgentPortForModel(task.model), @@ -1337,6 +1328,8 @@ function taskForCompactMetaResponse(task: QueueTask): JsonValue { truncated: task.referenceInjection.truncated, }, providerId: task.providerId, + executionMode: task.executionMode, + executionModeInfo: codeExecutionModeInfo(task.executionMode), cwd: task.cwd, model: task.model, agentPort: codeAgentPortForModel(task.model), @@ -1578,11 +1571,37 @@ function parseJudgeLine(text: string): JudgeResult | null { if (match === null) return null; const confidence = Number(match[2]); const source = match[3] === "minimax" ? "minimax" : "fallback"; + const rawReason = (match[4] ?? "").trim(); + const detailsMatch = /\bMiniMax failure details:\s+([\s\S]*)$/u.exec(rawReason); + const detailsText = detailsMatch?.[1] ?? ""; + const detailValue = (key: string): string | null => new RegExp(`\\b${key}=([^\\s]+)`, "u").exec(detailsText)?.[1] ?? null; + const detailNumber = (key: string): number | undefined => { + const value = Number(detailValue(key)); + return Number.isFinite(value) ? value : undefined; + }; + const errorMessage = /\berror=([\s\S]*)$/u.exec(detailsText)?.[1]?.trim() ?? ""; + const failureDetails = detailsText.length === 0 ? null : { + provider: "minimax" as const, + stage: (detailValue("stage") || "unknown") as JudgeResult["failureDetails"] extends infer T ? T extends { stage: infer S } ? S : never : never, + model: "", + apiBase: "", + occurredAt: "", + durationMs: detailNumber("durationMs") ?? 0, + timeoutMs: detailNumber("timeoutMs") ?? 0, + timedOut: detailValue("timedOut") === "true", + errorName: detailValue("errorName") || "", + errorMessage, + promptChars: detailNumber("promptChars"), + promptLines: detailNumber("promptLines"), + payloadBytes: detailNumber("payloadBytes"), + responseStatus: detailNumber("responseStatus") ?? null, + }; return { decision: match[1] as JudgeDecision, confidence: Number.isFinite(confidence) ? confidence : 0, source, - reason: (match[4] ?? "").trim(), + reason: detailsMatch === null ? rawReason : rawReason.slice(0, detailsMatch.index).trim(), + failureDetails, }; } @@ -1680,6 +1699,23 @@ function isRecoveredThreadLine(line: TranscriptLine): boolean { ); } +function traceSystemLineIsError(line: TranscriptLine): boolean { + const text = [ + line.title, + line.status, + line.bodyPreview, + line.commandPreview, + line.stderrPreview, + line.stdoutPreview, + ].map((value) => String(value || "")).join("\n"); + return /\b(error|failed|failure|interrupt|interrupted|cancell?ed|watchdog|timeout|closed|refused|aborted|exception)\b/iu.test(text); +} + +function traceLineVisibleInTraceView(line: TranscriptLine): boolean { + if (line.title === "Submitted prompt") return false; + return line.kind !== "system" || traceSystemLineIsError(line); +} + function mergeTraceWindowLines(left: TranscriptLine[], right: TranscriptLine[]): TranscriptLine[] { const seen = new Set(); const merged: TranscriptLine[] = []; @@ -1990,6 +2026,8 @@ function taskTraceSummaryResponse(task: QueueTask, oaTraceStats: JsonValue | nul queueId: ctx().queueIdOf(task), status: task.status, providerId: task.providerId, + executionMode: task.executionMode, + executionModeInfo: codeExecutionModeInfo(task.executionMode), model: task.model, agentPort: codeAgentPortForModel(task.model), agentPortInfo: codeAgentPortInfo(codeAgentPortForModel(task.model)), @@ -2083,7 +2121,7 @@ function taskTraceStepsResponse(task: QueueTask, url: URL): Response { const previewTranscript = cachedPreviewTranscript(task); const attemptWindow = attemptIndex === null ? null : traceAttemptWindows(task, previewTranscript).find((window) => window.index === attemptIndex) ?? null; const sourceTranscript = attemptWindow === null ? previewTranscript : executionLinesForAttempt(attemptWindow.lines); - const transcript = sourceTranscript.filter((line) => line.title !== "Submitted prompt"); + const transcript = sourceTranscript.filter(traceLineVisibleInTraceView); const page = ctx().pageBySeq(transcript, url, limit); return ctx().jsonResponse({ ok: true, @@ -2121,7 +2159,7 @@ function taskTraceStepDetailResponse(task: QueueTask, url: URL): Response { const seq = Number(url.searchParams.get("seq")); if (!Number.isFinite(seq)) return ctx().jsonResponse({ ok: false, error: "seq is required" }, 400); const agentPort = codeAgentPortForModel(task.model); - const transcript = fullTranscript(task).filter((line) => line.title !== "Submitted prompt"); + const transcript = fullTranscript(task).filter(traceLineVisibleInTraceView); const line = transcript.find((item) => Number(item.seq) === seq || item.rawSeqs.includes(seq)); if (line === undefined) return ctx().jsonResponse({ ok: false, error: "trace step not found", seq }, 404); return ctx().jsonResponse({ @@ -2145,6 +2183,8 @@ function taskSummaryResponse(task: QueueTask, url: URL): JsonValue { queueId: ctx().queueIdOf(task), status: task.status, providerId: task.providerId, + executionMode: task.executionMode, + executionModeInfo: codeExecutionModeInfo(task.executionMode), model: task.model, agentPort: codeAgentPortForModel(task.model), agentPortInfo: codeAgentPortInfo(codeAgentPortForModel(task.model)), diff --git a/src/components/microservices/code-queue/src/types.ts b/src/components/microservices/code-queue/src/types.ts index cf08ff6f..512f6350 100644 --- a/src/components/microservices/code-queue/src/types.ts +++ b/src/components/microservices/code-queue/src/types.ts @@ -20,6 +20,8 @@ export type RunMode = "initial" | "retry"; export type JudgeDecision = "complete" | "retry" | "fail"; +export type CodeExecutionMode = "default" | "windows-native"; + export type OutputChannel = "system" | "user" | "assistant" | "reasoning" | "command" | "diff" | "tool" | "error"; export type TerminalStatus = "completed" | "interrupted" | "failed" | null; @@ -81,6 +83,11 @@ export interface RuntimeConfig { devContainerDefaultProviderId: string; devContainerImage: string; devContainerWorkdir: string; + windowsNativeCodexBridgeDir: string; + windowsNativeCodexCommand: string; + windowsNativeCodexConnectHost: string; + windowsNativeCodexDefaultWorkdir: string; + windowsNativeCodexIdleTimeoutMs: number; } export interface QueueTaskRequest { @@ -90,6 +97,7 @@ export interface QueueTaskRequest { cwd?: string; model?: string; reasoningEffort?: string; + executionMode?: CodeExecutionMode; maxAttempts?: number; referenceTaskIds?: string[]; basePrompt?: string; @@ -145,11 +153,14 @@ export interface AttemptSummary { mode: RunMode; startedAt: string; finishedAt: string; + providerId?: string; + executionMode?: CodeExecutionMode; terminalStatus: TerminalStatus; transportClosedBeforeTerminal: boolean; appServerExitCode: number | null; appServerSignal: string | null; error: string | null; + events?: CodexEventSummary[]; inputPrompt?: string; inputPromptPreview?: string; inputPromptChars?: number; @@ -178,9 +189,33 @@ export interface JudgeResult { reason: string; continuePrompt?: string; source: "minimax" | "fallback"; + failureDetails?: JudgeFailureDetails | null; raw?: JsonValue; } +export interface JudgeFailureDetails { + provider: "minimax"; + stage: "request" | "http" | "parse" | "validation" | "unknown"; + model: string; + apiBase: string; + occurredAt: string; + durationMs: number; + timeoutMs: number; + timedOut: boolean; + errorName: string; + errorMessage: string; + repairAttempt?: number; + maxRepairAttempts?: number; + promptChars?: number; + promptLines?: number; + payloadBytes?: number; + responseStatus?: number | null; + responseTextPreview?: string; + responseTextChars?: number; + responseContentPreview?: string; + responseContentChars?: number; +} + export interface FeedbackPromptRecord { text: string; preview: string; @@ -199,6 +234,19 @@ export interface ParsedJudgeJson { export interface MiniMaxJudgeResponse { rawText: string; content: string; + diagnostics: { + provider: "minimax"; + model: string; + apiBase: string; + durationMs: number; + timeoutMs: number; + promptChars: number; + promptLines: number; + payloadBytes: number; + responseStatus: number; + responseTextChars: number; + responseContentChars: number; + }; } export interface ReferenceInjectionSummaryItem { @@ -208,6 +256,7 @@ export interface ReferenceInjectionSummaryItem { viaTaskId: string | null; status: TaskStatus; providerId: string; + executionMode?: CodeExecutionMode; model: string; cwd: string; createdAt: string; @@ -250,6 +299,7 @@ export interface QueueTask { cwd: string; model: string; reasoningEffort: string | null; + executionMode: CodeExecutionMode; maxAttempts: number; status: TaskStatus; createdAt: string; diff --git a/src/components/microservices/oa-event-flow/src/index.ts b/src/components/microservices/oa-event-flow/src/index.ts index 565a55ae..663a0694 100644 --- a/src/components/microservices/oa-event-flow/src/index.ts +++ b/src/components/microservices/oa-event-flow/src/index.ts @@ -643,13 +643,13 @@ async function applyTraceSnapshot(executor: SqlExecutor, event: OaEventRecord, s subject_kind = EXCLUDED.subject_kind, subject_id = EXCLUDED.subject_id, stats_revision = oa_trace_stats.stats_revision + 1, - step_count = GREATEST(oa_trace_stats.step_count, EXCLUDED.step_count), - llm_step_count = GREATEST(oa_trace_stats.llm_step_count, EXCLUDED.llm_step_count), - read_count = GREATEST(oa_trace_stats.read_count, EXCLUDED.read_count), - edit_count = GREATEST(oa_trace_stats.edit_count, EXCLUDED.edit_count), - run_count = GREATEST(oa_trace_stats.run_count, EXCLUDED.run_count), - error_count = GREATEST(oa_trace_stats.error_count, EXCLUDED.error_count), - trace_line_count = GREATEST(oa_trace_stats.trace_line_count, EXCLUDED.trace_line_count), + step_count = EXCLUDED.step_count, + llm_step_count = EXCLUDED.llm_step_count, + read_count = EXCLUDED.read_count, + edit_count = EXCLUDED.edit_count, + run_count = EXCLUDED.run_count, + error_count = EXCLUDED.error_count, + trace_line_count = EXCLUDED.trace_line_count, output_max_seq = GREATEST(oa_trace_stats.output_max_seq, EXCLUDED.output_max_seq), attempt_stats_json = EXCLUDED.attempt_stats_json, last_event_sequence = GREATEST(COALESCE(oa_trace_stats.last_event_sequence, 0), EXCLUDED.last_event_sequence), @@ -688,7 +688,7 @@ async function applyTraceStep(executor: SqlExecutor, event: OaEventRecord, scope error_count: string | number; }[]>` SELECT - COUNT(*) AS step_count, + COUNT(*) FILTER (WHERE kind <> 'system') AS step_count, COUNT(*) FILTER (WHERE kind = 'read') AS read_count, COUNT(*) FILTER (WHERE kind = 'edit') AS edit_count, COUNT(*) FILTER (WHERE kind = 'run') AS run_count, @@ -718,13 +718,13 @@ async function applyTraceStep(executor: SqlExecutor, event: OaEventRecord, scope subject_kind = EXCLUDED.subject_kind, subject_id = EXCLUDED.subject_id, stats_revision = oa_trace_stats.stats_revision + 1, - step_count = GREATEST(oa_trace_stats.step_count, EXCLUDED.step_count), - llm_step_count = GREATEST(oa_trace_stats.llm_step_count, EXCLUDED.llm_step_count), - read_count = GREATEST(oa_trace_stats.read_count, EXCLUDED.read_count), - edit_count = GREATEST(oa_trace_stats.edit_count, EXCLUDED.edit_count), - run_count = GREATEST(oa_trace_stats.run_count, EXCLUDED.run_count), - error_count = GREATEST(oa_trace_stats.error_count, EXCLUDED.error_count), - trace_line_count = GREATEST(oa_trace_stats.trace_line_count, EXCLUDED.trace_line_count), + step_count = EXCLUDED.step_count, + llm_step_count = EXCLUDED.llm_step_count, + read_count = EXCLUDED.read_count, + edit_count = EXCLUDED.edit_count, + run_count = EXCLUDED.run_count, + error_count = EXCLUDED.error_count, + trace_line_count = EXCLUDED.trace_line_count, output_max_seq = GREATEST(oa_trace_stats.output_max_seq, EXCLUDED.output_max_seq), attempt_stats_json = oa_trace_stats.attempt_stats_json, last_event_sequence = GREATEST(COALESCE(oa_trace_stats.last_event_sequence, 0), EXCLUDED.last_event_sequence),